https://github.com/rspivak/sftpserver


윈도우에서도 잘 돌아감


c:\Python27\Scripts>sftpserver.exe -k id_rsa.key -l DEBUG


#-*- encoding: utf-8 -*-

import paramiko
pkey = paramiko.RSAKey.from_private_key_file('c:\Python27\Scripts\id_rsa.key')
transport = paramiko.Transport(('localhost'3373))
transport.connect(username='admin'password='admin')
sftp = paramiko.SFTPClient.from_transport(transport)
print sftp.listdir('.')
"""
output:
['loop.py', 'stub_sftp.py', 'sftpserver-script.py']
"""
""" download """
sftp.get('sftpserver-script.py''sftpserver-script.py')


https://github.com/rspivak/sftpserver/blob/master/src/sftpserver/stub_sftp.py

class StubServer (ServerInterface):

    def check_auth_password(self, username, password):

        # all are allowed

        return AUTH_SUCCESSFUL


위 check_auth_password 함수에 pyotp 적용하면 보안상 좋을듯....

https://github.com/pyotp/pyotp


python_window_daemon.py

#-*- encoding: utf-8 -*-
# Now works in python 3 aswell as 2

import sys, threading, time, os, datetime, time, inspect, subprocess, socket
from subprocess import PIPE, STDOUT
from wsgiref.simple_server import make_server

class Webshite():

    def __init__(self):
        self.hostname = socket.getfqdn()
        self.header = """
        <html>
        <header>
        <style>
        body {
            background-color:#6C7A89;
        }
        p {
            color:white;
            font-family:Consolas;
        }
        </style>
        </header>
        <body>
        """
        self.shite = "<p>"+str(self.hostname)+"</p>"

        self.footer = """
        </body>
        </html>
        """

    def grains(selfenvironstart_response):
        self.environ = environ
        self.start = start_response
        status = '200 OK'
        response_headers = [('Content-type','text/html; charset=utf-8')]
        self.start(status, response_headers)
        fullsite = self.header + self.shite + self.footer
        fullsite = [fullsite.encode('utf-8')] # in python 3, this needed to be a list, and encoded
        return fullsite

    def run(self):
        srv = make_server('127.0.0.1'8080self.grains)

        while True:
            try:
                threading.Thread(target=srv.handle_request()).start()
            except KeyboardInterrupt:
                exit()



