Browse Source

重构操作系统模板管理功能。完成相关数据库的设计、模型、API部分。

James Iter 8 years ago
parent
commit
3c750c853a

+ 150 - 0
api/os_template_image.py

@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+from flask import Blueprint
+from flask import request
+import jimit as ji
+import json
+
+from api.base import Base
+from models import OSTemplateImage, OSTemplateProfile
+from models import Rules
+from models import Utils
+
+
+__author__ = 'James Iter'
+__date__ = '2018/2/4'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2018 by James Iter.'
+
+
+blueprint = Blueprint(
+    'api_os_template_image',
+    __name__,
+    url_prefix='/api/os_template_image'
+)
+
+blueprints = Blueprint(
+    'api_os_templates_image',
+    __name__,
+    url_prefix='/api/os_templates_image'
+)
+
+
+os_template_image_base = Base(the_class=OSTemplateImage, the_blueprint=blueprint, the_blueprints=blueprints)
+
+
+@Utils.dumps2response
+def r_create():
+
+    os_template_image = OSTemplateImage()
+
+    args_rules = [
+        Rules.OS_TEMPLATE_PROFILE_ID_EXT.value,
+        Rules.PATH.value,
+        Rules.ACTIVE.value
+    ]
+
+    os_template_image.path = request.json.get('path')
+    os_template_image.active = request.json.get('active')
+    os_template_image.os_template_profile_id = request.json.get('os_template_profile_id')
+
+    try:
+        ji.Check.previewing(args_rules, os_template_image.__dict__)
+
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+
+        if os_template_image.exist_by('path'):
+            ret['state'] = ji.Common.exchange_state(40901)
+            ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', os_template_image.path])
+            return ret
+
+        os_template_profile = OSTemplateProfile()
+        os_template_profile.id = os_template_image.os_template_profile_id
+        if not os_template_profile.exist():
+            ret['state'] = ji.Common.exchange_state(40401)
+            ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], u': 操作系统模板描述文件ID: ',
+                                                    os_template_image.os_template_profile_id.__str__()])
+            return ret
+
+        os_template_image.create()
+        os_template_image.get_by('path')
+        ret['data'] = os_template_image.__dict__
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
+@Utils.dumps2response
+def r_update(_id):
+
+    os_template_image = OSTemplateImage()
+
+    args_rules = [
+        Rules.ID.value
+    ]
+
+    if 'path' in request.json:
+        args_rules.append(
+            Rules.PATH.value,
+        )
+
+    if 'active' in request.json:
+        args_rules.append(
+            Rules.ACTIVE.value,
+        )
+
+    if 'os_template_profile_id' in request.json:
+        args_rules.append(
+            Rules.OS_TEMPLATE_PROFILE_ID_EXT.value,
+        )
+
+    if args_rules.__len__() < 2:
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        return ret
+
+    request.json['id'] = _id
+
+    try:
+        ji.Check.previewing(args_rules, request.json)
+        os_template_image.id = request.json.get('id')
+
+        os_template_image.get()
+        os_template_image.path = request.json.get('path', os_template_image.path)
+        os_template_image.active = request.json.get('active', os_template_image.active)
+        os_template_image.os_template_profile_id = \
+            request.json.get('os_template_profile_id', os_template_image.os_template_profile_id)
+
+        os_template_image.update()
+        os_template_image.get()
+
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        ret['data'] = os_template_image.__dict__
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
+@Utils.dumps2response
+def r_delete(ids):
+    return os_template_image_base.delete(ids=ids, ids_rule=Rules.IDS.value, by_field='id')
+
+
+@Utils.dumps2response
+def r_get(ids):
+    return os_template_image_base.get(ids=ids, ids_rule=Rules.IDS.value, by_field='id')
+
+
+@Utils.dumps2response
+def r_get_by_filter():
+    return os_template_image_base.get_by_filter()
+
+
+@Utils.dumps2response
+def r_content_search():
+    return os_template_image_base.content_search()
+

+ 212 - 0
api/os_template_initialize_operate.py

