openstack虚拟机resize源码分析

文章目录

resize过程python-client端debug

[root@openstack-con01 ~(keystone_admin)]# nova --debug resize 2001bdd5-8a2e-4ff4-b8fc-8a5eff066728  2  --poll
DEBUG (session:195) REQ: curl -g -i -X GET http://10.10.10.250:35357/v2.0/ -H "Accept: application/json" -H "User-Agent: python-keystoneclient"
INFO (connectionpool:203) Starting new HTTP connection (1): 10.10.10.250
DEBUG (connectionpool:383) "GET /v2.0/ HTTP/1.1" 200 339
DEBUG (session:224) RESP: [200] content-length: 339 vary: X-Auth-Token keep-alive: timeout=5, max=100 server: Apache/2.4.6 (CentOS) mod_wsgi/3.4 Python/2.7.5 connection: Keep-Alive date: Thu, 30 Aug 2018 11:28:07 GMT content-type: application/json x-openstack-request-id: req-84389041-c201-4869-acb0-0ca92945582f
RESP BODY: {"version": {"status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}], "id": "v2.0", "links": [{"href": "http://10.10.10.250:35357/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/", "type": "text/html", "rel": "describedby"}]}}

DEBUG (v2:76) Making authentication request to http://10.10.10.250:35357/v2.0/tokens
DEBUG (connectionpool:383) "POST /v2.0/tokens HTTP/1.1" 200 3484
DEBUG (session:195) REQ: curl -g -i -X GET http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}c963302cb137a44f36fa62c50c39fff3462d7e34"
INFO (connectionpool:203) Starting new HTTP connection (1): 10.10.10.250
DEBUG (connectionpool:383) "GET /v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 HTTP/1.1" 200 1751
DEBUG (session:224) RESP: [200] date: Thu, 30 Aug 2018 11:28:08 GMT connection: keep-alive content-type: application/json content-length: 1751 x-compute-request-id: req-7e7ea726-5479-4c92-b3d5-173bc9651338
RESP BODY: {"server": {"OS-EXT-STS:task_state": null, "addresses": {"tstack-vxlan-network": [{"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:fd:06:74", "version": 4, "addr": "172.16.0.105", "OS-EXT-IPS:type": "fixed"}]}, "links": [{"href": "http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "rel": "self"}, {"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "rel": "bookmark"}], "image": {"id": "0be3adcf-181b-4c8a-a5f4-657e972497d8", "links": [{"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/images/0be3adcf-181b-4c8a-a5f4-657e972497d8", "rel": "bookmark"}]}, "OS-EXT-STS:vm_state": "active", "OS-EXT-SRV-ATTR:instance_name": "instance-00000009", "OS-SRV-USG:launched_at": "2018-08-30T10:35:43.000000", "flavor": {"id": "1", "links": [{"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/flavors/1", "rel": "bookmark"}]}, "id": "2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "security_groups": [{"name": "default"}], "user_id": "33f84664ac69496ea4cdfb7166fbf416", "OS-DCF:diskConfig": "MANUAL", "accessIPv4": "", "accessIPv6": "", "progress": 0, "OS-EXT-STS:power_state": 1, "region_node_id": "REGION_FYD_1", "config_drive": "", "status": "ACTIVE", "updated": "2018-08-30T11:26:24Z", "hostId": "1b346db001405aa020eb63097240a58b546291e1464c4a3dad66e6b3", "OS-EXT-SRV-ATTR:host": "openstack-compute01", "OS-SRV-USG:terminated_at": null, "key_name": null, "OS-EXT-AZ:availability_zone": "nova", "OS-EXT-SRV-ATTR:hypervisor_hostname": "openstack-compute01", "name": "cirros_test", "created": "2018-08-30T10:35:32Z", "tenant_id": "b045010ed16147c680a368fd23d96272", "os-extended-volumes:volumes_attached": [], "metadata": {}}}

DEBUG (session:195) REQ: curl -g -i -X GET http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/flavors/2 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}c963302cb137a44f36fa62c50c39fff3462d7e34"
DEBUG (connectionpool:383) "GET /v2/b045010ed16147c680a368fd23d96272/flavors/2 HTTP/1.1" 200 425
DEBUG (session:224) RESP: [200] date: Thu, 30 Aug 2018 11:28:08 GMT connection: keep-alive content-type: application/json content-length: 425 x-compute-request-id: req-1ca47c75-1ab2-4d27-bec8-f92a03184fdf
RESP BODY: {"flavor": {"name": "m1.small", "links": [{"href": "http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/flavors/2", "rel": "self"}, {"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/flavors/2", "rel": "bookmark"}], "ram": 2048, "OS-FLV-DISABLED:disabled": false, "vcpus": 1, "swap": "", "os-flavor-access:is_public": true, "rxtx_factor": 1.0, "OS-FLV-EXT-DATA:ephemeral": 0, "disk": 20, "id": "2"}}

DEBUG (session:195) REQ: curl -g -i -X POST http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728/action -H "User-Agent: python-novaclient" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}c963302cb137a44f36fa62c50c39fff3462d7e34" -d '{"resize": {"flavorRef": "2"}}'
DEBUG (connectionpool:383) "POST /v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728/action HTTP/1.1" 202 0
DEBUG (session:224) RESP: [202] date: Thu, 30 Aug 2018 11:28:09 GMT connection: keep-alive content-type: text/html; charset=UTF-8 content-length: 0 x-compute-request-id: req-b4aa00c0-0065-47d8-a3e8-9631fc0651f7

DEBUG (session:195) REQ: curl -g -i -X GET http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}c963302cb137a44f36fa62c50c39fff3462d7e34"
DEBUG (connectionpool:383) "GET /v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 HTTP/1.1" 200 1760
DEBUG (session:224) RESP: [200] date: Thu, 30 Aug 2018 11:28:09 GMT connection: keep-alive content-type: application/json content-length: 1760 x-compute-request-id: req-87854e93-4156-4291-92f8-b9b9cbd97822
RESP BODY: {"server": {"OS-EXT-STS:task_state": "resize_prep", "addresses": {"tstack-vxlan-network": [{"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:fd:06:74", "version": 4, "addr": "172.16.0.105", "OS-EXT-IPS:type": "fixed"}]}, "links": [{"href": "http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "rel": "self"}, {"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "rel": "bookmark"}], "image": {"id": "0be3adcf-181b-4c8a-a5f4-657e972497d8", "links": [{"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/images/0be3adcf-181b-4c8a-a5f4-657e972497d8", "rel": "bookmark"}]}, "OS-EXT-STS:vm_state": "active", "OS-EXT-SRV-ATTR:instance_name": "instance-00000009", "OS-SRV-USG:launched_at": "2018-08-30T10:35:43.000000", "flavor": {"id": "1", "links": [{"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/flavors/1", "rel": "bookmark"}]}, "id": "2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "security_groups": [{"name": "default"}], "user_id": "33f84664ac69496ea4cdfb7166fbf416", "OS-DCF:diskConfig": "MANUAL", "accessIPv4": "", "accessIPv6": "", "progress": 0, "OS-EXT-STS:power_state": 1, "region_node_id": "REGION_FYD_1", "config_drive": "", "status": "RESIZE", "updated": "2018-08-30T11:28:09Z", "hostId": "1b346db001405aa020eb63097240a58b546291e1464c4a3dad66e6b3", "OS-EXT-SRV-ATTR:host": "openstack-compute01", "OS-SRV-USG:terminated_at": null, "key_name": null, "OS-EXT-AZ:availability_zone": "nova", "OS-EXT-SRV-ATTR:hypervisor_hostname": "openstack-compute01", "name": "cirros_test", "created": "2018-08-30T10:35:32Z", "tenant_id": "b045010ed16147c680a368fd23d96272", "os-extended-volumes:volumes_attached": [], "metadata": {}}}

Server resizing... 0% completeDEBUG (session:195) REQ: curl -g -i -X GET http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}c963302cb137a44f36fa62c50c39fff3462d7e34"
DEBUG (connectionpool:383) "GET /v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 HTTP/1.1" 200 1762
DEBUG (session:224) RESP: [200] date: Thu, 30 Aug 2018 11:28:14 GMT connection: keep-alive content-type: application/json content-length: 1762 x-compute-request-id: req-f2b70226-044b-4848-b5e3-ca1a3367ed8a
RESP BODY: {"server": {"OS-EXT-STS:task_state": "resize_finish", "addresses": {"tstack-vxlan-network": [{"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:fd:06:74", "version": 4, "addr": "172.16.0.105", "OS-EXT-IPS:type": "fixed"}]}, "links": [{"href": "http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "rel": "self"}, {"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "rel": "bookmark"}], "image": {"id": "0be3adcf-181b-4c8a-a5f4-657e972497d8", "links": [{"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/images/0be3adcf-181b-4c8a-a5f4-657e972497d8", "rel": "bookmark"}]}, "OS-EXT-STS:vm_state": "active", "OS-EXT-SRV-ATTR:instance_name": "instance-00000009", "OS-SRV-USG:launched_at": "2018-08-30T10:35:43.000000", "flavor": {"id": "2", "links": [{"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/flavors/2", "rel": "bookmark"}]}, "id": "2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "security_groups": [{"name": "default"}], "user_id": "33f84664ac69496ea4cdfb7166fbf416", "OS-DCF:diskConfig": "MANUAL", "accessIPv4": "", "accessIPv6": "", "progress": 0, "OS-EXT-STS:power_state": 1, "region_node_id": "REGION_FYD_1", "config_drive": "", "status": "RESIZE", "updated": "2018-08-30T11:28:14Z", "hostId": "1b346db001405aa020eb63097240a58b546291e1464c4a3dad66e6b3", "OS-EXT-SRV-ATTR:host": "openstack-compute01", "OS-SRV-USG:terminated_at": null, "key_name": null, "OS-EXT-AZ:availability_zone": "nova", "OS-EXT-SRV-ATTR:hypervisor_hostname": "openstack-compute01", "name": "cirros_test", "created": "2018-08-30T10:35:32Z", "tenant_id": "b045010ed16147c680a368fd23d96272", "os-extended-volumes:volumes_attached": [], "metadata": {}}}

Server resizing... 0% completeDEBUG (session:195) REQ: curl -g -i -X GET http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}c963302cb137a44f36fa62c50c39fff3462d7e34"
DEBUG (connectionpool:383) "GET /v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 HTTP/1.1" 200 1759
DEBUG (session:224) RESP: [200] date: Thu, 30 Aug 2018 11:28:20 GMT connection: keep-alive content-type: application/json content-length: 1759 x-compute-request-id: req-c6701531-517a-4c76-a841-b3369cfd3e58
RESP BODY: {"server": {"OS-EXT-STS:task_state": null, "addresses": {"tstack-vxlan-network": [{"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:fd:06:74", "version": 4, "addr": "172.16.0.105", "OS-EXT-IPS:type": "fixed"}]}, "links": [{"href": "http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "rel": "self"}, {"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "rel": "bookmark"}], "image": {"id": "0be3adcf-181b-4c8a-a5f4-657e972497d8", "links": [{"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/images/0be3adcf-181b-4c8a-a5f4-657e972497d8", "rel": "bookmark"}]}, "OS-EXT-STS:vm_state": "resized", "OS-EXT-SRV-ATTR:instance_name": "instance-00000009", "OS-SRV-USG:launched_at": "2018-08-30T11:28:15.000000", "flavor": {"id": "2", "links": [{"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/flavors/2", "rel": "bookmark"}]}, "id": "2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "security_groups": [{"name": "default"}], "user_id": "33f84664ac69496ea4cdfb7166fbf416", "OS-DCF:diskConfig": "MANUAL", "accessIPv4": "", "accessIPv6": "", "progress": 0, "OS-EXT-STS:power_state": 1, "region_node_id": "REGION_FYD_1", "config_drive": "", "status": "VERIFY_RESIZE", "updated": "2018-08-30T11:28:15Z", "hostId": "1b346db001405aa020eb63097240a58b546291e1464c4a3dad66e6b3", "OS-EXT-SRV-ATTR:host": "openstack-compute01", "OS-SRV-USG:terminated_at": null, "key_name": null, "OS-EXT-AZ:availability_zone": "nova", "OS-EXT-SRV-ATTR:hypervisor_hostname": "openstack-compute01", "name": "cirros_test", "created": "2018-08-30T10:35:32Z", "tenant_id": "b045010ed16147c680a368fd23d96272", "os-extended-volumes:volumes_attached": [], "metadata": {}}}

Server resizing... 100% complete
Finished
[root@openstack-con01 ~(keystone_admin)]# nova list
+--------------------------------------+-------------+---------------+------------+-------------+-----------------------------------+
| ID                                   | Name        | Status        | Task State | Power State | Networks                          |
+--------------------------------------+-------------+---------------+------------+-------------+-----------------------------------+
| 2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 | cirros_test | VERIFY_RESIZE | -          | Running     | tstack-vxlan-network=172.16.0.105 |
+--------------------------------------+-------------+---------------+------------+-------------+-----------------------------------+

[root@openstack-con01 ~(keystone_admin)]# nova --debug  resize-confirm 2001bdd5-8a2e-4ff4-b8fc-8a5eff066728
DEBUG (session:195) REQ: curl -g -i -X GET http://10.10.10.250:35357/v2.0/ -H "Accept: application/json" -H "User-Agent: python-keystoneclient"
INFO (connectionpool:203) Starting new HTTP connection (1): 10.10.10.250
DEBUG (connectionpool:383) "GET /v2.0/ HTTP/1.1" 200 339
DEBUG (session:224) RESP: [200] content-length: 339 vary: X-Auth-Token keep-alive: timeout=5, max=100 server: Apache/2.4.6 (CentOS) mod_wsgi/3.4 Python/2.7.5 connection: Keep-Alive date: Thu, 30 Aug 2018 11:41:52 GMT content-type: application/json x-openstack-request-id: req-bad6820b-800a-498f-b758-d81ae7cb2a3f
RESP BODY: {"version": {"status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}], "id": "v2.0", "links": [{"href": "http://10.10.10.250:35357/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/", "type": "text/html", "rel": "describedby"}]}}

DEBUG (v2:76) Making authentication request to http://10.10.10.250:35357/v2.0/tokens
DEBUG (connectionpool:383) "POST /v2.0/tokens HTTP/1.1" 200 3484
DEBUG (session:195) REQ: curl -g -i -X GET http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}ad997cb2eabbfb8ed4e469f296470180e21a4526"
INFO (connectionpool:203) Starting new HTTP connection (1): 10.10.10.250
DEBUG (connectionpool:383) "GET /v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 HTTP/1.1" 200 1759
DEBUG (session:224) RESP: [200] date: Thu, 30 Aug 2018 11:41:53 GMT connection: keep-alive content-type: application/json content-length: 1759 x-compute-request-id: req-cb70e06c-2364-4b01-966a-eb5de997d934
RESP BODY: {"server": {"OS-EXT-STS:task_state": null, "addresses": {"tstack-vxlan-network": [{"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:fd:06:74", "version": 4, "addr": "172.16.0.105", "OS-EXT-IPS:type": "fixed"}]}, "links": [{"href": "http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "rel": "self"}, {"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "rel": "bookmark"}], "image": {"id": "0be3adcf-181b-4c8a-a5f4-657e972497d8", "links": [{"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/images/0be3adcf-181b-4c8a-a5f4-657e972497d8", "rel": "bookmark"}]}, "OS-EXT-STS:vm_state": "resized", "OS-EXT-SRV-ATTR:instance_name": "instance-00000009", "OS-SRV-USG:launched_at": "2018-08-30T11:40:48.000000", "flavor": {"id": "3", "links": [{"href": "http://10.10.10.250:8774/b045010ed16147c680a368fd23d96272/flavors/3", "rel": "bookmark"}]}, "id": "2001bdd5-8a2e-4ff4-b8fc-8a5eff066728", "security_groups": [{"name": "default"}], "user_id": "33f84664ac69496ea4cdfb7166fbf416", "OS-DCF:diskConfig": "MANUAL", "accessIPv4": "", "accessIPv6": "", "progress": 0, "OS-EXT-STS:power_state": 1, "region_node_id": "REGION_FYD_1", "config_drive": "", "status": "VERIFY_RESIZE", "updated": "2018-08-30T19:44:58Z", "hostId": "1b346db001405aa020eb63097240a58b546291e1464c4a3dad66e6b3", "OS-EXT-SRV-ATTR:host": "openstack-compute01", "OS-SRV-USG:terminated_at": null, "key_name": null, "OS-EXT-AZ:availability_zone": "nova", "OS-EXT-SRV-ATTR:hypervisor_hostname": "openstack-compute01", "name": "cirros_test", "created": "2018-08-30T10:35:32Z", "tenant_id": "b045010ed16147c680a368fd23d96272", "os-extended-volumes:volumes_attached": [], "metadata": {}}}

DEBUG (session:195) REQ: curl -g -i -X POST http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728/action -H "User-Agent: python-novaclient" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}ad997cb2eabbfb8ed4e469f296470180e21a4526" -d '{"confirmResize": null}'
DEBUG (connectionpool:383) "POST /v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728/action HTTP/1.1" 204 0
DEBUG (session:224) RESP: [204] date: Thu, 30 Aug 2018 11:41:53 GMT connection: keep-alive content-type: application/json content-length: 0 x-compute-request-id: req-cf558e26-888b-4596-9af3-31b02905e4ba

debug分析

### resize过程

获取keystone版本详情

curl -g -i -X GET http://10.10.10.250:35357/v2.0/ -H "Accept: application/json" -H "User-Agent: python-keystoneclient"

验证admin信息并生成token

DEBUG (connectionpool:383) "POST /v2.0/tokens HTTP/1.1" 200 3484

带着token去请求虚拟机信息

curl -g -i -X GET http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}c963302cb137a44f36fa62c50c39fff3462d7e34"
# 格式为 /v2/​{tenant_id}​/servers/​{server_id}​

带着token去获取resizede的目标flavor

curl -g -i -X GET http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/flavors/2 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}c963302cb137a44f36fa62c50c39fff3462d7e34"

发送调整实例请求

curl -g -i -X POST http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728/action -H "User-Agent: python-novaclient" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}c963302cb137a44f36fa62c50c39fff3462d7e34" -d '{"resize": {"flavorRef": "2"}}'
# 格式为/v2/​{tenant_id}​/servers/action
# 行为json参数为
#{
#  "resize": {
#      "flavorRef": "2"
#  }
#}

再次获取虚拟机信息 监控服务器状态 直到状态改变为VERIFY_RESIZE 结束这个任务

curl -g -i -X GET http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}c963302cb137a44f36fa62c50c39fff3462d7e34"