# ------------------ terrible daemon code for windows -------------------
if __name__ == '__main__':
    webshite = Webshite()

    Windows = sys.platform == 'win32'
    ProcessFileName = os.path.realpath(__file__)
    pidName = ProcessFileName.split('\\')[-1].replace('.py','')

    if Windows:
        pidFile = 'c:\\Windows\\Temp\\'+pidName+'.pid'
    else:
        pidFile = '/tmp'+pidName+'.pid'


    def start(pidfilepidname):
        """ Create process file, and save process ID of detached process """
        pid = ""
        if Windows:
            #start child process in detached state
            DETACHED_PROCESS = 0x00000008
            p = subprocess.Popen([sys.executable, ProcessFileName, "child"],
                                    creationflags=DETACHED_PROCESS)
            pid = p.pid

        else:
            p = subprocess.Popen([sys.executable, ProcessFileName, "child"],
                                    stdout = PIPE, stderr = PIPE)
            pid = p.pid


        print("Service", pidname, pid, "started")
        # create processfile to signify process has started
        with open(pidfile, 'w'as f:
            f.write(str(pid))
        f.close()
        os._exit(0)


    def stop(pidfilepidname):
        """ Kill the process and delete the process file """
        procID = ""
        try:
            with open(pidfile, "r"as f:
                procID = f.readline()
            f.close()
        except IOError:
            print("process file does not exist, but that's ok <3 I still love you")

        if procID:
            if Windows:
                try:
                    killprocess = subprocess.Popen(['taskkill.exe','/PID',procID,'/F'],
                                                        stdout = PIPE, stderr = PIPE)
                    killoutput = killprocess.communicate()

                except Exception as e:
                    print(e)
                    print ("could not kill ",procID)
                else:
                    print("Service", pidname, procID, "stopped")

            else:
                try:
                    subprocess.Popen(['kill','-SIGTERM',procID])
                except Exception as e:
                    print(e)
                    print("could not kill "+procID)
                else:
                    print("Service "+procID + " stopped")

            #remove the pid file to signify the process has ended
            os.remove(pidfile)

    if len(sys.argv) == 2:

        if sys.argv[1] == "start":

            if os.path.isfile(pidFile) == False:
                start(pidFile, pidName)
            else:
                print("process is already started")

        elif sys.argv[1] == "stop":

            if os.path.isfile(pidFile) == True:
                stop(pidFile, pidName)
            else:
                print("process is already stopped")

        elif sys.argv[1] == "restart":
                stop(pidFile, pidName)
                start(pidFile, pidName)

        # This is only run on windows in the detached child process
        elif sys.argv[1] == "child":
            webshite.run()
    else:
        print("usage: python "+pidName+".py start|stop|restart")

#kill main
os._exit(0)


'Python' 카테고리의 다른 글

rrdmod  (0) 2017.02.03
Django + djangorestframework + django_rest_swagger 시작  (0) 2017.02.01
Pika Python AMQP Client Library  (0) 2017.01.31
s3 example  (0) 2016.12.28
daemonizing  (0) 2016.12.22

rrd로 트래픽수집을 하다보면 아래 그림처럼 갑자기 트래픽이 튀는 경우가 발생한다.



위와 같은 문제가 발생하면 rrd 디비를 dump -> 데이터수정 -> restore 를 해줘야 하는데 


상당히 귀찮은 작업이다.


그래서 스크립트 하나 만들어 봄...


1. rrd 파일을 xml 로 dump 를 받고

2. Param 으로 받은 시간대의 데이터를 0.0000000000e+00 으로 수정

3. 수정된 xml 로 restore 를 진행한다.


tip:

dump 이후에 수집된 데이터는 누락이 되는 문제가 있어 

dump 전/후 lastupdate 시간이 다를경우에 dump 후에 수집된 raw 데이터를 구하여 

update를 진행합니다. 


[root@new test]# /usr/local/python2.6/bin/python rrdmod.py -h

rrdmod.py [options]

Options:

-t, --time=<timestamp>   time format %Y%m%d%H or %Y%m%d

-f, --file=<filename>    rrd file name


코드는 아직 정리 전이라 보기에 좀 불편하겠지만 수정하여 다시 업데이트 할예정임...


import sys

import subprocess

import getopt

import datetime

import time

import re

import os


def get_rrd_lastinfo(rrd_file):

    last_time, last_input, last_output = None, None, None


    p = subprocess.Popen(

            ('rrdtool', 'lastupdate', rrd_file), stdout=subprocess.PIPE)

    out, err = p.communicate()

    for s in out.split("\n"):

        m = re.search(r"(\d+): (\d+) (\d+)", s)

        if m:

            last_time, last_input, last_output = m.groups()


    return last_time, last_input, last_output


def get_rrd_update_value(rrd_file, start_time, end_time, input, output):

    values = []

    p = subprocess.Popen(

        ('rrdtool', 'fetch', rrd_file, 'AVERAGE', '-s', start_time, '-e', end_time), stdout=subprocess.PIPE)

    out, err = p.communicate()

    for s in out.split("\n"):

        m = re.search(r"(\d+): ([\.e\+\-\d]+) ([\.e\+\-\d]+)", s)

        if m:

            last_time, last_input, last_output = m.groups()

            last_input = int(eval(last_input)*300)

            last_output = int(eval(last_output)*300)

            values.append((last_time,last_input, last_output))


    values.reverse()

    input = float(input)

    output = float(output)


    for n, v in enumerate(values):

        input -= v[1]

        output -= v[2]

        v = v + ("%d" % input,)

        v = v + ("%d" % output,)

        values[n] = v


    values.reverse()

    for v in values:

        print v

        subprocess.Popen(

            ('rrdtool', 'update', rrd_file, '%s:%s:%s' % (v[0], v[3], v[4])), stdout=subprocess.PIPE).communicate()


def modrrd(mod_time, rrd_file):

    """

    <!-- 2017-02-02 15:00:00 KST / 1486015200 --> <row><v>NaN</v><v>NaN</v></row>

    """

    pattern = re.compile(r" %s\s?[:\d]+ \w+ / (\d+) --> <row><v>(.*)</v><v>(.*)</v></row>" % mod_time)

    init_value = "0.0000000000e+00"


    last_update_time = get_rrd_lastinfo(rrd_file)[0]


    p1 = subprocess.Popen(

            ('rrdtool', 'dump', rrd_file), stdout=subprocess.PIPE)


    if os.path.exists('%s.new.rrd' % rrd_file):

        os.unlink('%s.new.rrd' % rrd_file)


    fp = open("%s.xml" % rrd_file, "a+")

    for num, line in enumerate(p1.stdout):

        matching = pattern.search(line)

        if matching:

            if len(matching.groups()) == 3:

                line = line.replace(matching.groups()[1], init_value).replace(matching.groups()[2], init_value)


        fp.write(line)

    fp.close()


    p2 = subprocess.Popen(

            ('rrdtool', 'restore', "%s.xml" % rrd_file, '%s.new.rrd' % rrd_file), stdout=subprocess.PIPE)


    out, err = p2.communicate()


    if os.path.exists("%s.xml" % rrd_file):

        os.unlink("%s.xml" % rrd_file)


    _last_update_time, _last_input, _last_output = get_rrd_lastinfo(rrd_file)


    if last_update_time != _last_update_time:

        get_rrd_update_value(rrd_file, last_update_time, _last_update_time, _last_input, _last_output)


def usage():

    print 'rrdmod.py [options]'

    print 'Options:'

    print '-t, --time=<timestamp>   time format %Y%m%d%H or %Y%m%d'

    print '-f, --file=<filename>    rrd file name'


def main():

    mod_time, rrd_file = None, None

    try:

        opts, args = getopt.getopt(sys.argv[1:],"ht:f:",["time=","file="])

    except getopt.GetoptError:

        usage()

        sys.exit(2)


    for opt, value in opts:

        if opt in ("-t", "--time"):

            mod_time = value

            if len(mod_time) == 10:

                mod_time = datetime.datetime.strptime(mod_time, '%Y%m%d%H')

                mod_time = mod_time.strftime("%Y-%m-%d %H")

            elif len(mod_time) == 8:

                mod_time = datetime.datetime.strptime(mod_time, '%Y%m%d')

                mod_time = mod_time.strftime("%Y-%m-%d")

            else:

                usage()

                sys.exit(2)


            # make timestamp

            #mod_time = time.mktime(mod_time.timetuple())


        elif opt in ("-f", "--file"):

             rrd_file = value

        elif opt == "-h":

            usage()

            sys.exit()


    if mod_time == None or rrd_file == None:

        usage()

        sys.exit()


    modrrd(mod_time, rrd_file)


if __name__ == "__main__":

    main()

'Python' 카테고리의 다른 글

sftpserver + pyotp  (0) 2017.03.08
Django + djangorestframework + django_rest_swagger 시작  (0) 2017.02.01
Pika Python AMQP Client Library  (0) 2017.01.31
s3 example  (0) 2016.12.28
daemonizing  (0) 2016.12.22

테스트환경

CentOS release 6.8 (Final)

Python 3.4.6

Django-1.10.5

djangorestframework-3.5.3

django_rest_swagger-2.1.1

MariaDB-server-10.0.29

pipenv-3.2.11


1. CentOS release 6.8 (Final)

    1-1. centos 6.8 minimal 설치

    1-2. Development tools 설치

    ]# yum update

    ]# yum groupinstall 'Development tools'


