Просмотр исходного кода

更新文档,加入磁盘部分

James Iter 9 лет назад
Родитель
Сommit
f31f9ccf93
10 измененных файлов с 573 добавлено и 109 удалено
  1. 7 3
      README.md
  2. 328 0
      docs/disk.md
  3. 19 17
      docs/enum.md
  4. 74 0
      docs/guest.md
  5. 1 0
      docs/screenshot.md
  6. 3 1
      models/event_processor.py
  7. 2 1
      route_table.py
  8. 78 61
      tests/test_disk.py
  9. 19 11
      tests/test_guest.py
  10. 42 15
      views/disk.py

+ 7 - 3
README.md

@@ -21,8 +21,9 @@
 - [API](#api)
     - [[状态码参考列表](docs/state_code.md)](#状态码参考列表)
     - [[过滤器操作符原语](docs/filter_primitive.md)](#过滤器操作符原语)
-    - [[Guest](docs/guest.md)](#guest)
     - [[状态列表](docs/enum.md)](#状态列表)
+    - [[Guest](docs/guest.md)](#guest)
+    - [[磁盘](docs/disk.md)](#磁盘)
 - [流程图](#流程图)
 - [Web端](#web端)
 - [问题反馈](#问题反馈)
@@ -123,7 +124,7 @@ mysql -u jimv -pyour_jimv_db_password -e 'show databases'
 | SESSION_FILE_THRESHOLD     | 1000                 | 存放的session超过该数量,之前的将被删除           |
 | SESSION_COOKIE_NAME        | sid                  | session id在客户端cookie中的存放名称            |
 | SESSION_COOKIE_SECURE      | false                | cookie的传输是否只在https的环境中进行            |
-| **`SECRET_KEY`**                                 || session安全码                                 |
+| **`SECRET_KEY`**           |                      | session安全码                                 |
 | PERMANENT_SESSION_LIFETIME | 604800               | cookie在客户端的持久化时间。该值需与token_ttl相同 |
 | vm_create_queue            | Q:VMCreate           | 创建虚拟机的队列                               |
 | host_event_report_queue    | Q:HostEvent          | 宿主机事件上抛队列                              |
@@ -203,9 +204,12 @@ gunicorn -c gunicorn_config.py main:app
 
 ### [过滤器操作符原语](docs/filter_primitive.md)
 
+### [状态列表](docs/enum.md)
+
 ### [Guest](docs/guest.md)
 
-### [状态列表](docs/enum.md)
+### [磁盘](docs/disk.md)
+
 
 
 ## 流程图

+ 328 - 0
docs/disk.md

@@ -0,0 +1,328 @@
+# Disk
+
+[TOC]: # " 目录"
+
+# 目录
+- [创建磁盘](#创建磁盘)
+- [磁盘扩容](#磁盘扩容)
+- [获取磁盘信息](#获取磁盘信息)
+- [更新磁盘信息](#更新磁盘信息)
+- [获取磁盘列表](#获取磁盘列表)
+- [磁盘全文检索](#磁盘全文检索)
+- [删除磁盘](#删除磁盘)
+
+
+## 创建磁盘
+
+> 创建磁盘
+
+```http
+POST https://$domain
+  /api/disk
+Body:
+{
+    "size": 4
+}
+```
+
+| 参数名称 | 必须 | 类型 | 说明             |
+|:-------:|:---:|:----:|:-----------------|
+|  size   |  Y  | Long | 磁盘大小,单位`GB` |
+
+响应示例
+
+```json
+{
+    "state": {
+        "en-us": "OK",
+        "zh-cn": "成功",
+        "code": "200"
+    }
+}
+```
+
+
+## 磁盘扩容
+
+> 磁盘扩容
+
+```http
+PUT https://$domain
+  /api/disk/_disk_resize/{uuid}/{size}
+```
+
+| 参数名称 | 必须 |  类型  | 说明            |
+|:-------:|:---:|:------:|:----------------|
+|  uuid   |  Y  | String | 磁盘的uuid       |
+|  size   |  Y  |  Long  | 扩容至,单位`GB` |
+
+响应示例
+
+```json
+{
+    "state": {
+        "en-us": "OK",
+        "zh-cn": "成功",
+        "code": "200"
+    }
+}
+```
+
+
+## 获取磁盘信息
+
+> 获取指定 UUID 的磁盘信息
+
+```http
+GET https://$domain
+  /api/disk/{uuid}
+```
+
+| 参数名称 | 必须 |  类型  | 说明            |
+|:-------:|:---:|:------:|:----------------|
+|  uuid   |  Y  | String | 磁盘的uuid       |
+
+响应示例
+
+```json
+{
+    "state": {
+        "en-us": "OK",
+        "zh-cn": "成功",
+        "code": "200"
+    },
+    "data": {
+        "guest_uuid": "",
+        "uuid": "fff8aead-3206-4820-8c98-146178a91cce",
+        "sequence": -1,
+        "format": "qcow2",
+        "label": "Hello-disk",
+        "state": 1,
+        "id": 42,
+        "size": 200
+    }
+}
+```
+
+| 参数名称    | 必须 |  类型  | 说明                                                  |
+|:-----------|:---:|:------:|:------------------------------------------------------|
+| id         |  Y  |  Long  | 磁盘 ID                                               |
+| uuid       |  Y  | String | 磁盘 UUID                                             |
+| label      |  Y  | String | 磁盘标注信息                                           |
+| size       |  Y  |  Long  | 磁盘大小                                               |
+| sequence   |  Y  |  Long  | 磁盘在某个 Guest 实例中的序列                            |
+| format     |  Y  | String | 磁盘镜像格式,默认 qcow2                                |
+| state      |  Y  |  Long  | 磁盘当前状态,可用状态值请参考 [磁盘状态](enum.md#磁盘状态) |
+| guest_uuid |  Y  | String | 当前磁盘被使用的 Guest 实例                             |
+
+
+## 更新磁盘信息
+
+> 更改指定 uuid 的磁盘信息
+
+```http
+PATCH https://$domain
+  /api/disk/{uuid}
+Body:
+{
+    "label": "desc"
+}
+```
+
+| 参数名称 | 必须 |  类型  | 说明 |
+|:--------|:---:|:------:|:-----|
+| label   |  Y  | String | 标注 |
+
+响应示例
+
+```json
+{
+    "state": {
+        "en-us": "OK",
+        "zh-cn": "成功",
+        "code": "200"
+    },
+    "data": {
+        "guest_uuid": "",
+        "uuid": "fff8aead-3206-4820-8c98-146178a91cce",
+        "format": "qcow2",
+        "sequence": -1,
+        "label": "Hello-disk",
+        "state": 0,
+        "id": 42,
+        "size": 10
+    }
+}
+```
+
+磁盘信息字段描述参见 [获取磁盘信息](#获取磁盘信息)
+
+
+## 获取磁盘列表
+
+> 获取磁盘列表
+
+```http
+GET https://$domain
+  /api/disks?offset={number}&limit={number}
+  or
+  /api/disks?page={number}&page_size={number}
+```
+
+|  参数名称  | 必须 |  类型  | 说明                                        |
+|:---------:|:---:|:------:|:--------------------------------------------|
+|  offset   |  N  | Number | 偏移量, 默认值0                              |
+|   limit   |  N  | Number | 返回条目数量, 默认值50                        |
+|   page    |  N  | Number | 页号, 与offset同时存在时, 以offset为准, 默认值1 |
+| page_size |  N  | Number | 页大小, 默认值50                             |
+| order_by  |  N  | String | 所依据的字段                                 |
+|   order   |  N  |  Enum  | 排序策略,`asc`\|`desc`                      |
+
+响应示例
+
+```json
+{
+    "state": {
+        "en-us": "OK",
+        "zh-cn": "成功",
+        "code": "200"
+    },
+    "data": [{
+        "guest_uuid": "",
+        "uuid": "5844e2cb-56c5-4b02-98b5-ee606bfbe3b3",
+        "sequence": -1,
+        "format": "qcow2",
+        "label": "82QUZJGJ",
+        "state": 0,
+        "id": 22,
+        "size": 10
+    }, {
+       "more": "more"
+    }, {
+        "guest_uuid": "",
+        "uuid": "fff8aead-3206-4820-8c98-146178a91cce",
+        "sequence": -1,
+        "format": "qcow2",
+        "label": "qhDCp3E8",
+        "state": 0,
+        "id": 42,
+        "size": 10
+    }],
+    "paging": {
+        "prev": "http://127.0.0.1:8008/api/disks?page=1&page_size=50&filter=&order=asc&order_by=id",
+        "last": "http://127.0.0.1:8008/api/disks?page=1&page_size=50&filter=&order=asc&order_by=id",
+        "page_size": 50,
+        "next": "http://127.0.0.1:8008/api/disks?page=1&page_size=50&filter=&order=asc&order_by=id",
+        "limit": 50,
+        "offset": 0,
+        "total": 10,
+        "page": 1,
+        "first": "http://127.0.0.1:8008/api/disks?page=1&page_size=50&filter=&order=asc&order_by=id"
+    }
+}
+```
+
+| 参数名称   | 必须 |  类型  | 说明                                            |
+|:----------|:---:|:------:|:------------------------------------------------|
+| total     |  Y  | Number | 用户总量                                         |
+| offset    |  Y  | Number | 当前偏移量                                       |
+| limit     |  Y  | Number | 返回条目数量                                     |
+| page      |  Y  | Number | 透传客户端请求的该参数, 如果没有传递, 则返回默认值1   |
+| page_size |  Y  | Number | 透传客户端请求的该参数, 如果没有传递, 则返回默认值 50 |
+
+磁盘信息字段描述参见 [获取磁盘信息](#获取磁盘信息)
+
+
+## 磁盘全文检索
+
+> 根据关键字查找磁盘信息
+
+```http
+GET https://$domain
+  /api/disks/_search?offset={number}&limit={number}&keyword=hello
+  or
+  /api/disks/_search?page={number}&page_size={number}&keyword=hello
+```
+
+| 参数名称   | 必须 |  类型  | 说明                                        |
+|:----------|:---:|:------:|:--------------------------------------------|
+| offset    |  N  | Number | 偏移量, 默认值0                              |
+| limit     |  N  | Number | 返回条目数量, 默认值50                        |
+| page      |  N  | Number | 页号, 与offset同时存在时, 以offset为准, 默认值1 |
+| page_size |  N  | Number | 页大小, 默认值50                             |
+| order_by  |  N  | String | 所依据的字段                                 |
+| order     |  N  |  Enum  | 排序策略,`asc`\|`desc`                      |
+| keyword   |  N  | String | 全文检索的关键字                              |
+
+响应示例
+
+```json
+{
+    "state": {
+        "en-us": "OK",
+        "zh-cn": "成功",
+        "code": "200"
+    },
+    "data": [{
+        "guest_uuid": "",
+        "uuid": "fff8aead-3206-4820-8c98-146178a91cce",
+        "sequence": -1,
+        "format": "qcow2",
+        "label": "Hello-disk",
+        "state": 1,
+        "id": 42,
+        "size": 200
+    }],
+    "paging": {
+        "prev": "http://127.0.0.1:8008/api/disks/_search?page=1&page_size=50&keyword=hello&order=asc&order_by=id",
+        "last": "http://127.0.0.1:8008/api/disks/_search?page=1&page_size=50&keyword=hello&order=asc&order_by=id",
+        "page_size": 50,
+        "next": "http://127.0.0.1:8008/api/disks/_search?page=1&page_size=50&keyword=hello&order=asc&order_by=id",
+        "limit": 50,
+        "offset": 0,
+        "total": 1,
+        "page": 1,
+        "first": "http://127.0.0.1:8008/api/disks/_search?page=1&page_size=50&keyword=hello&order=asc&order_by=id"
+    }
+}
+```
+
+| 参数名称   | 必须 |  类型  | 说明                                            |
+|:----------|:---:|:------:|:------------------------------------------------|
+| total     |  Y  | Number | 用户总量                                         |
+| offset    |  Y  | Number | 当前偏移量                                       |
+| limit     |  Y  | Number | 返回条目数量                                     |
+| page      |  Y  | Number | 透传客户端请求的该参数, 如果没有传递, 则返回默认值1   |
+| page_size |  Y  | Number | 透传客户端请求的该参数, 如果没有传递, 则返回默认值 50 |
+
+磁盘信息字段描述参见 [获取磁盘信息](#获取磁盘信息)
+
+
+## 删除磁盘
+
+> 删除指定 uuid 的磁盘
+
+```http
+DELETE https://$domain
+  /api/disks/{uuids}
+```
+
+| 参数名称 | 必须 |  类型  | 说明                                           |
+|:--------|:---:|:------:|:-----------------------------------------------|
+| uuids   |  Y  | String | uuids可为多个或单个uuid。多个磁盘的uuid以逗号间隔。 |
+
+响应示例
+
+```json
+{
+    "state": {
+        "en-us": "OK",
+        "zh-cn": "成功",
+        "code": "200"
+    }
+}
+```
+
+
+[返回上一级](../README.md)
+=====================

+ 19 - 17
docs/enum.md

@@ -8,24 +8,26 @@
 
 
 ## Guest 状态
-|状态|值|描述|
-|:--:|:--:|:--:|
-|no_state|0|无任何状态,一般是在创建Guest时会出现。|
-|running|1|Guest运行中。|
-|blocked|2|Guest阻塞。|
-|paused|3|Guest被暂停。|
-|shutdown|4|Guest关机状态。|
-|shutoff|5|Guest切断电源状态。|
-|crashed|6|Guest奔溃状态。|
-|pm_suspended|7|电源被悬挂。|
-|dirty|255|Guest现场被弄脏,需要清理。|
+
+|     状态      | 值  | 描述                                |
+|:------------:|:---:|:-----------------------------------|
+|   no_state   |  0  | 无任何状态,一般是在创建Guest时会出现。 |
+|   running    |  1  | Guest运行中。                       |
+|   blocked    |  2  | Guest阻塞。                         |
+|    paused    |  3  | Guest被暂停。                       |
+|   shutdown   |  4  | Guest关机状态。                     |
+|   shutoff    |  5  | Guest切断电源状态。                  |
+|   crashed    |  6  | Guest奔溃状态。                     |
+| pm_suspended |  7  | 电源被悬挂。                         |
+|    dirty     | 255 | Guest现场被弄脏,需要清理。           |
 
 
 ## 磁盘状态
-|状态|值|描述|
-|:--:|:--:|:--:|
-|pending|0|创建磁盘时的未决状态。|
-|idle|1|空闲状态,未被任何Guest使用。|
-|mounted|2|已经被某个Guest所挂载。|
-|dirty|255|磁盘创建失败,需要被清理。|
+
+|   状态   | 值  | 描述                        |
+|:-------:|:---:|:---------------------------|
+| pending |  0  | 创建磁盘时的未决状态。        |
+|  idle   |  1  | 空闲状态,未被任何Guest使用。 |
+| mounted |  2  | 已经被某个Guest所挂载。       |
+|  dirty  | 255 | 磁盘创建失败,需要被清理。     |
 

+ 74 - 0
docs/guest.md

@@ -203,6 +203,80 @@ GET https://$domain
 Guest 信息字段描述参见 [获取 Guest 信息](#获取-guest-信息)
 
 
+## Guest 全文检索
+
+> 根据关键字查找 Guest
+
+```http
+GET https://$domain
+  /api/guests/_search?offset={number}&limit={number}&keyword=10.10.4
+  or
+  /api/guests/_search?page={number}&page_size={number}&keyword=10.10.4
+```
+
+| 参数名称   | 必须 |  类型  | 说明                                        |
+|:----------|:---:|:------:|:--------------------------------------------|
+| offset    |  N  | Number | 偏移量, 默认值0                              |
+| limit     |  N  | Number | 返回条目数量, 默认值50                        |
+| page      |  N  | Number | 页号, 与offset同时存在时, 以offset为准, 默认值1 |
+| page_size |  N  | Number | 页大小, 默认值50                             |
+| order_by  |  N  | String | 所依据的字段                                 |
+| order     |  N  |  Enum  | 排序策略,`asc`\|`desc`                      |
+| keyword   |  N  | String | 全文检索的关键字                              |
+
+响应示例
+
+```json
+{
+    "state": {
+        "en-us": "OK",
+        "zh-cn": "成功",
+        "code": "200"
+    },
+    "data": [{
+        "status": 1,
+        "xml": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n            <domain type=\"kvm\">\n            \n            <features>\n                <acpi/>\n                <apic/>\n            </features>\n        \n            <name>wCbjmsDZ</name>\n            <uuid>ba102b41-4e7a-4d5b-a9e0-43d162695e4a</uuid>\n            <vcpu>4</vcpu>\n            <memory unit=\"GiB\">4</memory>\n            \n            <os>\n                <boot dev=\"hd\"/>\n                <type arch=\"x86_64\">hvm</type>\n                <bootmenu timeout=\"3000\" enable=\"yes\"/>\n            </os>\n        \n            \n            <devices>\n                \n            <interface type='network'>\n                <source network='net-br0'/>\n                <model type='virtio'/>\n            </interface>\n        \n                \n                <disk type='network' device='disk'>\n                    <driver name='qemu' type='qcow2' cache='none'/>\n                    <source protocol='gluster' name='gv0/VMs/wCbjmsDZ/f279a8d4-dc3c-42b7-8f57-54ddcd0bd361.qcow2'>\n                        <host name='127.0.0.1' port='24007'/>\n                    </source>\n                    <target dev='vda' bus='virtio'/>\n                </disk>\n        \n                \n            <graphics passwd=\"VDFsVLMLR9yvM5fS\" keymap=\"en-us\" port=\"16347\" type=\"vnc\">\n                <listen network=\"net-br0\" type=\"network\"/>\n            </graphics>\n        \n                \n            <serial type='pty'>\n                <target port='0'/>\n            </serial>\n            <console type='pty'>\n                <target type='serial' port='0'/>\n            </console>\n        \n            </devices>\n        \n            </domain>\n        ",
+        "remark": "zabbix",
+        "name": "wCbjmsDZ",
+        "os_template_id": 1,
+        "ip": "10.10.4.31",
+        "vnc_port": 16347,
+        "uuid": "ba102b41-4e7a-4d5b-a9e0-43d162695e4a",
+        "cpu": 4,
+        "create_time": 1494950937330417,
+        "manage_network": "net-br0",
+        "memory": 4,
+        "id": 18,
+        "password": "pswd.com",
+        "on_host": "10k01.jkser.com",
+        "vnc_password": "VDFsVLMLR9yvM5fS",
+        "network": "net-br0"
+    }],
+    "paging": {
+        "prev": "http://127.0.0.1:8008/api/guests/_search?page=1&page_size=50&keyword=10.10.4&order=asc&order_by=id",
+        "last": "http://127.0.0.1:8008/api/guests/_search?page=1&page_size=50&keyword=10.10.4&order=asc&order_by=id",
+        "page_size": 50,
+        "next": "http://127.0.0.1:8008/api/guests/_search?page=1&page_size=50&keyword=10.10.4&order=asc&order_by=id",
+        "limit": 50,
+        "offset": 0,
+        "total": 1,
+        "page": 1,
+        "first": "http://127.0.0.1:8008/api/guests/_search?page=1&page_size=50&keyword=10.10.4&order=asc&order_by=id"
+    }
+}
+```
+
+| 参数名称   | 必须 |  类型  | 说明                                            |
+|:----------|:---:|:------:|:------------------------------------------------|
+| total     |  Y  | Number | 用户总量                                         |
+| offset    |  Y  | Number | 当前偏移量                                       |
+| limit     |  Y  | Number | 返回条目数量                                     |
+| page      |  Y  | Number | 透传客户端请求的该参数, 如果没有传递, 则返回默认值1   |
+| page_size |  Y  | Number | 透传客户端请求的该参数, 如果没有传递, 则返回默认值 50 |
+
+Guest 信息字段描述参见 [获取 Guest 信息](#获取-guest-信息)
+
+
 ## 更改 Guest 信息
 
 > 更改指定 uuid 的 Guest 信息

+ 1 - 0
docs/screenshot.md

@@ -0,0 +1 @@
+# Web端程序截图

+ 3 - 1
models/event_processor.py

@@ -101,7 +101,9 @@ class EventProcessor(object):
                 cls.disk.update()
 
         elif action == 'delete_disk':
-            pass
+            cls.disk.uuid = uuid
+            cls.disk.get_by('uuid')
+            cls.disk.delete()
 
         else:
             pass

+ 2 - 1
route_table.py

@@ -63,8 +63,9 @@ add_rule(guest.blueprints, '/<uuids>', view_func='guest.r_delete', methods=['DEL
 # Disk操作
 add_rule(disk.blueprint, '', view_func='disk.r_create', methods=['POST'])
 add_rule(disk.blueprint, '/_disk_resize/<uuid>/<size>', view_func='disk.r_resize', methods=['PUT'])
-add_rule(disk.blueprint, '/<uuid>', view_func='disk.r_delete', methods=['DELETE'])
+add_rule(disk.blueprints, '/<uuids>', view_func='disk.r_delete', methods=['DELETE'])
 add_rule(disk.blueprint, '/<uuid>', view_func='disk.r_update', methods=['PATCH'])
+add_rule(disk.blueprint, '/<uuid>', view_func='disk.r_get', methods=['GET'])
 add_rule(disk.blueprints, '', view_func='disk.r_get_by_filter', methods=['GET'])
 add_rule(disk.blueprints, '/_search', view_func='disk.r_content_search', methods=['GET'])
 

+ 78 - 61
tests/test_disk.py

@@ -26,85 +26,102 @@ class TestDisk(unittest.TestCase):
     def tearDown(self):
         pass
 
-    # # 创建 Disk
-    # def test_11_create(self):
-    #     payload = {
-    #         "size": 10
-    #     }
-    #
-    #     url = TestDisk.base_url + '/disk'
+    # 创建 Disk
+    def test_11_create(self):
+        payload = {
+            "size": 10
+        }
+
+        url = TestDisk.base_url + '/disk'
+        headers = {'content-type': 'application/json'}
+        r = requests.post(url, data=json.dumps(payload), headers=headers)
+        j_r = json.loads(r.content)
+        print json.dumps(j_r, ensure_ascii=False)
+        self.assertEqual('200', j_r['state']['code'])
+
+    def test_12_get_list(self):
+        url = TestDisk.base_url + '/disks'
+        headers = {'content-type': 'application/json'}
+        r = requests.get(url, headers=headers)
+        j_r = json.loads(r.content)
+        print json.dumps(j_r, ensure_ascii=False)
+        TestDisk.uuid = j_r['data'][-1]['uuid']
+        self.assertEqual('200', j_r['state']['code'])
+        for disk in j_r['data']:
+            TestDisk.uuid_list.append(disk['uuid'])
+
+    # @unittest.skip('skip resize disk')
+    def test_13_disk_resize(self):
+        url = TestDisk.base_url + '/disk/_disk_resize/' + TestDisk.uuid + '/' + TestDisk.new_size.__str__()
+        headers = {'content-type': 'application/json'}
+        r = requests.put(url, headers=headers)
+        j_r = json.loads(r.content)
+        print json.dumps(j_r, ensure_ascii=False)
+        self.assertEqual('200', j_r['state']['code'])
+
+    # @unittest.skip('skip update disk')
+    def test_14_update(self):
+        payload = {
+            "label": "Hello-disk"
+        }
+
+        url = TestDisk.base_url + '/disk/' + TestDisk.uuid
+        headers = {'content-type': 'application/json'}
+        r = requests.patch(url, data=json.dumps(payload), headers=headers)
+        j_r = json.loads(r.content)
+        print json.dumps(j_r, ensure_ascii=False)
+        self.assertEqual('200', j_r['state']['code'])
+
+    # 校验更新结果
+    # @unittest.skip('skip get disk')
+    # def test_15_get(self):
+    #     TestDisk.uuid = 'fff8aead-3206-4820-8c98-146178a91cce'
+    #     url = TestDisk.base_url + '/disk/' + TestDisk.uuid
     #     headers = {'content-type': 'application/json'}
-    #     r = requests.post(url, data=json.dumps(payload), headers=headers)
+    #     r = requests.get(url, headers=headers)
     #     j_r = json.loads(r.content)
     #     print json.dumps(j_r, ensure_ascii=False)
     #     self.assertEqual('200', j_r['state']['code'])
-    #
-    # def test_12_get(self):
-    #     url = TestDisk.base_url + '/disks'
+    #     self.assertEqual(TestDisk.new_size, j_r['data']['size'])
+    #     self.assertEqual('Hello-disk', j_r['data']['label'])
+
+    # def test_16_content_search(self):
+    #     url = TestDisk.base_url + '/disks/_search?keyword=hello'
     #     headers = {'content-type': 'application/json'}
     #     r = requests.get(url, headers=headers)
     #     j_r = json.loads(r.content)
     #     print json.dumps(j_r, ensure_ascii=False)
-    #     TestDisk.uuid = j_r['data'][0]['uuid']
     #     self.assertEqual('200', j_r['state']['code'])
-    #
-    # # @unittest.skip('skip resize disk')
-    # def test_13_disk_resize(self):
-    #     url = TestDisk.base_url + '/disk/_disk_resize/' + TestDisk.uuid + '/' + TestDisk.new_size.__str__()
+
+    # def test_17_detach_disk(self):
+    #     url = TestDisk.base_url + '/guest/_detach_disk/' + '49aab662-abdd-4338-bcde-60a70020daa0'
     #     headers = {'content-type': 'application/json'}
     #     r = requests.put(url, headers=headers)
     #     j_r = json.loads(r.content)
     #     print json.dumps(j_r, ensure_ascii=False)
     #     self.assertEqual('200', j_r['state']['code'])
-    #
-    # # @unittest.skip('skip update disk')
-    # def test_14_update(self):
-    #     payload = {
-    #         "label": "Hello-disk"
-    #     }
-    #
-    #     url = TestDisk.base_url + '/disk/' + TestDisk.uuid
-    #     headers = {'content-type': 'application/json'}
-    #     r = requests.patch(url, data=json.dumps(payload), headers=headers)
-    #     j_r = json.loads(r.content)
-    #     print json.dumps(j_r, ensure_ascii=False)
-    #     self.assertEqual('200', j_r['state']['code'])
-    #
-    # # 校验更新结果
-    # # @unittest.skip('skip get disk')
-    # def test_15_get(self):
-    #     url = TestDisk.base_url + '/disks'
-    #     headers = {'content-type': 'application/json'}
-    #     r = requests.get(url, headers=headers)
-    #     j_r = json.loads(r.content)
-    #     print json.dumps(j_r, ensure_ascii=False)
-    #     self.assertEqual('200', j_r['state']['code'])
-    #     self.assertEqual(TestDisk.new_size, j_r['data'][0]['size'])
-    #     self.assertEqual('Hello-disk', j_r['data'][0]['label'])
-    #     for disk in j_r['data']:
-    #         TestDisk.uuid_list.append(disk['uuid'])
-
-    def test_16_detach_disk(self):
-        url = TestDisk.base_url + '/guest/_detach_disk/' + '49aab662-abdd-4338-bcde-60a70020daa0'
-        headers = {'content-type': 'application/json'}
-        r = requests.put(url, headers=headers)
-        j_r = json.loads(r.content)
-        print json.dumps(j_r, ensure_ascii=False)
-        self.assertEqual('200', j_r['state']['code'])
 
     # 删除Guest
     # @unittest.skip('skip delete disk')
-    def test_17_delete(self):
-        TestDisk.uuid_list.append('49aab662-abdd-4338-bcde-60a70020daa0')
-        for uuid in TestDisk.uuid_list:
-            TestDisk.uuid = uuid
-            url = TestDisk.base_url + '/disk/' + TestDisk.uuid
-            headers = {'content-type': 'application/json'}
-            r = requests.delete(url, headers=headers)
-            j_r = json.loads(r.content)
-            print json.dumps(j_r, ensure_ascii=False)
-            self.assertEqual('200', j_r['state']['code'])
+    # def test_18_delete(self):
+    #     TestDisk.uuid_list.append('49aab662-abdd-4338-bcde-60a70020daa0')
+    #     for uuid in TestDisk.uuid_list:
+    #         TestDisk.uuid = uuid
+    #         url = TestDisk.base_url + '/disk/' + TestDisk.uuid
+    #         headers = {'content-type': 'application/json'}
+    #         r = requests.delete(url, headers=headers)
+    #         j_r = json.loads(r.content)
+    #         print json.dumps(j_r, ensure_ascii=False)
+    #         self.assertEqual('200', j_r['state']['code'])
 
+    # def test_60_delete(self):
+    #     TestDisk.uuid = 'fff8aead-3206-4820-8c98-146178a91cce'
+    #     url = TestDisk.base_url + '/disks/' + TestDisk.uuid
+    #     headers = {'content-type': 'application/json'}
+    #     r = requests.delete(url, headers=headers)
+    #     j_r = json.loads(r.content)
+    #     print json.dumps(j_r, ensure_ascii=False)
+    #     self.assertEqual('200', j_r['state']['code'])
 
 if __name__ == '__main__':
     unittest.main()

+ 19 - 11
tests/test_guest.py

@@ -46,14 +46,14 @@ class TestGuest(unittest.TestCase):
     #     self.assertEqual('200', j_r['state']['code'])
 
     # 获取 Guest 列表
-    def test_12_get_list(self):
-        url = TestGuest.base_url + '/guests'
-        headers = {'content-type': 'application/json'}
-        r = requests.get(url, headers=headers)
-        j_r = json.loads(r.content)
-        print json.dumps(j_r, ensure_ascii=False)
-        TestGuest.uuid = j_r['data'][-1]['uuid']
-        self.assertEqual('200', j_r['state']['code'])
+    # def test_12_get_list(self):
+    #     url = TestGuest.base_url + '/guests'
+    #     headers = {'content-type': 'application/json'}
+    #     r = requests.get(url, headers=headers)
+    #     j_r = json.loads(r.content)
+    #     print json.dumps(j_r, ensure_ascii=False)
+    #     TestGuest.uuid = j_r['data'][-1]['uuid']
+    #     self.assertEqual('200', j_r['state']['code'])
 
     # # 获取指定 Guest
     # def test_13_get(self):
@@ -235,10 +235,18 @@ class TestGuest(unittest.TestCase):
     #     print json.dumps(j_r, ensure_ascii=False)
     #     self.assertEqual('200', j_r['state']['code'])
 
-    def test_61_migrate(self):
-        url = TestGuest.base_url + '/guests/_migrate/' + TestGuest.uuid + '/10k02.jkser.com'
+    # def test_61_migrate(self):
+    #     url = TestGuest.base_url + '/guests/_migrate/' + TestGuest.uuid + '/10k02.jkser.com'
+    #     headers = {'content-type': 'application/json'}
+    #     r = requests.put(url, headers=headers)
+    #     j_r = json.loads(r.content)
+    #     print json.dumps(j_r, ensure_ascii=False)
+    #     self.assertEqual('200', j_r['state']['code'])
+
+    def test_62_content_search(self):
+        url = TestGuest.base_url + '/guests/_search?keyword=10.10.4'
         headers = {'content-type': 'application/json'}
-        r = requests.put(url, headers=headers)
+        r = requests.get(url, headers=headers)
         j_r = json.loads(r.content)
         print json.dumps(j_r, ensure_ascii=False)
         self.assertEqual('200', j_r['state']['code'])

+ 42 - 15
views/disk.py

@@ -7,7 +7,7 @@ import json
 from uuid import uuid4
 import jimit as ji
 
-from models import Guest
+from models import Guest, DiskState
 from models.initialize import app, dev_table
 from models import Database as db
 from models import Config
@@ -132,36 +132,43 @@ def r_resize(uuid, size):
 
 
 @Utils.dumps2response
-def r_delete(uuid):
+def r_delete(uuids):
 
     args_rules = [
-        Rules.UUID.value
+        Rules.UUIDS.value
     ]
 
     try:
-        ji.Check.previewing(args_rules, {'uuid': uuid})
-
-        guest_disk = GuestDisk()
-        guest_disk.uuid = uuid
-        guest_disk.get_by('uuid')
+        ji.Check.previewing(args_rules, {'uuids': uuids})
 
         ret = dict()
         ret['state'] = ji.Common.exchange_state(20000)
 
-        if guest_disk.guest_uuid.__len__() > 0:
-            ret['state'] = ji.Common.exchange_state(41256)
-            return ret
+        guest_disk = GuestDisk()
+
+        # 检测所指定的 UUDIs 磁盘都存在
+        for uuid in uuids.split(','):
+            guest_disk.uuid = uuid
+            guest_disk.get_by('uuid')
+
+            if guest_disk.state != DiskState.idle.value:
+                ret['state'] = ji.Common.exchange_state(41256)
+                return ret
 
         config = Config()
         config.id = 1
         config.get()
 
-        image_path = '/'.join(['DiskPool', guest_disk.uuid + '.' + guest_disk.format])
+        # 执行删除操作
+        for uuid in uuids.split(','):
+            guest_disk.uuid = uuid
+            guest_disk.get_by('uuid')
 
-        message = {'action': 'delete_disk', 'glusterfs_volume': config.glusterfs_volume, 'image_path': image_path}
-        db.r.rpush(app.config['downstream_queue'], json.dumps(message, ensure_ascii=False))
+            image_path = '/'.join(['DiskPool', guest_disk.uuid + '.' + guest_disk.format])
 
-        guest_disk.delete()
+            message = {'action': 'delete_disk', 'uuid': guest_disk.uuid,
+                       'glusterfs_volume': config.glusterfs_volume, 'image_path': image_path}
+            db.r.rpush(app.config['downstream_queue'], json.dumps(message, ensure_ascii=False))
 
         return ret
 
@@ -169,6 +176,26 @@ def r_delete(uuid):
         return json.loads(e.message)
 
 
+@Utils.dumps2response
+def r_get(uuid):
+    guest_disk = GuestDisk()
+
+    args_rules = [
+        Rules.UUID.value
+    ]
+    guest_disk.uuid = uuid
+
+    try:
+        ji.Check.previewing(args_rules, guest_disk.__dict__)
+        guest_disk.get_by('uuid')
+        ret = dict()
+        ret['state'] = ji.Common.exchange_state(20000)
+        ret['data'] = guest_disk.__dict__
+        return ret
+    except ji.PreviewingError, e:
+        return json.loads(e.message)
+
+
 @Utils.dumps2response
 def r_get_by_filter():
     page = str(request.args.get('page', 1))