resize confirm过程

获取keystone版本信息

curl -g -i -X GET http://10.10.10.250:35357/v2.0/ -H "Accept: application/json" -H "User-Agent: python-keystoneclient"

验证admin信息并生成token

curl -g -i -X GET http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728 -H "User-Agent: python-novaclient" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}ad997cb2eabbfb8ed4e469f296470180e21a4526"

带着token去执行resize-confirm请求

curl -g -i -X POST http://10.10.10.250:8774/v2/b045010ed16147c680a368fd23d96272/servers/2001bdd5-8a2e-4ff4-b8fc-8a5eff066728/action -H "User-Agent: python-novaclient" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token: {SHA1}ad997cb2eabbfb8ed4e469f296470180e21a4526" -d '{"confirmResize": null}'
# 请求参数json格式
#{
#    "confirmResize": null
#}

在v2 api中 基本上所有的外部请求都要先去keystone验证身份 然后从keystone获取一个token 拿着这个token再去做其他行为

resize过程源码分析

控制节点


通过源码地图setup.cfg可以知道nova api实现的代码路径nova/api/openstack/compute/servers.py (一次rpc调用nova-api到compute-api)

def _resize(self, req, instance_id, flavor_id, **kwargs):
    """Begin the resize process with given instance/flavor.
    输入参数说明如下:
    req:Request:对象,包含本次请求的上下文
    instance_id:实例id
    flavor_id:机型id
    **kwargs:其他参数字典
    """

    #得到上下文,根据上下文去获取虚拟机得具体信息
    context = req.environ["nova.context"]
    instance = self._get_server(context, req, instance_id)
    try:
        self.compute_api.resize(context, instance, flavor_id, **kwargs)
   # 异常部分省略
    ...

    return webob.Response(status_int=202)

