Răsfoiți Sursa

加入批量添加启动作业功能

James Iter 9 ani în urmă
părinte
comite
fec3adc1be
6 a modificat fișierele cu 118 adăugiri și 6 ștergeri
  1. 12 0
      api/guest.py
  2. 1 0
      api_route_table.py
  3. 3 0
      docs/todo.md
  4. 9 0
      models/guest.py
  5. 85 0
      templates/guest_show.html
  6. 8 6
      views/disk.py

+ 12 - 0
api/guest.py

@@ -742,6 +742,18 @@ def r_delete_boot_jobs(uuids, boot_jobs_id):
         return json.loads(e.message)
         return json.loads(e.message)
 
 
 
 
+@Utils.dumps2response
+def r_get_uuids_of_all_had_boot_job():
+    guest = Guest()
+    try:
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        ret['data'] = guest.get_uuids_of_all_had_boot_job()
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
 @Utils.dumps2response
 @Utils.dumps2response
 def r_reset_password(uuids, password):
 def r_reset_password(uuids, password):
 
 

+ 1 - 0
api_route_table.py

@@ -71,6 +71,7 @@ add_rule_api(guest.blueprints, '/_boot_jobs/<uuids>/<boot_jobs_id>', api_func='g
 add_rule_api(guest.blueprints, '/_boot_jobs/<uuids>', api_func='guest.r_get_boot_jobs', methods=['GET'])
 add_rule_api(guest.blueprints, '/_boot_jobs/<uuids>', api_func='guest.r_get_boot_jobs', methods=['GET'])
 add_rule_api(guest.blueprints, '/_boot_jobs/<uuids>/<boot_jobs_id>', api_func='guest.r_delete_boot_jobs',
 add_rule_api(guest.blueprints, '/_boot_jobs/<uuids>/<boot_jobs_id>', api_func='guest.r_delete_boot_jobs',
              methods=['DELETE'])
              methods=['DELETE'])
+add_rule_api(guest.blueprints, '/_boot_jobs/uuids', api_func='guest.r_get_uuids_of_all_had_boot_job', methods=['GET'])
 add_rule_api(guest.blueprints, '/_reset_password/<uuids>/<password>', api_func='guest.r_reset_password',
 add_rule_api(guest.blueprints, '/_reset_password/<uuids>/<password>', api_func='guest.r_reset_password',
              methods=['PUT'])
              methods=['PUT'])
 
 

+ 3 - 0
docs/todo.md

@@ -15,7 +15,10 @@
 - [ ] 增加模板镜像上传功能
 - [ ] 增加模板镜像上传功能
 - [x] 虚拟机加入用户级的重启作业功能
 - [x] 虚拟机加入用户级的重启作业功能
 - [ ] 提示待做的启动作业
 - [ ] 提示待做的启动作业
+- [ ] 加入 tag 功能
 - [ ] 收集存在于 JimV-N,却不存在于 JimV-C 的 Guest
 - [ ] 收集存在于 JimV-N,却不存在于 JimV-C 的 Guest
+- [ ] 批量添加启动作业
+- [ ] 单独写页面展现已有启动作业的虚拟机列表
 - [x] 磁盘页面,默认不显示系统盘,加 CheckBox 来控制
 - [x] 磁盘页面,默认不显示系统盘,加 CheckBox 来控制
 - [x] 不显示系统级别的启动作业
 - [x] 不显示系统级别的启动作业
 - [ ] 添加对 Guest 的IP管理功能
 - [ ] 添加对 Guest 的IP管理功能

+ 9 - 0
models/guest.py

@@ -90,6 +90,15 @@ class Guest(ORM):
         if db.r.exists(key):
         if db.r.exists(key):
             db.r.expire(key, app.config['guest_boot_jobs_wait_time'])
             db.r.expire(key, app.config['guest_boot_jobs_wait_time'])
 
 
+    @staticmethod
+    def get_uuids_of_all_had_boot_job():
+        boot_job_keys = db.r.keys(pattern=app.config['guest_boot_jobs'] + '*')
+        uuids = list()
+        for boot_job_key in boot_job_keys:
+            uuids.append(boot_job_key.split(':')[-1])
+
+        return uuids
+
 
 
 class Disk(ORM):
 class Disk(ORM):
 
 

+ 85 - 0
templates/guest_show.html

@@ -166,6 +166,10 @@
             $('#reset_password_instance_uuid').val(
             $('#reset_password_instance_uuid').val(
                 $(me.relatedTarget).parent().parent().parent().parent().parent().children()[0].textContent);
                 $(me.relatedTarget).parent().parent().parent().parent().parent().children()[0].textContent);
         });
         });
+
+        $('#add_boot_job_modal').on('show.bs.modal', function (me) {
+            refresh_boot_job_selectpicker($('#boot_job_selector'));
+        });
     });
     });
 
 
     function refresh() {
     function refresh() {
@@ -179,6 +183,26 @@
         window.location.href=cur_url;
         window.location.href=cur_url;
     }
     }
 
 