@@ -0,0 +1,212 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+from flask import Blueprint
+from flask import request
+import jimit as ji
+import json
+
+from api.base import Base
+from models import Rules
+from models import Utils
+from models import OSTemplateInitializeOperate
+from models import OSTemplateInitializeOperateSet
+from models.status import OSTemplateInitializeOperateKind
+
+
+__author__ = 'James Iter'
+__date__ = '2018/2/4'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2018 by James Iter.'
+
+
+blueprint = Blueprint(
+    'api_os_template_initialize_operate',
+    __name__,
+    url_prefix='/api/os_template_initialize_operate'
+)
+
+blueprints = Blueprint(
+    'api_os_template_initialize_operates',
+    __name__,
+    url_prefix='/api/os_template_initialize_operates'
+)
+
+
+os_template_initialize_operate_base = \
+    Base(the_class=OSTemplateInitializeOperate, the_blueprint=blueprint, the_blueprints=blueprints)
+
+
+@Utils.dumps2response
+def r_create():
+
+    os_template_initialize_operate_set = OSTemplateInitializeOperateSet()
+    os_template_initialize_operate = OSTemplateInitializeOperate()
+
+    args_rules = [
+        Rules.OS_TEMPLATE_INITIALIZE_OPERATE_SET_ID_EXT.value,
+        Rules.OS_TEMPLATE_INITIALIZE_OPERATE_KIND.value,
+        Rules.OS_TEMPLATE_INITIALIZE_OPERATE_SEQUENCE.value
+    ]
+
+    os_template_initialize_operate.os_template_initialize_operate_set_id = \
+        request.json.get('os_template_initialize_operate_set_id')
+    os_template_initialize_operate.kind = request.json.get('kind')
+    os_template_initialize_operate.path = request.json.get('path', '')
+    os_template_initialize_operate.sequence = request.json.get('sequence', 0)
+    os_template_initialize_operate.content = request.json.get('content', '')
+    os_template_initialize_operate.command = request.json.get('command', '')
+
+    if os_template_initialize_operate.kind == OSTemplateInitializeOperateKind.cmd.value:
+        args_rules.append(
+            Rules.OS_TEMPLATE_INITIALIZE_OPERATE_COMMAND.value
+        )
+
+    else:
+        args_rules.extend([
+            Rules.OS_TEMPLATE_INITIALIZE_OPERATE_PATH.value,
+            Rules.OS_TEMPLATE_INITIALIZE_OPERATE_CONTENT.value
+        ])
+
+    try:
+        ji.Check.previewing(args_rules, os_template_initialize_operate.__dict__)
+
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+
+        os_template_initialize_operate_set.id = os_template_initialize_operate.os_template_initialize_operate_set_id
+        if not os_template_initialize_operate_set.exist():
+            ret['state'] = ji.Common.exchange_state(40401)
+            ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], u': 操作系统初始化操作集ID: ',
+                                                    os_template_initialize_operate_set.id.__str__()])
+            return ret
+
+        if os_template_initialize_operate.kind == OSTemplateInitializeOperateKind.cmd.value:
+            data, total = os_template_initialize_operate.get_by_filter(
+                filter_str=':'.join(['os_template_initialize_operate_set_id', 'eq',
+                                     os_template_initialize_operate.os_template_initialize_operate_set_id.__str__()]) +
+                           ';' + ':'.join(['command', 'eq', os_template_initialize_operate.command]))
+
+        else:
+            data, total = os_template_initialize_operate.get_by_filter(
+                filter_str=':'.join(['os_template_initialize_operate_set_id', 'eq',
+                                     os_template_initialize_operate.os_template_initialize_operate_set_id.__str__()]) +
+                           ';' + ':'.join(['path', 'eq', os_template_initialize_operate.path]))
+
+        if data.__len__() > 0:
+            ret['state'] = ji.Common.exchange_state(40901)
+
+            if os_template_initialize_operate.kind == OSTemplateInitializeOperateKind.cmd.value:
+                ret['state']['sub']['zh-cn'] = ''.join(
+                    [ret['state']['sub']['zh-cn'], u', 命令: ', os_template_initialize_operate.command,
+                     u', 已存在于操作集ID ',
+                     os_template_initialize_operate.os_template_initialize_operate_set_id.__str__(), u' 中。'])
+
+            else:
+                ret['state']['sub']['zh-cn'] = ''.join([
+                    ret['state']['sub']['zh-cn'], u', 路径: ', os_template_initialize_operate.path,
+                    u', 已存在于操作集ID ',
+                    os_template_initialize_operate.os_template_initialize_operate_set_id.__str__(), u' 中。'])
+            return ret
+
+        os_template_initialize_operate.create()
+        data, total = os_template_initialize_operate.get_by_filter(
+            filter_str=':'.join(['os_template_initialize_operate_set_id', 'eq',
+                                 os_template_initialize_operate.os_template_initialize_operate_set_id.__str__()]) + ';'
+                       + ':'.join(['path', 'eq', os_template_initialize_operate.path]))
+        ret['data'] = data[0]
+        return ret
+
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
+@Utils.dumps2response
+def r_update(_id):
+
+    os_template_initialize_operate = OSTemplateInitializeOperate()
+
+    args_rules = [
+        Rules.ID.value
+    ]
+
+    if 'os_template_initialize_operate_set_id' in request.json:
+        args_rules.append(
+            Rules.OS_TEMPLATE_INITIALIZE_OPERATE_SET_ID_EXT.value,
+        )
+
+    if 'kind' in request.json:
+        args_rules.append(
+            Rules.OS_TEMPLATE_INITIALIZE_OPERATE_KIND.value,
+        )
+
+    if 'sequence' in request.json:
+        args_rules.append(
+            Rules.OS_TEMPLATE_INITIALIZE_OPERATE_SEQUENCE.value,
+        )
+
+    if 'path' in request.json:
+        args_rules.append(
+            Rules.OS_TEMPLATE_INITIALIZE_OPERATE_PATH.value,
+        )
+
+    if 'content' in request.json:
+        args_rules.append(
+            Rules.OS_TEMPLATE_INITIALIZE_OPERATE_CONTENT.value,
+        )
+
+    if 'command' in request.json:
+        args_rules.append(
+            Rules.OS_TEMPLATE_INITIALIZE_OPERATE_COMMAND.value,
+        )
+
+    if args_rules.__len__() < 2:
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        return ret
+
+    request.json['id'] = _id
+
+    try:
+        ji.Check.previewing(args_rules, request.json)
+        os_template_initialize_operate.id = request.json.get('id')
+        os_template_initialize_operate.get()
+        os_template_initialize_operate.os_template_initialize_operate_set_id = \
+            request.json.get('os_template_initialize_operate_set_id',
+                             os_template_initialize_operate.os_template_initialize_operate_set_id)
+        os_template_initialize_operate.kind = request.json.get('kind', os_template_initialize_operate.kind)
+        os_template_initialize_operate.sequence = request.json.get('sequence', os_template_initialize_operate.sequence)
+        os_template_initialize_operate.path = request.json.get('path', os_template_initialize_operate.path)
+        os_template_initialize_operate.content = request.json.get('content', os_template_initialize_operate.content)
+        os_template_initialize_operate.command = request.json.get('command', os_template_initialize_operate.command)
+
+        os_template_initialize_operate.update()
+        os_template_initialize_operate.get()
+
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        ret['data'] = os_template_initialize_operate.__dict__
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
+@Utils.dumps2response
+def r_delete(ids):
+    return os_template_initialize_operate_base.delete(ids=ids, ids_rule=Rules.IDS.value, by_field='id')
+
+
+@Utils.dumps2response
+def r_get(ids):
+    return os_template_initialize_operate_base.get(ids=ids, ids_rule=Rules.IDS.value, by_field='id')
+
+
+@Utils.dumps2response
+def r_get_by_filter():
+    return os_template_initialize_operate_base.get_by_filter()
+
+
+@Utils.dumps2response
+def r_content_search():
+    return os_template_initialize_operate_base.content_search()

+ 148 - 0
api/os_template_initialize_operate_set.py