接上文 nova/compute/api.py

def resize(self, context, instance, flavor_id=None, clean_shutdown=True,
           **extra_instance_updates):
    """Resize (ie, migrate) a running instance.

    If flavor_id is None, the process is considered a migration, keeping
    the original flavor_id. If flavor_id is not None, the instance should
    be migrated to a new host and resized to the new flavor_id.
    context:上下文
    instance:实例对象
    flavor_id:resize的目标机型
    clean_shutdown:静态迁移时开启关机重试,如果未能正常关闭虚拟机会抛异常
    **extra_instance_update:目标实例属性
    """
    self._check_auto_disk_config(instance, **extra_instance_updates)
    #检查系统磁盘的‘自动配置磁盘’功能是否打开,否则抛异常,迁移完成后,云主机需要能够自动配置系统磁盘
    current_instance_type = instance.get_flavor()
    # 获取虚拟机机型信息
    # 如果上面没有传flavor_id过来,冷迁移虚拟机
    if not flavor_id:
        LOG.debug("flavor_id is None. Assuming migration.",
                  instance=instance)
        new_instance_type = current_instance_type
    else:
        new_instance_type = flavors.get_flavor_by_flavor_id(
                flavor_id, read_deleted="no")
        if (new_instance_type.get('root_gb') == 0 and
            current_instance_type.get('root_gb') != 0):
            reason = _('Resize to zero disk flavor is not allowed.')
            raise exception.CannotResizeDisk(reason=reason)
    # 否则获取目标机型,并检查目标机型的磁盘是不是0g 如果是则掷出异常        
    if not new_instance_type:
        raise exception.FlavorNotFound(flavor_id=flavor_id)
    # 如果传过来的flavorid不在现有的flavor 掷出异常
    current_instance_type_name = current_instance_type['name']
    new_instance_type_name = new_instance_type['name']
    LOG.debug("Old instance type %(current_instance_type_name)s, "
              " new instance type %(new_instance_type_name)s",
              {'current_instance_type_name': current_instance_type_name,
               'new_instance_type_name': new_instance_type_name},
              instance=instance)

    same_instance_type = (current_instance_type['id'] ==
                          new_instance_type['id'])
    # 判断一下虚拟机现在的机型是否跟目标机型一样

    # NOTE(sirp): We don't want to force a customer to change their flavor
    # when Ops is migrating off of a failed host.
    if not same_instance_type and new_instance_type.get('disabled'):
        raise exception.FlavorNotFound(flavor_id=flavor_id)

    if same_instance_type and flavor_id and self.cell_type != 'compute':
        raise exception.CannotResizeToSameFlavor()

    # ensure there is sufficient headroom for upsizes
    if flavor_id:
        deltas = self._upsize_quota_delta(context, new_instance_type,
                                          current_instance_type)
    # 获取新旧flavor cpu与内存的差值
        try:
            quotas = self._reserve_quota_delta(context, deltas, instance)
    # 如果上面的差值为正数则为这个未来的实例预留资源,否则打印日志 掷出异常
        except exception.OverQuota as exc:
            quotas = exc.kwargs['quotas']
            overs = exc.kwargs['overs']
            usages = exc.kwargs['usages']
            headroom = self._get_headroom(quotas, usages, deltas)

            resource = overs[0]
            used = quotas[resource] - headroom[resource]
            total_allowed = used + headroom[resource]
            overs = ','.join(overs)
            LOG.warning(_LW("%(overs)s quota exceeded for %(pid)s,"
                            " tried to resize instance."),
                        {'overs': overs, 'pid': context.project_id})
            raise exception.TooManyInstances(overs=overs,
                                             req=deltas[resource],
                                             used=used,
                                             allowed=total_allowed,
                                             resource=resource)
    # 如果没有传入flavor_id,则不保留配额,因为冷迁移不需要额外资源
    else:
        quotas = objects.Quotas(context=context)
    #更新与主机状态:主机状态:重建/迁移,任务状态:准备重建或者迁移
    instance.task_state = task_states.RESIZE_PREP
    instance.progress = 0
    instance.update(extra_instance_updates)
    instance.save(expected_task_state=[None])

    filter_properties = {'ignore_hosts': []}

    if not CONF.allow_resize_to_same_host:
        filter_properties['ignore_hosts'].append(instance.host)
    # nova scheduler调度过滤器,如果该选项这个参数为true则把它加到调度列表
    # 如果是false则不加入调度列表

    # Here when flavor_id is None, the process is considered as migrate.
    if (not flavor_id and not CONF.allow_migrate_to_same_host):
        filter_properties['ignore_hosts'].append(instance.host)

    if self.cell_type == 'api':
        # Commit reservations early and create migration record.
        self._resize_cells_support(context, quotas, instance,
                                   current_instance_type,
                                   new_instance_type)
      # 如果配置了cell则通过cell来完成resize,过程相对简单,默认cell_type为未启用状态

    if not flavor_id:
        self._record_action_start(context, instance,
                                  instance_actions.MIGRATE)
    else:
        self._record_action_start(context, instance,
                                  instance_actions.RESIZE)
    # 数据库记录
    scheduler_hint = {'filter_properties': filter_properties}
    self.compute_task_api.resize_instance(context, instance,
            extra_instance_updates, scheduler_hint=scheduler_hint,
            flavor=new_instance_type,
            reservations=quotas.reservations or [],
            clean_shutdown=clean_shutdown)
    # 将请求转发给nova-conductor

    def compute_task_api(self):
      if self._compute_task_api is None:
          # TODO(alaski): Remove calls into here from conductor manager so
          # that this isn't necessary. #1180540
          from nova import conductor
          self._compute_task_api = conductor.ComputeTaskAPI()
      return self._compute_task_api