2. Python 3.4.6

    2-1. Python 3.4.6 설치

    ]# wget https://www.python.org/ftp/python/3.4.6/Python-3.4.6.tgz

    ]# tar zxf Python-3.4.6.tgz

    ]# cd Python-3.4.6

    ]# ./configure --prefix=/usr/local/python3.4 --enable-shared

    ]# make

    ]# make install

    ]# echo "/usr/local/python3.4/lib" >> /etc/ld.so.conf.d/python3.4.conf

    ]# ldconfig

    ]# /usr/local/python3.4/bin/pip3 install pipenv

    ]# ln -s /usr/local/python3.4/bin/python3 /usr/local/bin/

    ]# ln -s /usr/local/python3.4/bin/python3.4 /usr/local/bin/

    ]# ln -s /usr/local/python3.4/bin/pip3 /usr/local/bin/

    ]# ln -s /usr/local/python3.4/bin/pip3.4 /usr/local/bin/

    ]# ln -s /usr/local/python3.4/bin/pipenv /usr/local/bin/

    ]# ln -s /usr/local/python3.4/bin/virtualenv /usr/local/bin/

    

    Tip: https://www.python.org/dev/peps/pep-0513/#ucs-2-vs-ucs-4-builds

          --enable-unicode=ucs4 옵션은 CPython 2.x, 3.0 ~ 3.2 까지만 사용한다.


3. MariaDB-server-10.0.29

    3-1. MariaDB-server-10.0.29 설치

    ]# vi /etc/yum.repos.d/MariaDB.repo

    [mariadb]

    name = MariaDB

    baseurl = http://yum.mariadb.org/10.0/centos6-amd64

    gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB

    gpgcheck=1

    

    ]# yum install MariaDB-server MariaDB-client MariaDB-devel

    ]# /etc/rc.d/init.d/mysqld start

    ]# mysql -u root

    MariaDB [(none)]> CREATE DATABASE test_django CHARACTER SET UTF8;

    MariaDB [(none)]> CREATE USER django@localhost IDENTIFIED BY '비밀번호';

    MariaDB [(none)]> CREATE USER django@127.0.0.1 IDENTIFIED BY '비밀번호';

    MariaDB [(none)]> GRANT ALL PRIVILEGES ON test_django.* TO django@localhost;

    MariaDB [(none)]> GRANT ALL PRIVILEGES ON test_django.* TO django@127.0.0.1;

    MariaDB [(none)]> FLUSH PRIVILEGES;


