Преглед на файлове

加入日志处理及日志获取功能

James Iter преди 9 години
родител
ревизия
0488d28cff
променени са 17 файла, в които са добавени 416 реда и са изтрити 35 реда
  1. 6 0
      README.md
  2. 30 0
      main.py
  3. 14 1
      misc/init.sql
  4. 5 1
      models/__init__.py
  5. 7 4
      models/guest_xml.py
  6. 83 0
      models/log.py
  7. 10 0
      models/status.py
  8. 20 2
      models/utils.py
  9. 9 3
      route_table.py
  10. 2 2
      tests/test_os_init.py
  11. 1 1
      tests/test_os_init_write.py
  12. 2 2
      tests/test_os_template.py
  13. 2 1
      views/guest.py
  14. 188 0
      views/log.py
  15. 12 6
      views/os_init.py
  16. 13 6
      views/os_init_write.py
  17. 12 6
      views/os_template.py

+ 6 - 0
README.md

@@ -11,6 +11,12 @@
 
 ## 未来计划
 >
+* 增加计费功能
+* 增加过期资源自动回收机制
+* 增加模板上传功能
+* 日志处理机制
+* 用户管理功能
+* 参照gitlab,打包出 CentOS yum 一语安装仓库
 * 加入移动端的支持;
 
 

+ 30 - 0
main.py

@@ -5,14 +5,25 @@
 import traceback
 import thread
 
+import signal
+
+import time
+
+from models import Utils
 from models.initialize import app, logger
 import route_table
 from models import Database as db
+from models import Log
 from views.os_init import blueprint as os_init_blueprint
+from views.os_init import blueprints as os_init_blueprints
 from views.os_init_write import blueprint as os_init_write_blueprint
+from views.os_init_write import blueprints as os_init_write_blueprints
 from views.os_template import blueprint as os_template_blueprint
+from views.os_template import blueprints as os_template_blueprints
 from views.guest import blueprint as guest_blueprint
 from views.config import blueprint as config_blueprint
+from views.log import blueprint as log_blueprint
+from views.log import blueprints as log_blueprints
 
 
 __author__ = 'James Iter'
@@ -28,16 +39,35 @@ try:
     db.init_conn_redis()
 
     app.register_blueprint(os_init_blueprint)
+    app.register_blueprint(os_init_blueprints)
     app.register_blueprint(os_init_write_blueprint)
+    app.register_blueprint(os_init_write_blueprints)
     app.register_blueprint(os_template_blueprint)
+    app.register_blueprint(os_template_blueprints)
     app.register_blueprint(guest_blueprint)
     app.register_blueprint(config_blueprint)
+    app.register_blueprint(log_blueprint)
+    app.register_blueprint(log_blueprints)
 except:
     logger.error(traceback.format_exc())
 
 if __name__ == '__main__':
     # noinspection PyBroadException
     try:
+        signal.signal(signal.SIGTERM, Utils.signal_handle)
+        signal.signal(signal.SIGINT, Utils.signal_handle)
+
+        thread.start_new_thread(Log.launch, ())
+        Utils.thread_counter += 1
+
         app.run(host=app.config['jimv_listen'], port=app.config['jimv_port'], use_reloader=False, threaded=True)
+
+        while Utils.thread_counter > 0:
+            time.sleep(1)
+
+        print 'Main say bye-bye!'
+
     except:
         logger.error(traceback.format_exc())
+        exit(-1)
+

+ 14 - 1
misc/init.sql

@@ -1,4 +1,4 @@
-DROP DATABASE IF EXISTS jimv;
+# DROP DATABASE IF EXISTS jimv;
 CREATE DATABASE IF NOT EXISTS jimv CHARACTER SET utf8;
 USE jimv;
 
@@ -89,3 +89,16 @@ CREATE TABLE IF NOT EXISTS config(
     PRIMARY KEY (id))
     ENGINE=InnoDB
     DEFAULT CHARSET=utf8;