接上文 nova/conductor/api.py

class ComputeTaskAPI(object):
    """ComputeTask API that queues up compute tasks for nova-conductor."""
    def __init__(self):
        self.conductor_compute_rpcapi = rpcapi.ComputeTaskAPI()

    def resize_instance(self, context, instance, extra_instance_updates,
                        scheduler_hint, flavor, reservations,
                        clean_shutdown=True):
        # NOTE(comstud): 'extra_instance_updates' is not used here but is
        # needed for compatibility with the cells_rpcapi version of this
        # method.
        self.conductor_compute_rpcapi.migrate_server(
            context, instance, scheduler_hint, live=False, rebuild=False,
            flavor=flavor, block_migration=None, disk_over_commit=None,
            reservations=reservations, clean_shutdown=clean_shutdown)
        """
        调用Conductor的rpcapi
        context: 上下文
        instance:实例对象
        scheduler_hint:nova/compute/api.py中定义的字典
        extra_instance_updates:没有使用,兼容cells_rpcapi
        flavor:机型
        reservations:预留配额对象
        clean_shutdown:静态迁移时开启关机重试,如果未能正常关闭云主机会抛异常
        下面迁移差不多
        live:热迁移选项关闭
        rebuild:重建选项关闭
        block_migration:块迁移,默认不是
        disk_over_commit:磁盘超量,默认不是
        """