4. Django-1.10.5, djangorestframework-3.5.3, django_rest_swagger-2.1.1, mysqlclient-1.3.9

    4-1. Django, djangorestframework, django_rest_swagger, mysqlclient 설치

    ]# mkdir /home/test-django

    ]# cd /home/test-django

    ]# pipenv install mysqlclient django djangorestframework django-rest-swagger

    

5. djangorestframework tutorial 시작

]# pipenv shell

(test-django) ]# django-admin startproject test_api

(test-django) ]# cd test_api

(test-django) ]# vi test_api/settings.py


"""

ALLOWED_HOST 수정

DATABASE 수정

"""

- ALLOWED_HOSTS = []

+ ALLOWED_HOSTS = ['*']


- DATABASES = {

-    'default': {

-        'ENGINE': 'django.db.backends.sqlite3',

-        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),

-    }

- }


+ DATABASES = {

+    'default': {

+        'ENGINE': 'django.db.backends.mysql',

+        'NAME': 'test_django',

+        'USER': 'django',

+        'PASSWORD': '비밀번호',

+        'HOST': 'localhost',   # Or an IP Address that your DB is hosted on

+        'PORT': '3306',

+        'OPTIONS': {

+            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",

+        },

+    }

}

 


""" migrate 수행 """

(test-django) ]# ./manage.py migrate


""" admin 계정 생성 """

(test-django) ]# ./manage.py createsuperuse


""" app 추가 """

(test-django) ]# ./manage.py startapp v1


""" Post 모델 작성 """

(test-django) ]# vi v1/models.py

from django.db import models

class Post(models.Model):
   title = models.CharField(max_length=200)
   content = models.TextField()
   created_at = models.DateTimeField(auto_now_add=True)
   updated_at = models.DateTimeField(auto_now=True)

   def __str__(self):
       return "{}: {}".format(self.pk, self.title)


""" INSTALLED_APPS 에 v1, rest_framework, rest_framework_swagger 추가 """

(test-django) ]# vi test_api/settings.py

INSTALLED_APPS.append('v1')
INSTALLED_APPS.append('rest_framework')
INSTALLED_APPS.append('rest_framework_swagger')


""" v1 App의 Post 모델 생성 """

(test-django) ]# ./manage.py makemigrations v1

(test-django) ]# ./manage.py migrate v1



""" admin 페이지에서 Post 관리할 수 있도록 추가 """

(test-django) ]# vi v1/admin.py

from django.contrib import admin
from .models import *

admin.site.register(Post)


""" serializers 클래스 생성 """

(test-django) ]# vi v1/serializers.py

from rest_framework import serializers
from .models import *

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = '__all__'


""" viewset 클래스 생성 """

(test-django) ]# vi v1/views.py

from django.shortcuts import render from .models import * from .serializers import * from rest_framework import viewsets class PostViewSet(viewsets.ModelViewSet): queryset = Post.objects.all() serializer_class = PostSerializer


""" app urls 생성 및 project urls 에 추가 """

(test-django) ]# vi v1/urls.py

from django.conf.urls import include, url from .views import * from rest_framework import routers from rest_framework_swagger.views import get_swagger_view router = routers.DefaultRouter() router.register(r'post', <PostViewSet) schema_view = get_swagger_view(title='TEST API') urlpatterns = [ url(r'^', include(router.urls)),

url(r'^swagger', schema_view) , ]


from django.conf.urls import include, url

from .views import *

from rest_framework import routers

from rest_framework_swagger.views import get_swagger_view


router = routers.DefaultRouter()

router.register(r'post', PostViewSet)


schema_view = get_swagger_view(title='TEST API')


urlpatterns = [

    url(r'^', include(router.urls)),

    url(r'^swagger', schema_view),

]

 


(test-django) ]# vi test_api/urls.py

"""test_api URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [url(r'^admin/', admin.site.urls),url(r'^v1/', include('v1.urls')),]


from django.conf.urls import include, url

from django.contrib import admin


urlpatterns = [

    url(r'^admin/', admin.site.urls),

    url(r'^v1/', include('v1.urls')),

]

 


""" 실행 """

(test-django) ]# ./manage.py runserver 0.0.0.0:80


""" 웹브라우져로 접속 및 테스트 """



 


기본적인 예제를 테스트 해보았고 공식 tutorial 사이트를 방문해서 단계별로 테스트를 진행해야한다...

http://www.django-rest-framework.org/#tutorial

'Python' 카테고리의 다른 글

sftpserver + pyotp  (0) 2017.03.08
rrdmod  (0) 2017.02.03
Pika Python AMQP Client Library  (0) 2017.01.31
s3 example  (0) 2016.12.28
daemonizing  (0) 2016.12.22

+ Recent posts