openstack虚拟机resize源码分析
文章目录
- openstack虚拟机resize源码分析
- resize过程python-client端debug
- debug分析
- 获取keystone版本详情
- 验证admin信息并生成token
- 带着token去请求虚拟机信息
- 带着token去获取resizede的目标flavor
- 发送调整实例请求
- 再次获取虚拟机信息 监控服务器状态 直到状态改变为`VERIFY_RESIZE` 结束这个任务
- resize confirm过程
- resize过程源码分析
- 控制节点
- 通过源码地图`setup.cfg`可以知道nova api实现的代码路径`nova/api/openstack/compute/servers.py` (一次rpc调用nova-api到compute-api)
- 接上文 `nova/compute/api.py`
- 接上文 `nova/conductor/api.py`
- 接上文 `nova/conductor/rpcapi.py`(一次rpc调用,从compute-api到conductor-api)
- 接上文 `nova/conductor/manager.py`
- 接上文 `nova/conductor/manager.py`与上文同文件
- 接上文 RPC发起远程cast调用`nova/compute/rpcapi.py ComputeAPI.prep_resize`(一次rpc调用,从compute到目标计算节点nova-compute)
- 目标计算节点
- nova-compute监听从rabbitmq过来的消息 接收到控制节点发过来的prep_resize请求之后
- 接上文`nova/compute/manager.py _prep_resize`(一次rpc调用 从目标计算节点nova-compute到源计算节点nova-compute)
- 源计算节点
- `nova/compute/manager.py ComputeManager.resize_instance`(一次rpc调用 从源计算节点nova-compute到目标计算节点nova-compute)
- LibvirtDriver迁移虚拟机磁盘实现
- 目标计算节点
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']