接上文 nova/conductor/rpcapi.py(一次rpc调用,从compute-api到conductor-api)

class ComputeTaskAPI(object):
    """Client side of the conductor 'compute' namespaced RPC API"""
    def __init__(self):
        super(ComputeTaskAPI, self).__init__()
        target = messaging.Target(topic=CONF.conductor.topic,
                                  namespace='compute_task',
                                  version='1.0')
    """
    oslo.messaging为Openstack各项目使用RPC和事件通知提供统一的接口,为了支持不同的RPC
    后端实现,oslo.messeging对一些对象进行了统一,例如这儿用到的Target
    Target对象分钟了制定一个消息最终目的地得所有信息,下面为他的一些属性:
    topic: 字符串类型,一个topic可以用来标识服务器所暴露得一组接口(一个接口包
    含多个可被远程调用得方法)。允许多个服务器暴露一组接口,消息会议轮转的方式发给多个
    服务器中的某一个
    namespace:用来标识服务器所暴露的某个特定接口(多个可被远程调用的方法)
    version: 服务器所暴露的接口支持M.N类型的版本号。次版本号(N)的增加表示新的接口向前兼容
    主版本号(M)的增加表示新接口和旧接口不兼容。RPC服务器可以实现多个不同得主版本号接口
    """
        serializer = objects_base.NovaObjectSerializer()
        # serializer对象用来序列化/反序列化消息, 任何服务
        # 需要接受或返回NovaObjects作为参数或值
        #都应该将它传递给它的RPCClient和RPCServer对象。
        self.client = rpc.get_client(target, serializer=serializer)

    def migrate_server(self, context, instance, scheduler_hint, live, rebuild,
                  flavor, block_migration, disk_over_commit,
                  reservations=None, clean_shutdown=True):
        kw = {'instance': instance, 'scheduler_hint': scheduler_hint,
              'live': live, 'rebuild': rebuild, 'flavor': flavor,
              'block_migration': block_migration,
              'disk_over_commit': disk_over_commit,
              'reservations': reservations,
              'clean_shutdown': clean_shutdown}
        version = '1.11'
    # rpc默认版本1.11 如果客户端满足任意一个版本,则发送相应版本兼容的rpc请求
        if not self.client.can_send_version(version):
            del kw['clean_shutdown']
            version = '1.10'
        if not self.client.can_send_version(version):
            kw['flavor'] = objects_base.obj_to_primitive(flavor)
            version = '1.6'
        if not self.client.can_send_version(version):
            kw['instance'] = jsonutils.to_primitive(
                    objects_base.obj_to_primitive(instance))
            version = '1.4'
        cctxt = self.client.prepare(version=version)
        # 返回一个messaging.RPCClient对象,Target对象的属性在RPCClient
        # 对象构造以后,通过prepare()方法修改,修改后的target属性只有在这
        # 个prepare()方法返回的对象有效,简单一点就是这儿新建了一
        # 个RPCClient对象,用来被rpc远程调用
        return cctxt.call(context, 'migrate_server', **kw)
        # rpc同步阻塞调用,就是说发送这个调用之后进程会阻塞在这儿
        # 直到客户端任务完成,返回一个完成状态
        # 这个call请求到哪儿去了需要看下上面topic=CONF.conductor.topic
        # 默认这个值是conductor,所以conductor会监听这个消息