+
+CREATE TABLE IF NOT EXISTS log(
+    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
+    type TINYINT UNSIGNED NOT NULL,
+    timestamp BIGINT UNSIGNED NOT NULL,
+    host CHAR(15),
+    message VARCHAR(255) NOT NULL DEFAULT '',
+    PRIMARY KEY (id))
+    ENGINE=Innodb
+    DEFAULT CHARSET=utf8;
+
+ALTER TABLE log ADD INDEX (host);
+

+ 5 - 1
models/__init__.py

@@ -51,6 +51,10 @@ from status import (
     GuestStatus
 )
 
+from log import (
+    Log
+)
+
 
 __author__ = 'James Iter'
 __date__ = '2017/3/21'
@@ -60,6 +64,6 @@ __copyright__ = '(c) 2017 by James Iter.'
 
 __all__ = [
     'Rules', 'Utils', 'Init', 'Database', 'FilterFieldType', 'Filter', 'GuestStatus', 'ORM', 'Config',
-    'Guest', 'GuestDisk', 'OSInit', 'OSInitWrite', 'OSTemplate', 'GuestXML'
+    'Guest', 'GuestDisk', 'OSInit', 'OSInitWrite', 'OSTemplate', 'GuestXML', 'Log'
 ]
 

+ 7 - 4
models/guest_xml.py

@@ -61,8 +61,7 @@ class GuestXML(object):
         self.config = config
 
     def get_domain(self):
-        return """
-            <?xml version="1.0" encoding="utf-8"?>
+        return """<?xml version="1.0" encoding="utf-8"?>
             <domain type="kvm">
             {0}
             {1}
@@ -70,9 +69,10 @@ class GuestXML(object):
             {3}
             {4}
             {5}
+            {6}
             </domain>
-        """.format(self.get_features(), self.get_name(), self.get_vcpu(), self.get_memory(), self.get_os(),
-                   self.get_devices())
+        """.format(self.get_features(), self.get_name(), self.get_uuid(), self.get_vcpu(), self.get_memory(),
+                   self.get_os(), self.get_devices())
 
     @staticmethod
     def get_features():
@@ -86,6 +86,9 @@ class GuestXML(object):
     def get_name(self):
         return """<name>{0}</name>""".format(self.guest.name)
 
+    def get_uuid(self):
+        return """<uuid>{0}</uuid>""".format(self.guest.uuid)
+
     def get_vcpu(self):
         return """<vcpu>{0}</vcpu>""".format(self.guest.cpu.__str__())
 

+ 83 - 0
models/log.py

@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+import json
+import jimit as ji
+import time
+
+from models import Database as db
+from models import FilterFieldType
+from models import ORM
+from models import Utils
+from models.initialize import app, logger
+
+
+__author__ = 'James Iter'
+__date__ = '2017/4/8'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2017 by James Iter.'
+
+
+class Log(ORM):
+
+    _table_name = 'log'
+    _primary_key = 'id'
+
+    def __init__(self, **kwargs):
+        super(Log, self).__init__()
+        self.id = 0
+        self.type = kwargs.get('type', None)
+        self.timestamp = kwargs.get('timestamp', 0)
+        self.host = kwargs.get('host', None)
+        self.message = kwargs.get('message', None)
+
+    def set(self, **kwargs):
+        self.type = kwargs.get('type', None)
+        self.timestamp = kwargs.get('timestamp', 0)
+        self.host = kwargs.get('host', None)
+        self.message = kwargs.get('message', None)
+
+    @staticmethod
+    def get_filter_keywords():
+        return {
+            'type': FilterFieldType.INT.value,
+            'timestamp': FilterFieldType.INT.value,
+            'host': FilterFieldType.STR.value
+        }
+
+    @staticmethod
+    def get_allow_update_keywords():
+        return []
+
+    @staticmethod
+    def get_allow_content_search_keywords():
+        return ['host']
+
+    @classmethod
+    def launch(cls):
+
+        log = Log()
+
+        while True:
+            if Utils.exit_flag:
+                Utils.thread_counter -= 1
+                print 'Thread say bye-bye'
+                return
+
+            try:
+                host_log = db.r.lpop(app.config['host_event_report_queue'])
+
+                if host_log is None:
+                    time.sleep(1)
+                    continue
+
+                host_log = json.loads(host_log)
+                log.set(type=host_log['type'], timestamp=host_log['timestamp'], host=host_log['host'],
+                        message=host_log['message'])
+
+                log.create()
+
+            except Exception as e:
+                logger.error(e.message)
+