@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+from flask import Blueprint
+from flask import request, g
+import jimit as ji
+import json
+
+from api.base import Base
+from models import Rules
+from models import Utils
+from models import OSTemplateInitializeOperateSet, OSTemplateInitializeOperate
+
+
+__author__ = 'James Iter'
+__date__ = '2018/2/4'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2018 by James Iter.'
+
+
+blueprint = Blueprint(
+    'api_os_template_initialize_operate_set',
+    __name__,
+    url_prefix='/api/os_template_initialize_operate_set'
+)
+
+blueprints = Blueprint(
+    'api_os_templates_initialize_operate_set',
+    __name__,
+    url_prefix='/api/os_templates_initialize_operate_set'
+)
+
+
+os_template_initialize_operate_set_base = Base(the_class=OSTemplateInitializeOperateSet,
+                                               the_blueprint=blueprint, the_blueprints=blueprints)
+
+
+@Utils.dumps2response
+def r_create():
+
+    os_template_initialize_operate_set = OSTemplateInitializeOperateSet()
+
+    args_rules = [
+        Rules.LABEL.value,
+        Rules.DESCRIBE.value,
+        Rules.ACTIVE.value
+    ]
+
+    os_template_initialize_operate_set.label = request.json.get('label')
+    os_template_initialize_operate_set.describe = request.json.get('describe')
+    os_template_initialize_operate_set.active = request.json.get('active')
+
+    try:
+        ji.Check.previewing(args_rules, os_template_initialize_operate_set.__dict__)
+
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+
+        if os_template_initialize_operate_set.exist_by('label'):
+            ret['state'] = ji.Common.exchange_state(40901)
+            ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ',
+                                                    os_template_initialize_operate_set.label])
+            return ret
+
+        os_template_initialize_operate_set.create()
+        os_template_initialize_operate_set.get_by('label')
+        ret['data'] = os_template_initialize_operate_set.__dict__
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
+@Utils.dumps2response
+def r_update(_id):
+
+    os_template_initialize_operate_set = OSTemplateInitializeOperateSet()
+
+    args_rules = [
+        Rules.ID.value
+    ]
+
+    if 'label' in request.json:
+        args_rules.append(
+            Rules.LABEL.value,
+        )
+
+    if 'describe' in request.json:
+        args_rules.append(
+            Rules.DESCRIBE.value,
+        )
+
+    if 'active' in request.json:
+        args_rules.append(
+            Rules.ACTIVE.value,
+        )
+
+    if args_rules.__len__() < 2:
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        return ret
+
+    request.json['id'] = _id
+
+    try:
+        ji.Check.previewing(args_rules, request.json)
+        os_template_initialize_operate_set.id = request.json.get('id')
+        os_template_initialize_operate_set.get()
+        os_template_initialize_operate_set.label = request.json.get('label', os_template_initialize_operate_set.label)
+        os_template_initialize_operate_set.describe = \
+            request.json.get('describe', os_template_initialize_operate_set.describe)
+        os_template_initialize_operate_set.active = \
+            request.json.get('active', os_template_initialize_operate_set.active)
+
+        os_template_initialize_operate_set.update()
+        os_template_initialize_operate_set.get()
+
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        ret['data'] = os_template_initialize_operate_set.__dict__
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
+@Utils.dumps2response
+def r_delete(ids):
+    os_template_initialize_operate_base = Base(the_class=OSTemplateInitializeOperate)
+    os_template_initialize_operate_base.delete(ids=ids, ids_rule=Rules.IDS.value,
+                                               by_field='os_template_initialize_operate_set_id')
+
+    return os_template_initialize_operate_set_base.delete(ids=ids, ids_rule=Rules.IDS.value, by_field='id')
+
+
+@Utils.dumps2response
+def r_get(ids):
+    return os_template_initialize_operate_set_base.get(ids=ids, ids_rule=Rules.IDS.value, by_field='id')
+
+
+@Utils.dumps2response
+def r_get_by_filter():
+    return os_template_initialize_operate_set_base.get_by_filter()
+
+
+@Utils.dumps2response
+def r_content_search():
+    return os_template_initialize_operate_set_base.content_search()
+

+ 208 - 0
api/os_template_profile.py

@@ -0,0 +1,208 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+from flask import Blueprint
+from flask import request
+import jimit as ji
+import json
+
+from api.base import Base
+from models import OSTemplateProfile
+from models import Rules
+from models import Utils
+
+
+__author__ = 'James Iter'
+__date__ = '2018/2/4'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2018 by James Iter.'
+
+
+blueprint = Blueprint(
+    'api_os_template_profile',
+    __name__,
+    url_prefix='/api/os_template_profile'
+)
+
+blueprints = Blueprint(
+    'api_os_templates_profile',
+    __name__,
+    url_prefix='/api/os_templates_profile'
+)
+
+
+os_template_profile_base = Base(the_class=OSTemplateProfile, the_blueprint=blueprint, the_blueprints=blueprints)
+
+
+@Utils.dumps2response
+def r_create():
+
+    os_template_profile = OSTemplateProfile()
+
+    args_rules = [
+        Rules.LABEL.value,
+        Rules.DESCRIBE.value,
+        Rules.OS_TYPE.value,
+        Rules.OS_DISTRO.value,
+        Rules.OS_MAJOR.value,
+        Rules.OS_MINOR.value,
+        Rules.OS_ARCH.value,
+        Rules.OS_PRODUCT_NAME.value,
+        Rules.ACTIVE.value,
+        Rules.ICON.value,
+        Rules.OS_TEMPLATE_INITIALIZE_OPERATE_SET_ID_EXT.value
+    ]
+
+    os_template_profile.label = request.json.get('label')
+    os_template_profile.describe = request.json.get('describe')
+    os_template_profile.os_type = request.json.get('os_type')
+    os_template_profile.os_distro = request.json.get('os_distro')
+    os_template_profile.os_major = request.json.get('os_major')
+    os_template_profile.os_minor = request.json.get('os_minor')
+    os_template_profile.os_arch = request.json.get('os_arch')
+    os_template_profile.os_product_name = request.json.get('os_product_name')
+    os_template_profile.active = request.json.get('active')
+    os_template_profile.icon = request.json.get('icon')
+    os_template_profile.os_template_initialize_operate_set_id = \
+        request.json.get('os_template_initialize_operate_set_id')
+
+    try:
+        ji.Check.previewing(args_rules, os_template_profile.__dict__)
+
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+
+        if os_template_profile.exist_by('label'):
+            ret['state'] = ji.Common.exchange_state(40901)
+            ret['state']['sub']['zh-cn'] = ''.join([ret['state']['sub']['zh-cn'], ': ', os_template_profile.label])
+            return ret
+
+        os_template_profile.create()
+        os_template_profile.get_by('label')
+        ret['data'] = os_template_profile.__dict__
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
+@Utils.dumps2response
+def r_update(_id):
+
+    os_template_profile = OSTemplateProfile()
+
+    args_rules = [
+        Rules.ID.value
+
+    ]
+
+    if 'label' in request.json:
+        args_rules.append(
+            Rules.LABEL.value,
+        )
+
+    if 'describe' in request.json:
+        args_rules.append(
+            Rules.DESCRIBE.value,
+        )
+
+    if 'os_type' in request.json:
+        args_rules.append(
+            Rules.OS_TYPE.value,
+        )
+
+    if 'os_distro' in request.json:
+        args_rules.append(
+            Rules.OS_DISTRO.value,
+        )
+
+    if 'os_major' in request.json:
+        args_rules.append(
+            Rules.OS_MAJOR.value,
+        )
+
+    if 'os_minor' in request.json:
+        args_rules.append(
+            Rules.OS_MINOR.value,
+        )
+
+    if 'os_arch' in request.json:
+        args_rules.append(
+            Rules.OS_ARCH.value,
+        )
+
+    if 'os_product_name' in request.json:
+        args_rules.append(
+            Rules.OS_PRODUCT_NAME.value,
+        )
+
+    if 'active' in request.json:
+        args_rules.append(
+            Rules.ACTIVE.value,
+        )
+
+    if 'icon' in request.json:
+        args_rules.append(
+            Rules.ICON.value,
+        )
+
+    if 'os_template_initialize_operate_set_id' in request.json:
+        args_rules.append(
+            Rules.OS_TEMPLATE_INITIALIZE_OPERATE_SET_ID_EXT.value,
+        )
+
+    if args_rules.__len__() < 2:
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        return ret
+
+    request.json['id'] = _id
+
+    try:
+        ji.Check.previewing(args_rules, request.json)
+        os_template_profile.id = request.json.get('id')
+
+        os_template_profile.get()
+        os_template_profile.label = request.json.get('label', os_template_profile.label)
+        os_template_profile.describe = request.json.get('describe', os_template_profile.describe)
+        os_template_profile.os_type = request.json.get('os_type', os_template_profile.os_type)
+        os_template_profile.os_distro = request.json.get('os_distro', os_template_profile.os_distro)
+        os_template_profile.os_major = request.json.get('os_major', os_template_profile.os_major)
+        os_template_profile.os_minor = request.json.get('os_minor', os_template_profile.os_minor)
+        os_template_profile.os_arch = request.json.get('os_arch', os_template_profile.os_arch)
+        os_template_profile.os_product_name = request.json.get('os_product_name', os_template_profile.os_product_name)
+        os_template_profile.active = request.json.get('active', os_template_profile.active)
+        os_template_profile.icon = request.json.get('icon', os_template_profile.icon)
+        os_template_profile.os_template_initialize_operate_set_id = request.json.get(
+            'os_template_initialize_operate_set_id', os_template_profile.os_template_initialize_operate_set_id)
+
+        os_template_profile.update()
+        os_template_profile.get()
+
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        ret['data'] = os_template_profile.__dict__
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
+@Utils.dumps2response
+def r_delete(ids):
+    return os_template_profile_base.delete(ids=ids, ids_rule=Rules.IDS.value, by_field='id')
+
+
+@Utils.dumps2response
+def r_get(ids):
+    return os_template_profile_base.get(ids=ids, ids_rule=Rules.IDS.value, by_field='id')
+
+
+@Utils.dumps2response
+def r_get_by_filter():
+    return os_template_profile_base.get_by_filter()
+
+
+@Utils.dumps2response
+def r_content_search():
+    return os_template_profile_base.content_search()
+