+    function refresh_boot_job_selectpicker(selectpicker) {
+        $.ajax({
+            url : '/api/boot_jobs?filter=use_for:eq:2',
+            type : 'GET',
+            contentType: "application/json; charset=utf-8",
+            dataType: 'json',
+            error : function() {
+            },
+            success : function(data, textStatus, xhr) {
+                selectpicker.empty();
+                $.each(data.data, function(k, v) {
+                    selectpicker.append(
+                        $('<option>', {value: v['id'], text: v['name'], 'data-subtext': v['remark']})
+                    );
+                });
+                selectpicker.selectpicker('refresh');
+            }
+        });
+    }
+
     function row_onmouseover(me) {
     function row_onmouseover(me) {
         $(me).find(".edit_remark_trigger").css('display','inline-flex');
         $(me).find(".edit_remark_trigger").css('display','inline-flex');
     }
     }
@@ -389,6 +413,21 @@
         });
         });
     }
     }
 
 
+    function add_boot_job(uuids, boot_job_id) {
+        $.ajax({
+            url : '/api/guests/_boot_jobs/' + uuids.join(',') + '/' + boot_job_id,
+            type : 'PUT',
+            contentType: "application/json; charset=utf-8",
+            error : function() {
+                alter_danger('启动作业添加指令发送失败!');
+            },
+            success : function() {
+                alter_success('启动作业添加指令发送成功!');
+                refresh();
+            }
+        });
+    }
+
     function boot_at(me) {
     function boot_at(me) {
         var uuid = $(me).parent().parent().parent().parent().parent().children()[0].textContent;
         var uuid = $(me).parent().parent().parent().parent().parent().children()[0].textContent;
         boot([uuid]);
         boot([uuid]);
@@ -533,6 +572,15 @@
             remove(uuids);
             remove(uuids);
         }
         }
     }
     }
+
+    function batch_add_boot_job() {
+        var uuids = get_checked_uuids();
+        var boot_job_id = $('#boot_job_selector').val();
+        if (uuids) {
+            add_boot_job(uuids, boot_job_id);
+        }
+        $('#add_boot_job_modal').modal('hide');
+    }
 </script>
 </script>
 <div class="panel">
 <div class="panel">
     <div class="panel-body">
     <div class="panel-body">
@@ -687,6 +735,12 @@
                                                 </a>
                                                 </a>
                                             </li>
                                             </li>
                                             <li class="divider"></li>
                                             <li class="divider"></li>
+                                            <li>
+                                                <a href="javascript:;" data-toggle="modal" data-target="#add_boot_job_modal">
+                                                    启动作业
+                                                </a>
+                                            </li>
+                                            <li class="divider"></li>
                                             <li>
                                             <li>
                                                 <a href="javascript:;" onclick="batch_force_shutdown();">强制停止</a>
                                                 <a href="javascript:;" onclick="batch_force_shutdown();">强制停止</a>
                                             </li>
                                             </li>
@@ -789,4 +843,35 @@
         </div>
         </div>
     </div>
     </div>
 </div>
 </div>
+
+<div class="modal" id="add_boot_job_modal" tabindex="-1" role="dialog" style="margin-top: 100px;">
+    <div class="modal-dialog modal-lg">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h4 class="modal-title">添加启动作业:</h4>
+            </div>
+            <div class="modal-body" style="padding-top: 0; padding-bottom: 0;">
+                <div class="example-box-wrapper">
+                    <form class="form-horizontal bordered-row">
+                        <div class="form-group">
+                            <div class="col-sm-2"></div>
+                            <label class="col-sm-2 control-label"><span class="glyph-icon icon-list-alt"></span>&nbsp;&nbsp;启动作业</label>
+                            <div class="col-sm-6">
+                                <select id="boot_job_selector" name="boot_job_selector" title="启动作业" class="selectpicker">
+                                </select>
+                            </div>
+                        </div>
+                        <div class="form-group">
+                            <div class="col-sm-4"></div>
+                            <div class="col-sm-6 pull-right">
+                                <button class="btn btn-blue-alt" style="width: 180px; height: 40px; font-size: 16px;" onclick="batch_add_boot_job();">添加</button>
+                                <button class="btn btn-default" style="width: 64px; height: 40px; font-size: 16px;" data-dismiss="modal">取消</button>
+                            </div>
+                        </div>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
 {% endblock content %}
 {% endblock content %}

+ 8 - 6
views/disk.py

@@ -49,6 +49,14 @@ def show():
     if keyword is not None:
     if keyword is not None:
         args.append('keyword=' + keyword.__str__())
         args.append('keyword=' + keyword.__str__())
 
 
+    if guest_uuid is not None:
+        filters.append('guest_uuid:in:' + guest_uuid.__str__())
+        show_area = 'all'
+
+    if sequence is not None:
+        filters.append('sequence:in:' + sequence.__str__())
+        show_area = 'all'
+
     if show_area in ['unmount', 'data_disk', 'all']:
     if show_area in ['unmount', 'data_disk', 'all']:
         if show_area == 'unmount':
         if show_area == 'unmount':
             filters.append('sequence:eq:-1')
             filters.append('sequence:eq:-1')
@@ -63,12 +71,6 @@ def show():
         # 与前端页面相照应,首次打开时,默认只显示未挂载的磁盘
         # 与前端页面相照应,首次打开时,默认只显示未挂载的磁盘
         filters.append('sequence:eq:-1')
         filters.append('sequence:eq:-1')
 
 
-    if guest_uuid is not None:
-        filters.append('guest_uuid:in:' + guest_uuid.__str__())
-
-    if sequence is not None:
-        filters.append('sequence:in:' + sequence.__str__())
-
     if order_by is not None:
     if order_by is not None:
         args.append('order_by=' + order_by)
         args.append('order_by=' + order_by)