+ 10 - 0
models/status.py

@@ -16,4 +16,14 @@ class GuestStatus(IntEnum):
     booting = 1
     running = 2
     rebooting = 3
+    suspend = 4
+    resuming = 5
+
+
+class LogLevel(IntEnum):
+    critical = 0
+    error = 1
+    warn = 2
+    info = 3
+    debug = 4
 

+ 20 - 2
models/utils.py

@@ -3,6 +3,7 @@
 
 from functools import wraps
 
+import commands
 from flask import make_response, g, request
 from flask.wrappers import Response
 from werkzeug.utils import import_string, cached_property
@@ -12,13 +13,30 @@ from models.initialize import *
 
 
 __author__ = 'James Iter'
-__date__ = '16/06/08'
+__date__ = '2017/03/01'
 __contact__ = 'james.iter.cn@gmail.com'
-__copyright__ = '(c) 2016 by James Iter.'
+__copyright__ = '(c) 2017 by James Iter.'
 
 
 class Utils(object):
 
+    exit_flag = False
+    thread_counter = 0
+
+    @staticmethod
+    def shell_cmd(cmd):
+        try:
+            exit_status, output = commands.getstatusoutput(cmd)
+
+            return exit_status, str(output)
+
+        except Exception as e:
+            return -1, e.message
+
+    @classmethod
+    def signal_handle(cls, signum=0, frame=None):
+        cls.exit_flag = True
+
     @staticmethod
     def dumps2response(func):
         """

+ 9 - 3
route_table.py

@@ -8,6 +8,7 @@ from views import guest
 from views import os_init
 from views import os_init_write
 from views import os_template
+from views import log
 
 
 __author__ = 'James Iter'
@@ -26,20 +27,25 @@ add_rule(config.blueprint, '', view_func='config.r_get', methods=['GET'])
 add_rule(os_init.blueprint, '', view_func='os_init.r_create', methods=['POST'])
 add_rule(os_init.blueprint, '/<_id>', view_func='os_init.r_update', methods=['PATCH'])
 add_rule(os_init.blueprint, '/<_id>', view_func='os_init.r_delete', methods=['DELETE'])
-add_rule(os_init.blueprint, '', view_func='os_init.r_get_by_filter', methods=['GET'])
+add_rule(os_init.blueprints, '', view_func='os_init.r_get_by_filter', methods=['GET'])
 
 add_rule(os_init_write.blueprint, '', view_func='os_init_write.r_create', methods=['POST'])
 add_rule(os_init_write.blueprint, '/<_id>', view_func='os_init_write.r_update', methods=['PATCH'])
 add_rule(os_init_write.blueprint, '/<_id>', view_func='os_init_write.r_delete', methods=['DELETE'])
-add_rule(os_init_write.blueprint, '', view_func='os_init_write.r_get_by_filter', methods=['GET'])
+add_rule(os_init_write.blueprints, '', view_func='os_init_write.r_get_by_filter', methods=['GET'])
 
 # 系统模板操作
 add_rule(os_template.blueprint, '', view_func='os_template.r_create', methods=['POST'])
 add_rule(os_template.blueprint, '/<_id>', view_func='os_template.r_update', methods=['PATCH'])
 add_rule(os_template.blueprint, '/<_id>', view_func='os_template.r_delete', methods=['DELETE'])
-add_rule(os_template.blueprint, '', view_func='os_template.r_get_by_filter', methods=['GET'])
+add_rule(os_template.blueprints, '', view_func='os_template.r_get_by_filter', methods=['GET'])
 
 # Guest操作
 # 创建虚拟机
 add_rule(guest.blueprint, '', view_func='guest.r_create', methods=['POST'])
 
+# 日志查询
+# 系统模板操作
+add_rule(log.blueprints, '', view_func='log.r_get_by_filter', methods=['GET'])
+add_rule(log.blueprints, '/_search', view_func='log.r_content_search', methods=['GET'])
+

+ 2 - 2
tests/test_os_init.py

@@ -40,7 +40,7 @@ class TestOSInit(unittest.TestCase):
 
     # 获取系统初始化组列表
     def test_12_get(self):
-        url = TestOSInit.base_url + '/os_init'
+        url = TestOSInit.base_url + '/os_inits'
         headers = {'content-type': 'application/json'}
         r = requests.get(url, headers=headers)
         j_r = json.loads(r.content)
@@ -63,7 +63,7 @@ class TestOSInit(unittest.TestCase):
 
     # 校验系统初始化组列表更新结果
     def test_14_get(self):
-        url = TestOSInit.base_url + '/os_init'
+        url = TestOSInit.base_url + '/os_inits'
         headers = {'content-type': 'application/json'}
         r = requests.get(url, headers=headers)
         j_r = json.loads(r.content)

+ 1 - 1
tests/test_os_init_write.py

@@ -117,7 +117,7 @@ class TestOSInitWrite(unittest.TestCase):
         self.assertEqual('40901', j_r['state']['sub']['code'])
 
     def test_25_get(self):
-        url = TestOSInitWrite.base_url + '/os_init_write'
+        url = TestOSInitWrite.base_url + '/os_init_writes'
         headers = {'content-type': 'application/json'}
         r = requests.get(url, headers=headers)
         j_r = json.loads(r.content)

+ 2 - 2
tests/test_os_template.py

@@ -42,7 +42,7 @@ class TestOSTemplate(unittest.TestCase):
 
     # 获取系统模板列表
     def test_12_get(self):
-        url = TestOSTemplate.base_url + '/os_template'
+        url = TestOSTemplate.base_url + '/os_templates'
         headers = {'content-type': 'application/json'}
         r = requests.get(url, headers=headers)
         j_r = json.loads(r.content)
@@ -64,7 +64,7 @@ class TestOSTemplate(unittest.TestCase):
 
     # 校验系统模板更新结果
     def test_14_get(self):
-        url = TestOSTemplate.base_url + '/os_template'
+        url = TestOSTemplate.base_url + '/os_templates'
         headers = {'content-type': 'application/json'}
         r = requests.get(url, headers=headers)
         j_r = json.loads(r.content)

+ 2 - 1
views/guest.py

@@ -130,7 +130,7 @@ def r_create():
             # 替换占位符为有效内容
             _os_init_writes = copy.deepcopy(os_init_writes)
             for k, v in enumerate(_os_init_writes):
-                _os_init_writes[k] = v['content'].replace('{IP}', guest.ip).\
+                _os_init_writes[k]['content'] = v['content'].replace('{IP}', guest.ip).\
                     replace('{HOSTNAME}', guest.name).\
                     replace('{NETMASK}', config.netmask).\
                     replace('{GATEWAY}', config.gateway).\
@@ -139,6 +139,7 @@ def r_create():
 
             create_vm_msg = {
                 'uuid': guest.uuid,
+                'name': guest.name,
                 'glusterfs_volume': config.glusterfs_volume,
                 'template_path': 'template_pool/' + os_template.name,
                 'guest_disks': guest_disks,

+ 188 - 0
views/log.py

@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+from flask import Blueprint
+from flask import request
+import jimit as ji
+import json
+
+from models import Log
+from models import Rules
+from models import Utils
+
+
+__author__ = 'James Iter'
+__date__ = '2017/4/8'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2017 by James Iter.'
+
+
+blueprint = Blueprint(
+    'log',
+    __name__,
+    url_prefix='/api/log'
+)
+
+blueprints = Blueprint(
+    'logs',
+    __name__,
+    url_prefix='/api/logs'
+)
+
+
+@Utils.dumps2response
+def r_get_by_filter():
+    page = str(request.args.get('page', 1))
+    page_size = str(request.args.get('page_size', 50))
+
+    args_rules = [
+        Rules.PAGE.value,
+        Rules.PAGE_SIZE.value
+    ]
+
+    try:
+        ji.Check.previewing(args_rules, {'page': page, 'page_size': page_size})
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+    page = int(page)
+    page_size = int(page_size)
+
+    # 把page和page_size换算成offset和limit
+    offset = (page - 1) * page_size
+    # offset, limit将覆盖page及page_size的影响
+    offset = str(request.args.get('offset', offset))
+    limit = str(request.args.get('limit', page_size))
+
+    order_by = request.args.get('order_by', 'id')
+    order = request.args.get('order', 'asc')
+    filter_str = request.args.get('filter', '')
+
+    args_rules = [
+        Rules.OFFSET.value,
+        Rules.LIMIT.value,
+        Rules.ORDER_BY.value,
+        Rules.ORDER.value
+    ]
+
+    try:
+        ji.Check.previewing(args_rules, {'offset': offset, 'limit': limit, 'order_by': order_by, 'order': order})
+        offset = int(offset)
+        limit = int(limit)
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        ret['data'] = list()
+        ret['paging'] = {'total': 0, 'offset': offset, 'limit': limit, 'page': page, 'page_size': page_size,
+                         'next': '', 'prev': '', 'first': '', 'last': ''}
+
+        ret['data'], ret['paging']['total'] = Log.get_by_filter(offset=offset, limit=limit, order_by=order_by,
+                                                                order=order, filter_str=filter_str)
+
+        host_url = request.host_url.rstrip('/')
+        other_str = '&filter=' + filter_str + '&order=' + order + '&order_by=' + order_by
+        last_pagination = (ret['paging']['total'] + page_size - 1) / page_size
+
+        if page <= 1:
+            ret['paging']['prev'] = host_url + blueprints.url_prefix + '?page=1&page_size=' + page_size.__str__() + \
+                                    other_str
+        else:
+            ret['paging']['prev'] = host_url + blueprints.url_prefix + '?page=' + str(page-1) + '&page_size=' + \
+                                    page_size.__str__() + other_str
+
+        if page >= last_pagination:
+            ret['paging']['next'] = host_url + blueprints.url_prefix + '?page=' + last_pagination.__str__() + \
+                                    '&page_size=' + page_size.__str__() + other_str
+        else:
+            ret['paging']['next'] = host_url + blueprints.url_prefix + '?page=' + str(page+1) + '&page_size=' + \
+                                    page_size.__str__() + other_str
+
+        ret['paging']['first'] = host_url + blueprints.url_prefix + '?page=1&page_size=' + \
+            page_size.__str__() + other_str
+        ret['paging']['last'] = \
+            host_url + blueprints.url_prefix + '?page=' + last_pagination.__str__() + '&page_size=' + \
+            page_size.__str__() + other_str
+
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
+@Utils.dumps2response
+@Utils.superuser
+def r_content_search():
+    page = str(request.args.get('page', 1))
+    page_size = str(request.args.get('page_size', 50))
+
+    args_rules = [
+        Rules.PAGE.value,
+        Rules.PAGE_SIZE.value
+    ]
+
+    try:
+        ji.Check.previewing(args_rules, {'page': page, 'page_size': page_size})
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+    page = int(page)
+    page_size = int(page_size)
+
+    # 把page和page_size换算成offset和limit
+    offset = (page - 1) * page_size
+    # offset, limit将覆盖page及page_size的影响
+    offset = str(request.args.get('offset', offset))
+    limit = str(request.args.get('limit', page_size))
+
+    order_by = request.args.get('order_by', 'id')
+    order = request.args.get('order', 'asc')
+    keyword = request.args.get('keyword', '')
+
+    args_rules = [
+        Rules.OFFSET.value,
+        Rules.LIMIT.value,
+        Rules.ORDER_BY.value,
+        Rules.ORDER.value,
+        Rules.KEYWORD.value
+    ]
+
+    try:
+        ji.Check.previewing(args_rules, {'offset': offset, 'limit': limit, 'order_by': order_by, 'order': order,
+                                         'keyword': keyword})
+        offset = int(offset)
+        limit = int(limit)
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        ret['data'] = list()
+        ret['paging'] = {'total': 0, 'offset': offset, 'limit': limit, 'page': page, 'page_size': page_size}
+
+        ret['data'], ret['paging']['total'] = Log.content_search(offset=offset, limit=limit, order_by=order_by,
+                                                                 order=order, keyword=keyword)
+
+        host_url = request.host_url.rstrip('/')
+        other_str = '&keyword=' + keyword + '&order=' + order + '&order_by=' + order_by
+        last_pagination = (ret['paging']['total'] + page_size - 1) / page_size
+
+        if page <= 1:
+            ret['paging']['prev'] = host_url + blueprints.url_prefix + '/_search?page=1&page_size=' + \
+                                    page_size.__str__() + other_str
+        else:
+            ret['paging']['prev'] = host_url + blueprints.url_prefix + '/_search?page=' + str(page-1) + \
+                                    '&page_size=' + page_size.__str__() + other_str
+
+        if page >= last_pagination:
+            ret['paging']['next'] = host_url + blueprints.url_prefix + '/_search?page=' + last_pagination.__str__() + \
+                                    '&page_size=' + page_size.__str__() + other_str
+        else:
+            ret['paging']['next'] = host_url + blueprints.url_prefix + '/_search?page=' + str(page+1) + \
+                                    '&page_size=' + page_size.__str__() + other_str
+
+        ret['paging']['first'] = host_url + blueprints.url_prefix + '/_search?page=1&page_size=' + \
+            page_size.__str__() + other_str
+        ret['paging']['last'] = \
+            host_url + blueprints.url_prefix + '/_search?page=' + last_pagination.__str__() + '&page_size=' + \
+            page_size.__str__() + other_str
+
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+

+ 12 - 6
views/os_init.py

@@ -25,6 +25,12 @@ blueprint = Blueprint(
     url_prefix='/api/os_init'
 )
 
+blueprints = Blueprint(
+    'os_inits',
+    __name__,
+    url_prefix='/api/os_inits'
+)
+
 
 @Utils.dumps2response
 def r_create():
@@ -181,23 +187,23 @@ def r_get_by_filter():
         last_pagination = (ret['paging']['total'] + page_size - 1) / page_size
 
         if page <= 1:
-            ret['paging']['prev'] = host_url + blueprint.url_prefix + '?page=1&page_size=' + page_size.__str__() + \
+            ret['paging']['prev'] = host_url + blueprints.url_prefix + '?page=1&page_size=' + page_size.__str__() + \
                                     other_str
         else:
-            ret['paging']['prev'] = host_url + blueprint.url_prefix + '?page=' + str(page-1) + '&page_size=' + \
+            ret['paging']['prev'] = host_url + blueprints.url_prefix + '?page=' + str(page-1) + '&page_size=' + \
                                     page_size.__str__() + other_str
 
         if page >= last_pagination:
-            ret['paging']['next'] = host_url + blueprint.url_prefix + '?page=' + last_pagination.__str__() + \
+            ret['paging']['next'] = host_url + blueprints.url_prefix + '?page=' + last_pagination.__str__() + \
                                     '&page_size=' + page_size.__str__() + other_str
         else:
-            ret['paging']['next'] = host_url + blueprint.url_prefix + '?page=' + str(page+1) + '&page_size=' + \
+            ret['paging']['next'] = host_url + blueprints.url_prefix + '?page=' + str(page+1) + '&page_size=' + \
                                     page_size.__str__() + other_str
 
-        ret['paging']['first'] = host_url + blueprint.url_prefix + '?page=1&page_size=' + \
+        ret['paging']['first'] = host_url + blueprints.url_prefix + '?page=1&page_size=' + \
             page_size.__str__() + other_str
         ret['paging']['last'] = \
-            host_url + blueprint.url_prefix + '?page=' + last_pagination.__str__() + '&page_size=' + \
+            host_url + blueprints.url_prefix + '?page=' + last_pagination.__str__() + '&page_size=' + \
             page_size.__str__() + other_str
 
         return ret

+ 13 - 6
views/os_init_write.py

@@ -25,6 +25,12 @@ blueprint = Blueprint(
     url_prefix='/api/os_init_write'
 )
 
+blueprints = Blueprint(
+    'os_init_writes',
+    __name__,
+    url_prefix='/api/os_init_writes'
+)
+
 
 @Utils.dumps2response
 def r_create():
@@ -187,25 +193,26 @@ def r_get_by_filter():
         last_pagination = (ret['paging']['total'] + page_size - 1) / page_size
 
         if page <= 1:
-            ret['paging']['prev'] = host_url + blueprint.url_prefix + '?page=1&page_size=' + page_size.__str__() + \
+            ret['paging']['prev'] = host_url + blueprints.url_prefix + '?page=1&page_size=' + page_size.__str__() + \
                                     other_str
         else:
-            ret['paging']['prev'] = host_url + blueprint.url_prefix + '?page=' + str(page-1) + '&page_size=' + \
+            ret['paging']['prev'] = host_url + blueprints.url_prefix + '?page=' + str(page-1) + '&page_size=' + \
                                     page_size.__str__() + other_str
 
         if page >= last_pagination:
-            ret['paging']['next'] = host_url + blueprint.url_prefix + '?page=' + last_pagination.__str__() + \
+            ret['paging']['next'] = host_url + blueprints.url_prefix + '?page=' + last_pagination.__str__() + \
                                     '&page_size=' + page_size.__str__() + other_str
         else:
-            ret['paging']['next'] = host_url + blueprint.url_prefix + '?page=' + str(page+1) + '&page_size=' + \
+            ret['paging']['next'] = host_url + blueprints.url_prefix + '?page=' + str(page+1) + '&page_size=' + \
                                     page_size.__str__() + other_str
 
-        ret['paging']['first'] = host_url + blueprint.url_prefix + '?page=1&page_size=' + \
+        ret['paging']['first'] = host_url + blueprints.url_prefix + '?page=1&page_size=' + \
             page_size.__str__() + other_str
         ret['paging']['last'] = \
-            host_url + blueprint.url_prefix + '?page=' + last_pagination.__str__() + '&page_size=' + \
+            host_url + blueprints.url_prefix + '?page=' + last_pagination.__str__() + '&page_size=' + \
             page_size.__str__() + other_str
 
         return ret
     except ji.PreviewingError, e:
         return json.loads(e.message)
+

+ 12 - 6
views/os_template.py

@@ -24,6 +24,12 @@ blueprint = Blueprint(
     url_prefix='/api/os_template'
 )
 
+blueprints = Blueprint(
+    'os_templates',
+    __name__,
+    url_prefix='/api/os_templates'
+)
+
 
 @Utils.dumps2response
 def r_create():
@@ -194,23 +200,23 @@ def r_get_by_filter():
         last_pagination = (ret['paging']['total'] + page_size - 1) / page_size
 
         if page <= 1:
-            ret['paging']['prev'] = host_url + blueprint.url_prefix + '?page=1&page_size=' + page_size.__str__() + \
+            ret['paging']['prev'] = host_url + blueprints.url_prefix + '?page=1&page_size=' + page_size.__str__() + \
                                     other_str
         else:
-            ret['paging']['prev'] = host_url + blueprint.url_prefix + '?page=' + str(page-1) + '&page_size=' + \
+            ret['paging']['prev'] = host_url + blueprints.url_prefix + '?page=' + str(page-1) + '&page_size=' + \
                                     page_size.__str__() + other_str
 
         if page >= last_pagination:
-            ret['paging']['next'] = host_url + blueprint.url_prefix + '?page=' + last_pagination.__str__() + \
+            ret['paging']['next'] = host_url + blueprints.url_prefix + '?page=' + last_pagination.__str__() + \
                                     '&page_size=' + page_size.__str__() + other_str
         else:
-            ret['paging']['next'] = host_url + blueprint.url_prefix + '?page=' + str(page+1) + '&page_size=' + \
+            ret['paging']['next'] = host_url + blueprints.url_prefix + '?page=' + str(page+1) + '&page_size=' + \
                                     page_size.__str__() + other_str
 
-        ret['paging']['first'] = host_url + blueprint.url_prefix + '?page=1&page_size=' + \
+        ret['paging']['first'] = host_url + blueprints.url_prefix + '?page=1&page_size=' + \
             page_size.__str__() + other_str
         ret['paging']['last'] = \
-            host_url + blueprint.url_prefix + '?page=' + last_pagination.__str__() + '&page_size=' + \
+            host_url + blueprints.url_prefix + '?page=' + last_pagination.__str__() + '&page_size=' + \
             page_size.__str__() + other_str
 
         return ret