+ 49 - 0
api_route_table.py

@@ -10,6 +10,10 @@ from api import disk
 from api import boot_job
 from api import boot_job
 from api import operate_rule
 from api import operate_rule
 from api import os_template
 from api import os_template
+from api import os_template_image
+from api import os_template_profile
+from api import os_template_initialize_operate_set
+from api import os_template_initialize_operate
 from api import log
 from api import log
 from api import host
 from api import host
 from api import guest_performance
 from api import guest_performance
@@ -60,6 +64,51 @@ add_rule_api(os_template.blueprints, '/<ids>', api_func='os_template.r_get', met
 add_rule_api(os_template.blueprints, '', api_func='os_template.r_get_by_filter', methods=['GET'])
 add_rule_api(os_template.blueprints, '', api_func='os_template.r_get_by_filter', methods=['GET'])
 add_rule_api(os_template.blueprints, '/_search', api_func='os_template.r_content_search', methods=['GET'])
 add_rule_api(os_template.blueprints, '/_search', api_func='os_template.r_content_search', methods=['GET'])
 
 
+# 系统模板镜像操作
+add_rule_api(os_template_image.blueprint, '', api_func='os_template_image.r_create', methods=['POST'])
+add_rule_api(os_template_image.blueprint, '/<_id>', api_func='os_template_image.r_update', methods=['PATCH'])
+add_rule_api(os_template_image.blueprints, '/<ids>', api_func='os_template_image.r_delete', methods=['DELETE'])
+add_rule_api(os_template_image.blueprints, '/<ids>', api_func='os_template_image.r_get', methods=['GET'])
+add_rule_api(os_template_image.blueprints, '', api_func='os_template_image.r_get_by_filter', methods=['GET'])
+add_rule_api(os_template_image.blueprints, '/_search', api_func='os_template_image.r_content_search', methods=['GET'])
+
+# 系统模板描述文件操作
+add_rule_api(os_template_profile.blueprint, '', api_func='os_template_profile.r_create', methods=['POST'])
+add_rule_api(os_template_profile.blueprint, '/<_id>', api_func='os_template_profile.r_update', methods=['PATCH'])
+add_rule_api(os_template_profile.blueprints, '/<ids>', api_func='os_template_profile.r_delete', methods=['DELETE'])
+add_rule_api(os_template_profile.blueprints, '/<ids>', api_func='os_template_profile.r_get', methods=['GET'])
+add_rule_api(os_template_profile.blueprints, '', api_func='os_template_profile.r_get_by_filter', methods=['GET'])
+add_rule_api(os_template_profile.blueprints, '/_search', api_func='os_template_profile.r_content_search',
+             methods=['GET'])
+
+# 系统模板初始化操作集操作
+add_rule_api(os_template_initialize_operate_set.blueprint, '',
+             api_func='os_template_initialize_operate_set.r_create', methods=['POST'])
+add_rule_api(os_template_initialize_operate_set.blueprint, '/<_id>',
+             api_func='os_template_initialize_operate_set.r_update', methods=['PATCH'])
+add_rule_api(os_template_initialize_operate_set.blueprints, '/<ids>',
+             api_func='os_template_initialize_operate_set.r_delete', methods=['DELETE'])
+add_rule_api(os_template_initialize_operate_set.blueprints, '/<ids>',
+             api_func='os_template_initialize_operate_set.r_get', methods=['GET'])
+add_rule_api(os_template_initialize_operate_set.blueprints, '',
+             api_func='os_template_initialize_operate_set.r_get_by_filter', methods=['GET'])
+add_rule_api(os_template_initialize_operate_set.blueprints, '/_search',
+             api_func='os_template_initialize_operate_set.r_content_search', methods=['GET'])
+
+# 系统模板初始化操作细则
+add_rule_api(os_template_initialize_operate.blueprint, '',
+             api_func='os_template_initialize_operate.r_create', methods=['POST'])
+add_rule_api(os_template_initialize_operate.blueprint, '/<_id>',
+             api_func='os_template_initialize_operate.r_update', methods=['PATCH'])
+add_rule_api(os_template_initialize_operate.blueprints, '/<ids>',
+             api_func='os_template_initialize_operate.r_delete', methods=['DELETE'])
+add_rule_api(os_template_initialize_operate.blueprints, '/<ids>',
+             api_func='os_template_initialize_operate.r_get', methods=['GET'])
+add_rule_api(os_template_initialize_operate.blueprints, '',
+             api_func='os_template_initialize_operate.r_get_by_filter', methods=['GET'])
+add_rule_api(os_template_initialize_operate.blueprints, '/_search',
+             api_func='os_template_initialize_operate.r_content_search', methods=['GET'])
+
 # Guest操作
 # Guest操作
 # 创建虚拟机
 # 创建虚拟机
 add_rule_api(guest.blueprint, '', api_func='guest.r_create', methods=['POST'])
 add_rule_api(guest.blueprint, '', api_func='guest.r_create', methods=['POST'])

+ 67 - 28
misc/init.sql

@@ -112,32 +112,61 @@ ALTER TABLE disk ADD INDEX (node_id);
 ALTER TABLE disk ADD INDEX (remark);
 ALTER TABLE disk ADD INDEX (remark);
 
 
 
 
-CREATE TABLE IF NOT EXISTS os_template(
+-- 操作系统模板镜像
+CREATE TABLE IF NOT EXISTS os_template_image(
     id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
     id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
-    label VARCHAR(255) NOT NULL,
+    os_template_profile_id BIGINT UNSIGNED NOT NULL,
     path VARCHAR(255) NOT NULL,
     path VARCHAR(255) NOT NULL,
-    os_type TINYINT UNSIGNED NOT NULL,
+    active BOOLEAN NOT NULL DEFAULT TRUE,
+    PRIMARY KEY (id))
+    ENGINE=InnoDB
+    DEFAULT CHARSET=utf8;
+
+
+-- 操作系统模板描述文件
+CREATE TABLE IF NOT EXISTS os_template_profile(
+    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
+    label VARCHAR(255) NOT NULL,
+    describe TEXT NOT NULL DEFAULT '',
+    -- http://libguestfs.org/guestfish.1.html#inspect-get-type
+    os_type VARCHAR(10) NOT NULL,
+    -- http://libguestfs.org/guestfish.1.html#inspect-get-distro
+    os_distro VARCHAR(20) NOT NULL,
+    os_major TINYINT UNSIGNED NOT NULL,
+    os_minor TINYINT UNSIGNED NOT NULL,
+    -- http://libguestfs.org/guestfish.1.html#inspect-get-arch  http://libguestfs.org/guestfish.1.html#file-architecture
+    os_arch VARCHAR(10) NOT NULL,
+    os_product_name VARCHAR(255) NOT NULL,
     active BOOLEAN NOT NULL DEFAULT TRUE,
     active BOOLEAN NOT NULL DEFAULT TRUE,
     icon VARCHAR(255) NOT NULL,
     icon VARCHAR(255) NOT NULL,
-    boot_job_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
+    os_template_initialize_operate_set_id BIGINT UNSIGNED NOT NULL,
     PRIMARY KEY (id))
     PRIMARY KEY (id))
     ENGINE=InnoDB
     ENGINE=InnoDB
     DEFAULT CHARSET=utf8;
     DEFAULT CHARSET=utf8;
 
 
+ALTER TABLE os_template_profile ADD INDEX (label);
+ALTER TABLE os_template_profile ADD INDEX (os_type);
+ALTER TABLE os_template_profile ADD INDEX (os_distro);
+ALTER TABLE os_template_profile ADD INDEX (os_product_name);
 
 
-CREATE TABLE IF NOT EXISTS boot_job(
+
+-- 操作系统模板初始化操作集
+CREATE TABLE IF NOT EXISTS os_template_initialize_operate_set(
     id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
     id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
-    name VARCHAR(255) NOT NULL,
-    use_for TINYINT UNSIGNED NOT NULL DEFAULT 0,
-    remark VARCHAR(255) NOT NULL DEFAULT '',
+    label VARCHAR(255) NOT NULL,
+    describe TEXT NOT NULL DEFAULT '',
+    active BOOLEAN NOT NULL DEFAULT TRUE,
     PRIMARY KEY (id))
     PRIMARY KEY (id))
     ENGINE=InnoDB
     ENGINE=InnoDB
     DEFAULT CHARSET=utf8;
     DEFAULT CHARSET=utf8;
 
 
+ALTER TABLE os_template_initialize_operate_set ADD INDEX (label);
 
 
-CREATE TABLE IF NOT EXISTS operate_rule(
+
+-- 操作系统模板初始化操作细则
+CREATE TABLE IF NOT EXISTS os_template_initialize_operate(
     id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
     id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
-    boot_job_id BIGINT UNSIGNED NOT NULL,
+    os_template_initialize_operate_set_id BIGINT UNSIGNED NOT NULL,
     kind TINYINT UNSIGNED NOT NULL DEFAULT 0,
     kind TINYINT UNSIGNED NOT NULL DEFAULT 0,
     sequence TINYINT UNSIGNED NOT NULL DEFAULT 0,
     sequence TINYINT UNSIGNED NOT NULL DEFAULT 0,
     path VARCHAR(255) NOT NULL,
     path VARCHAR(255) NOT NULL,
@@ -147,6 +176,8 @@ CREATE TABLE IF NOT EXISTS operate_rule(
     ENGINE=InnoDB
     ENGINE=InnoDB
     DEFAULT CHARSET=utf8;
     DEFAULT CHARSET=utf8;
 
 
+ALTER TABLE os_template_initialize_operate ADD INDEX (os_template_initialize_operate_set_id);
+
 
 
 CREATE TABLE IF NOT EXISTS config(
 CREATE TABLE IF NOT EXISTS config(
     id BIGINT UNSIGNED NOT NULL DEFAULT 1,
     id BIGINT UNSIGNED NOT NULL DEFAULT 1,
@@ -323,19 +354,15 @@ ALTER TABLE host_disk_usage_io ADD INDEX (timestamp);
 ALTER TABLE host_disk_usage_io ADD INDEX (node_id, mountpoint, timestamp);
 ALTER TABLE host_disk_usage_io ADD INDEX (node_id, mountpoint, timestamp);
 
 
 
 
-INSERT INTO boot_job (name, use_for, remark) VALUES ('Reset password for Linux', 1, '重置 Linux 平台管理员密码。');
-INSERT INTO boot_job (name, use_for, remark) VALUES ('CentOS-Systemd', 0, '用作 Redhat Systemd 系列的系统初始化。初始化操作依据 CentOS 7 来实现。');
-INSERT INTO boot_job (name, use_for, remark) VALUES ('CentOS-SysV', 0, '用作 Redhat SysV 系列的系统初始化。初始化操作依据 CentOS 6.8 来实现。');
-INSERT INTO boot_job (name, use_for, remark) VALUES ('Gentoo-OpenRC', 0, '用作 Gentoo OpenRC 系列的系统初始化。');
-INSERT INTO boot_job (name, use_for, remark) VALUES ('Windows', 0, '用作 MS-Windos 系列的系统初始化。初始化操作依据 Windows 2012 来实现。');
-
--- For Reset password for Linux
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (1, 0, 0, '', '', 'echo "root:{PASSWORD}" | chpasswd');
+INSERT INTO os_template_initialize_operate_set (label, describe, active) VALUES ('CentOS-Systemd', '用作 Redhat Systemd 系列的系统初始化。初始化操作依据 CentOS 7 来实现。', 1);
+INSERT INTO os_template_initialize_operate_set (label, describe, active) VALUES ('CentOS-SysV', '用作 Redhat SysV 系列的系统初始化。初始化操作依据 CentOS 6.8 来实现。', 1);
+INSERT INTO os_template_initialize_operate_set (label, describe, active) VALUES ('Gentoo-OpenRC', '用作 Gentoo OpenRC 系列的系统初始化。', 1);
+INSERT INTO os_template_initialize_operate_set (label, describe, active) VALUES ('Windows', '用作 MS-Windows 系列的系统初始化。初始化操作依据 Windows 2012 来实现。', 1);
 
 
 -- For CentOS-Systemd
 -- For CentOS-Systemd
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (2, 1, 0, '/etc/resolv.conf', 'nameserver {DNS1}
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (1, 1, 0, '/etc/resolv.conf', 'nameserver {DNS1}
 nameserver {DNS2}', '');
 nameserver {DNS2}', '');
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (2, 1, 0, '/etc/sysconfig/network-scripts/ifcfg-eth0', 'DEVICE=eth0
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (1, 1, 1, '/etc/sysconfig/network-scripts/ifcfg-eth0', 'DEVICE=eth0
 TYPE=Ethernet
 TYPE=Ethernet
 ONBOOT=yes
 ONBOOT=yes
 BOOTPROTO="static"
 BOOTPROTO="static"
@@ -346,12 +373,13 @@ DNS1={DNS1}
 DNS2={DNS2}
 DNS2={DNS2}
 IPV6INIT=no
 IPV6INIT=no
 NAME=eth0', '');
 NAME=eth0', '');
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (2, 1, 0, '/etc/hostname', '{HOSTNAME}', '');
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (1, 1, 2, '/etc/hostname', '{HOSTNAME}', '');
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (1, 0, 3, '', '', 'echo "root:{PASSWORD}" | chpasswd');
 
 
 -- For CentOS-SysV
 -- For CentOS-SysV
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (3, 1, 0, '/etc/resolv.conf', 'nameserver {DNS1}
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (2, 1, 0, '/etc/resolv.conf', 'nameserver {DNS1}
 nameserver {DNS2}', '');
 nameserver {DNS2}', '');
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (3, 1, 0, '/etc/sysconfig/network-scripts/ifcfg-eth0', 'DEVICE=eth0
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (2, 1, 1, '/etc/sysconfig/network-scripts/ifcfg-eth0', 'DEVICE=eth0
 TYPE=Ethernet
 TYPE=Ethernet
 ONBOOT=yes
 ONBOOT=yes
 BOOTPROTO="static"
 BOOTPROTO="static"
@@ -360,18 +388,20 @@ NETMASK={NETMASK}
 GATEWAY={GATEWAY}
 GATEWAY={GATEWAY}
 IPV6INIT=no
 IPV6INIT=no
 NAME=eth0', '');
 NAME=eth0', '');
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (3, 1, 0, '/etc/sysconfig/network', 'NETWORKING=yes
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (2, 1, 2, '/etc/sysconfig/network', 'NETWORKING=yes
 HOSTNAME="{HOSTNAME}"', '');
 HOSTNAME="{HOSTNAME}"', '');
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (2, 0, 3, '', '', 'echo "root:{PASSWORD}" | chpasswd');
 
 
 -- For Gentoo-OpenRC
 -- For Gentoo-OpenRC
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (4, 1, 0, '/etc/resolv.conf', 'nameserver {DNS1}
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (3, 1, 0, '/etc/resolv.conf', 'nameserver {DNS1}
 nameserver {DNS2}', '');
 nameserver {DNS2}', '');
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (4, 1, 0, '/etc/conf.d/net', 'config_eth0="{IP}/{NETMASK}"
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (3, 1, 1, '/etc/conf.d/net', 'config_eth0="{IP}/{NETMASK}"
 routes_eth0="default via {GATEWAY}"', '');
 routes_eth0="default via {GATEWAY}"', '');
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (4, 1, 0, '/etc/conf.d/hostname', 'hostname="{HOSTNAME}"', '');
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (3, 1, 2, '/etc/conf.d/hostname', 'hostname="{HOSTNAME}"', '');
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (3, 0, 3, '', '', 'echo "root:{PASSWORD}" | chpasswd');
 
 
 -- For Windows
 -- For Windows
-INSERT INTO operate_rule (boot_job_id, kind, sequence, path, content, command) VALUES (5, 1, 0, '/Windows/jimv_init.bat', 'netsh interface ip set address name="Ethernet" source=static {IP} {NETMASK} {GATEWAY}
+INSERT INTO os_template_initialize_operate (os_template_initialize_operate_set_id, kind, sequence, path, content, command) VALUES (4, 1, 0, '/Windows/jimv_init.bat', 'netsh interface ip set address name="Ethernet" source=static {IP} {NETMASK} {GATEWAY}
 netsh interface ip set dns "Ethernet" static {DNS1} primary
 netsh interface ip set dns "Ethernet" static {DNS1} primary
 netsh interface ip add dns "Ethernet" {DNS2}
 netsh interface ip add dns "Ethernet" {DNS2}
 wmic computersystem where name="%COMPUTERNAME%" call rename name="{HOSTNAME}"
 wmic computersystem where name="%COMPUTERNAME%" call rename name="{HOSTNAME}"
@@ -382,3 +412,12 @@ del C:\\Windows\\jimv_init.bat
 timeout 2 > NUL
 timeout 2 > NUL
 shutdown -r -t 0', '');
 shutdown -r -t 0', '');
 
 
+
+INSERT INTO os_template_profile (label, describe, os_type, os_distro, os_major, os_minor, os_arch, os_product_name, active, icon, os_template_initialize_operate_set_id)
+VALUES ('CentOS-7.4', 'CentOS 7.4。', 'linux', 'centos', 7, 4, 'x86_64', 'CentOS Linux release 7.4.1708 (Core)', 1, 'icon-os icon-os-centos', 1);
+INSERT INTO os_template_profile (label, describe, os_type, os_distro, os_major, os_minor, os_arch, os_product_name, active, icon, os_template_initialize_operate_set_id)
+VALUES ('CentOS-6.8', 'CentOS 6.8。', 'linux', 'centos', 6, 8, 'x86_64', 'CentOS release 6.8 (Final)', 1, 'icon-os icon-os-centos', 2);
+INSERT INTO os_template_profile (label, describe, os_type, os_distro, os_major, os_minor, os_arch, os_product_name, active, icon, os_template_initialize_operate_set_id)
+VALUES ('Gentoo-2.2', 'Gentoo 2.2。', 'linux', 'gentoo', 2, 2, 'x86_64', 'Gentoo Base System release 2.2', 1, 'icon-os icon-os-gentoo', 3);
+INSERT INTO os_template_profile (label, describe, os_type, os_distro, os_major, os_minor, os_arch, os_product_name, active, icon, os_template_initialize_operate_set_id)
+VALUES ('Windows-2012-R2-Standard', 'Windows 2012 R2 Standard。', 'windows', 'windows', 6, 3, 'x86_64', 'Windows Server 2012 R2 Standard', 1, 'icon-os icon-os-gentoo', 4);

+ 17 - 0
models/__init__.py

@@ -47,6 +47,22 @@ from os_template import (
     OSTemplate
     OSTemplate
 )
 )
 
 
+from os_template_image import (
+    OSTemplateImage
+)
+
+from os_template_profile import (
+    OSTemplateProfile
+)
+
+from os_template_initialize_operate_set import (
+    OSTemplateInitializeOperateSet
+)
+
+from os_template_initialize_operate import (
+    OSTemplateInitializeOperate
+)
+
 from status import (
 from status import (
     EmitKind,
     EmitKind,
     GuestState,
     GuestState,
@@ -94,6 +110,7 @@ __copyright__ = '(c) 2017 by James Iter.'
 __all__ = [
 __all__ = [
     'Rules', 'Utils', 'Init', 'Database', 'FilterFieldType', 'Filter', 'EmitKind', 'GuestState', 'DiskState', 'OSType',
     'Rules', 'Utils', 'Init', 'Database', 'FilterFieldType', 'Filter', 'EmitKind', 'GuestState', 'DiskState', 'OSType',
     'LogLevel', 'ORM', 'User', 'Config', 'Guest', 'Disk', 'BootJob', 'OperateRule', 'OSTemplate', 'GuestXML', 'Log',
     'LogLevel', 'ORM', 'User', 'Config', 'Guest', 'Disk', 'BootJob', 'OperateRule', 'OSTemplate', 'GuestXML', 'Log',
+    'OSTemplateImage', 'OSTemplateProfile', 'OSTemplateInitializeOperateSet', 'OSTemplateInitializeOperate',
     'EventProcessor', 'ResponseState', 'GuestCPUMemory', 'GuestTraffic', 'GuestDiskIO', 'HostCPUMemory', 'HostTraffic',
     'EventProcessor', 'ResponseState', 'GuestCPUMemory', 'GuestTraffic', 'GuestDiskIO', 'HostCPUMemory', 'HostTraffic',
     'HostDiskUsageIO', 'Host'
     'HostDiskUsageIO', 'Host'
 ]
 ]

+ 42 - 0
models/os_template_image.py

@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+from models import FilterFieldType
+from models import ORM
+
+
+__author__ = 'James Iter'
+__date__ = '2018/2/4'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2018 by James Iter.'
+
+
+class OSTemplateImage(ORM):
+
+    _table_name = 'os_template_image'
+    _primary_key = 'id'
+
+    def __init__(self):
+        super(OSTemplateImage, self).__init__()
+        self.id = 0
+        self.os_template_profile_id = None
+        self.path = None
+        self.active = True
+
+    @staticmethod
+    def get_filter_keywords():
+        return {
+            'id': FilterFieldType.INT.value,
+            'os_template_profile_id': FilterFieldType.INT.value,
+            'path': FilterFieldType.STR.value,
+            'active': FilterFieldType.INT.value
+        }
+
+    @staticmethod
+    def get_allow_update_keywords():
+        return []
+
+    @staticmethod
+    def get_allow_content_search_keywords():
+        return ['path']

+ 48 - 0
models/os_template_initialize_operate.py

@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+from models import FilterFieldType
+from models import ORM
+
+
+__author__ = 'James Iter'
+__date__ = '2018/2/4'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2018 by James Iter.'
+
+
+class OSTemplateInitializeOperate(ORM):
+
+    _table_name = 'os_template_initialize_operate'
+    _primary_key = 'id'
+
+    def __init__(self):
+        super(OSTemplateInitializeOperate, self).__init__()
+        self.id = 0
+        self.os_template_initialize_operate_set_id = None
+        self.kind = None
+        self.sequence = None
+        self.path = None
+        self.content = None
+        self.command = None
+
+    @staticmethod
+    def get_filter_keywords():
+        return {
+            'id': FilterFieldType.INT.value,
+            'os_template_initialize_operate_set_id': FilterFieldType.INT.value,
+            'sequence': FilterFieldType.INT.value,
+            'command': FilterFieldType.STR.value,
+            'path': FilterFieldType.STR.value,
+            'content': FilterFieldType.STR.value,
+        }
+
+    @staticmethod
+    def get_allow_update_keywords():
+        return ['os_template_initialize_operate_set_id']
+
+    @staticmethod
+    def get_allow_content_search_keywords():
+        return ['command', 'path', 'content']
+

+ 42 - 0
models/os_template_initialize_operate_set.py

@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+from models import FilterFieldType
+from models import ORM
+
+
+__author__ = 'James Iter'
+__date__ = '2018/2/4'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2018 by James Iter.'
+
+
+class OSTemplateInitializeOperateSet(ORM):
+
+    _table_name = 'os_template_initialize_operate_set'
+    _primary_key = 'id'
+
+    def __init__(self):
+        super(OSTemplateInitializeOperateSet, self).__init__()
+        self.id = 0
+        self.label = None
+        self.describe = ''
+        self.active = True
+
+    @staticmethod
+    def get_filter_keywords():
+        return {
+            'id': FilterFieldType.INT.value,
+            'label': FilterFieldType.STR.value,
+            'active': FilterFieldType.INT.value
+        }
+
+    @staticmethod
+    def get_allow_update_keywords():
+        return []
+
+    @staticmethod
+    def get_allow_content_search_keywords():
+        return ['label']
+

+ 54 - 0
models/os_template_profile.py

@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
+from models import FilterFieldType
+from models import ORM
+
+
+__author__ = 'James Iter'
+__date__ = '2018/2/4'
+__contact__ = 'james.iter.cn@gmail.com'
+__copyright__ = '(c) 2018 by James Iter.'
+
+
+class OSTemplateProfile(ORM):
+
+    _table_name = 'os_template_profile'
+    _primary_key = 'id'
+
+    def __init__(self):
+        super(OSTemplateProfile, self).__init__()
+        self.id = 0
+        self.label = None
+        self.describe = ''
+        self.os_type = None
+        self.os_distro = None
+        self.os_major = None
+        self.os_minor = None
+        self.os_arch = None
+        self.os_product_name = None
+        self.active = True
+        self.icon = None
+        self.os_template_initialize_operate_set_id = None
+
+    @staticmethod
+    def get_filter_keywords():
+        return {
+            'id': FilterFieldType.INT.value,
+            'label': FilterFieldType.STR.value,
+            'os_type': FilterFieldType.STR.value,
+            'os_distro': FilterFieldType.STR.value,
+            'os_product_name': FilterFieldType.STR.value,
+            'os_template_initialize_operate_set_id': FilterFieldType.INT.value,
+            'active': FilterFieldType.INT.value
+        }
+
+    @staticmethod
+    def get_allow_update_keywords():
+        return ['os_type', 'os_distro', 'os_arch', 'active', 'icon', 'os_template_initialize_operate_set_id']
+
+    @staticmethod
+    def get_allow_content_search_keywords():
+        return ['label', 'os_type', 'os_distro', 'os_product_name']
+

+ 15 - 1
models/rules.py

@@ -86,11 +86,25 @@ class Rules(Enum):
     REMARK = (basestring, 'remark')
     REMARK = (basestring, 'remark')
     USE_FOR = (int, 'use_for')
     USE_FOR = (int, 'use_for')
     LABEL = (basestring, 'label')
     LABEL = (basestring, 'label')
-    OS_TYPE = (int, 'os_type')
+    DESCRIBE = (basestring, 'describe')
+    OS_TYPE = (basestring, 'os_type')
+    OS_DISTRO = (basestring, 'os_distro')
+    OS_MAJOR = (int, 'os_major')
+    OS_MINOR = (int, 'os_minor')
+    OS_ARCH = (basestring, 'os_arch')
+    OS_PRODUCT_NAME = (basestring, 'os_product_name')
     ACTIVE = (bool, 'active')
     ACTIVE = (bool, 'active')
     ICON = (basestring, 'icon')
     ICON = (basestring, 'icon')
 
 
     BOOT_JOB_ID_EXT = (int, 'boot_job_id')
     BOOT_JOB_ID_EXT = (int, 'boot_job_id')
+    OS_TEMPLATE_PROFILE_ID_EXT = (int, 'os_template_profile_id')
+    OS_TEMPLATE_INITIALIZE_OPERATE_SET_ID_EXT = (int, 'os_template_initialize_operate_set_id')
+    OS_TEMPLATE_INITIALIZE_OPERATE_KIND = (int, 'kind')
+    OS_TEMPLATE_INITIALIZE_OPERATE_SEQUENCE = (int, 'sequence')
+    OS_TEMPLATE_INITIALIZE_OPERATE_PATH = (basestring, 'path')
+    OS_TEMPLATE_INITIALIZE_OPERATE_CONTENT = (basestring, 'content')
+    OS_TEMPLATE_INITIALIZE_OPERATE_COMMAND = (basestring, 'command')
+
     OPERATE_RULE_KIND = (int, 'kind')
     OPERATE_RULE_KIND = (int, 'kind')
     OPERATE_RULE_SEQUENCE = (int, 'sequence')
     OPERATE_RULE_SEQUENCE = (int, 'sequence')
     OPERATE_RULE_PATH = (basestring, 'path')
     OPERATE_RULE_PATH = (basestring, 'path')

+ 6 - 0
models/status.py

@@ -91,6 +91,12 @@ class OperateRuleKind(IntEnum):
     append_file = 2
     append_file = 2
 
 
 
 
+class OSTemplateInitializeOperateKind(IntEnum):
+    cmd = 0
+    write_file = 1
+    append_file = 2
+
+
 class GuestCollectionPerformanceDataKind(IntEnum):
 class GuestCollectionPerformanceDataKind(IntEnum):
     cpu_memory = 0
     cpu_memory = 0
     traffic = 1
     traffic = 1

+ 3 - 3
templates/os_templates_show.html

@@ -734,10 +734,10 @@
                         </div>
                         </div>
                         <div class="form-group">
                         <div class="form-group">
                             <div class="col-sm-2"></div>
                             <div class="col-sm-2"></div>
-                            <label class="col-sm-2 control-label"><span class="glyph-icon icon-bookmark-o"></span>&nbsp;&nbsp;操作系统类型</label>
+                            <label class="col-sm-2 control-label"><span class="glyph-icon icon-bookmark-o"></span>&nbsp;&nbsp;模板系统类型</label>
                             <div class="col-sm-6">
                             <div class="col-sm-6">
-                                <select id="os_type" name="os_type" title="操作系统类型" class="selectpicker">
-                                    <option value="0" selected>Linux</option>
+                                <select id="os_type" name="os_type" title="请选择模板系统类型" class="selectpicker">
+                                    <option value="0">Linux</option>
                                     <option value="1">Windows</option>
                                     <option value="1">Windows</option>
                                     <option value="2">BSD</option>
                                     <option value="2">BSD</option>
                                     <option value="3">AIX</option>
                                     <option value="3">AIX</option>