接上文 nova/conductor/manager.py

class ComputeTaskManager(base.Base):  target = messaging.Target(namespace='compute_task', version='1.11')    def __init__(self):      super(ComputeTaskManager, self).__init__()      self.compute_rpcapi = compute_rpcapi.ComputeAPI()      self.image_api = image.API()      self.scheduler_client = scheduler_client.SchedulerClient()      # 这儿的值都是从api那边传过来的    def migrate_server(self, context, instance, scheduler_hint, live, rebuild,              flavor, block_migration, disk_over_commit, reservations=None,              clean_shutdown=True):  # 判断传过来得实例对象是不是novaobject实例如果不是则从数据库获取        if instance and not isinstance(instance, nova_object.NovaObject):            # NOTE(danms): Until v2 of the RPC API, we need to tolerate                # old-world instance objects here          attrs = ['metadata', 'system_metadata', 'info_cache',                         'security_groups']          instance = objects.Instance._from_db_object(                    context, objects.Instance(), instance,                    expected_attrs=attrs)            # NOTE(melwitt): Remove this in version 2.0 of the RPC API        if flavor and not isinstance(flavor, objects.Flavor):                # Code downstream may expect extra_specs to be populated since it                # is receiving an object, so lookup the flavor to ensure this.          flavor = objects.Flavor.get_by_id(context, flavor['id'])          # 如果传入的参数live为true rebuild为false或为空false则热迁移        if live and not rebuild and not flavor:          self._live_migrate(context, instance, scheduler_hint,                             block_migration, disk_over_commit)        elif not live and not rebuild and flavor:                instance_uuid = instance['uuid']
10-07 18:53