Update VIM to use nova API version 2.53
Updating the VIM to use version 2.53 (Pike) of the nova API. The VIM was previously using version 2.38 (Newton). The main changes are: - Stop using os-hosts (no longer exists). Fortunately we weren't actually using this code. - Use new format for os-services (server uuid now required in URL and body changed). - The GET servers now returns a flavor in the response (instead of the flavor uuid). The VIM was previously using the uuid to look up the flavor in the instance_type table. Now the VIM must access the flavor information embedded in each instance. Note that the server notifications from nova still include the flavor uuid (we need to switch to the newer versioned notifications to get the flavor). I changed our notification handling to ignore the flavor uuid as it is no longer of any use to us. The main reason for this change is to allow flavors to be modified or deleted even if in use by a running instance. This brings us in line with upstream behaviour and will allow us to stop modifying this behaviour in nova. Change-Id: I65fab6843174d59782aa7366f2e0cc646cebafb7 Signed-off-by: Al Bailey <Al.Bailey@windriver.com>
This commit is contained in:
parent
37f3cabe55
commit
0b06f1dbd4
|
@ -1 +1 @@
|
|||
TIS_PATCH_VER=67
|
||||
TIS_PATCH_VER=69
|
||||
|
|
|
@ -602,13 +602,13 @@ logs:
|
|||
- name: Instance NFVI State Change
|
||||
type: nfv_vim_instance_nfvi_state_change
|
||||
file: _vim_nfvi_events.py
|
||||
regex: "Instance state-change, nfvi_instance={'instance_type_uuid': u'(.*)',
|
||||
regex: "Instance state-change, nfvi_instance={'instance_type': ({.*}),
|
||||
'name': u'(.*)', 'tenant_id': '(.*)', 'avail_status': \\[(.*)], 'nfvi_data':
|
||||
{'vm_state': u'(.*)', 'task_state': u?'(.*)', 'power_state': '(.*)'},
|
||||
'live_migration_support': (.*), 'oper_state': '(.*)', 'host_name': u'(.*)',
|
||||
'admin_state': '(.*)', 'action': '(.*)', 'image_uuid': (.*), 'uuid': u'(.*)'}."
|
||||
fields:
|
||||
- instance_type_uuid
|
||||
- instance_type
|
||||
- instance_name
|
||||
- tenant_uuid
|
||||
- instance_avail_status
|
||||
|
|
|
@ -448,64 +448,6 @@ class NFVIComputeAPI(nfvi.api.v1.NFVIComputeAPI):
|
|||
DLOG.verbose("Auditing action requests, timer_id=%s." % timer_id)
|
||||
self._ageout_action_requests()
|
||||
|
||||
def get_service_hosts(self, future, callback):
|
||||
"""
|
||||
Get a list of service hosts
|
||||
"""
|
||||
response = dict()
|
||||
response['completed'] = False
|
||||
response['reason'] = ''
|
||||
|
||||
try:
|
||||
future.set_timeouts(config.CONF.get('nfvi-timeouts', None))
|
||||
|
||||
if self._token is None or self._token.is_expired():
|
||||
future.work(openstack.get_token, self._directory)
|
||||
future.result = (yield)
|
||||
|
||||
if not future.result.is_complete():
|
||||
return
|
||||
|
||||
self._token = future.result.data
|
||||
|
||||
future.work(nova.get_hosts, self._token)
|
||||
future.result = (yield)
|
||||
|
||||
if not future.result.is_complete():
|
||||
return
|
||||
|
||||
host_data_list = future.result.data
|
||||
|
||||
host_objs = list()
|
||||
|
||||
for host_data in host_data_list['hosts']:
|
||||
host_obj = nfvi_objs.ServiceHost(host_data['host_name'],
|
||||
host_data['service'],
|
||||
host_data['zone'])
|
||||
host_objs.append(host_obj)
|
||||
|
||||
response['result-data'] = host_objs
|
||||
response['completed'] = True
|
||||
|
||||
except exceptions.OpenStackRestAPIException as e:
|
||||
if httplib.UNAUTHORIZED == e.http_status_code:
|
||||
response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED
|
||||
if self._token is not None:
|
||||
self._token.set_expired()
|
||||
|
||||
else:
|
||||
DLOG.exception("Caught exception while trying to get service "
|
||||
"host list, error=%s." % e)
|
||||
response['reason'] = e.http_response_reason
|
||||
|
||||
except Exception as e:
|
||||
DLOG.exception("Caught exception while trying to get service "
|
||||
"host list, error=%s." % e)
|
||||
|
||||
finally:
|
||||
callback.send(response)
|
||||
callback.close()
|
||||
|
||||
def get_host_aggregates(self, future, callback):
|
||||
"""
|
||||
Get a list of host aggregates
|
||||
|
@ -1283,7 +1225,7 @@ class NFVIComputeAPI(nfvi.api.v1.NFVIComputeAPI):
|
|||
instance_obj = nfvi_objs.Instance(
|
||||
instance_data['id'], instance_data['name'],
|
||||
str(tenant_uuid), admin_state, oper_state, avail_status, action,
|
||||
instance_data['OS-EXT-SRV-ATTR:host'], instance_type_uuid,
|
||||
instance_data['OS-EXT-SRV-ATTR:host'], instance_data['flavor'],
|
||||
image_uuid, live_migration_support, attached_volumes, nfvi_data)
|
||||
|
||||
response['result-data'] = instance_obj
|
||||
|
@ -2655,7 +2597,7 @@ class NFVIComputeAPI(nfvi.api.v1.NFVIComputeAPI):
|
|||
|
||||
tenant_uuid = uuid.UUID(instance_data['tenant_id'])
|
||||
|
||||
instance_type_uuid = instance_data['flavor']['id']
|
||||
instance_type = instance_data['flavor']
|
||||
|
||||
image_data = instance_data.get('image', None)
|
||||
if image_data:
|
||||
|
@ -2686,7 +2628,7 @@ class NFVIComputeAPI(nfvi.api.v1.NFVIComputeAPI):
|
|||
instance_obj = nfvi_objs.Instance(
|
||||
instance_data['id'], instance_data['name'],
|
||||
str(tenant_uuid), admin_state, oper_state, avail_status, action,
|
||||
instance_data['OS-EXT-SRV-ATTR:host'], instance_type_uuid,
|
||||
instance_data['OS-EXT-SRV-ATTR:host'], instance_type,
|
||||
image_uuid, live_migration_support, attached_volumes,
|
||||
nfvi_data, recovery_priority, live_migration_timeout)
|
||||
|
||||
|
@ -2751,7 +2693,6 @@ class NFVIComputeAPI(nfvi.api.v1.NFVIComputeAPI):
|
|||
task_state = message.get('task_state', None)
|
||||
power_state = message.get('power_state', None)
|
||||
host_name = message.get('host_name', None)
|
||||
instance_type_uuid = message.get('flavor_id', None)
|
||||
image_uuid = message.get('image_id', None)
|
||||
recovery_priority = message.get('recovery_priority', None)
|
||||
live_migration_timeout = message.get('live_migration_timeout', None)
|
||||
|
@ -2789,7 +2730,7 @@ class NFVIComputeAPI(nfvi.api.v1.NFVIComputeAPI):
|
|||
admin_state, oper_state,
|
||||
avail_status, action,
|
||||
host_name,
|
||||
instance_type_uuid,
|
||||
None,
|
||||
image_uuid, None, None,
|
||||
nfvi_data,
|
||||
recovery_priority,
|
||||
|
|
|
@ -141,3 +141,40 @@ class OpenStackRestAPIException(exceptions.PickleableException):
|
|||
Returns the reason for the exception
|
||||
"""
|
||||
return self._reason
|
||||
|
||||
|
||||
class NotFound(exceptions.PickleableException):
|
||||
"""
|
||||
Not Found Exception
|
||||
"""
|
||||
def __init__(self, message):
|
||||
"""
|
||||
Create an OpenStack exception
|
||||
"""
|
||||
super(NotFound, self).__init__(message)
|
||||
self._message = message
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Return a string representing the exception
|
||||
"""
|
||||
return "[NotFound Exception: message=%s]" % self._message
|
||||
|
||||
def __repr__(self):
|
||||
"""
|
||||
Provide a representation of the exception
|
||||
"""
|
||||
return str(self)
|
||||
|
||||
def __reduce__(self):
|
||||
"""
|
||||
Return a tuple so that we can properly pickle the exception
|
||||
"""
|
||||
return NotFound, (self.message,)
|
||||
|
||||
@property
|
||||
def message(self):
|
||||
"""
|
||||
Returns the message for the exception
|
||||
"""
|
||||
return self._message
|
||||
|
|
|
@ -5,19 +5,19 @@
|
|||
#
|
||||
import six
|
||||
import json
|
||||
import httplib
|
||||
|
||||
from nfv_common import debug
|
||||
from nfv_common.helpers import Constants, Constant, Singleton
|
||||
|
||||
from exceptions import OpenStackRestAPIException
|
||||
from exceptions import NotFound
|
||||
from objects import OPENSTACK_SERVICE
|
||||
from rest_api import rest_api_request, rest_api_request_with_context
|
||||
|
||||
DLOG = debug.debug_get_logger('nfv_plugins.nfvi_plugins.openstack.nova')
|
||||
|
||||
# Using maximum nova API version for newton release.
|
||||
NOVA_API_VERSION = '2.38'
|
||||
# Using maximum nova API version for pike release.
|
||||
NOVA_API_VERSION = '2.53'
|
||||
NOVA_API_VERSION_NEWTON = '2.38'
|
||||
|
||||
|
||||
@six.add_metaclass(Singleton)
|
||||
|
@ -199,24 +199,6 @@ def vm_power_state_str(power_state):
|
|||
return "unknown"
|
||||
|
||||
|
||||
def get_hosts(token):
|
||||
"""
|
||||
Asks OpenStack Nova for a list of hosts
|
||||
"""
|
||||
url = token.get_service_url(OPENSTACK_SERVICE.NOVA, strip_version=True)
|
||||
if url is None:
|
||||
raise ValueError("OpenStack Nova URL is invalid")
|
||||
|
||||
api_cmd = url + "/v2.1/%s/os-hosts" % token.get_tenant_id()
|
||||
|
||||
api_cmd_headers = dict()
|
||||
api_cmd_headers['wrs-header'] = 'true'
|
||||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
|
||||
|
||||
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
||||
return response
|
||||
|
||||
|
||||
def get_host_aggregates(token):
|
||||
"""
|
||||
Asks OpenStack Nova for a list of host aggregates
|
||||
|
@ -1331,7 +1313,6 @@ def rpc_message_server_state_change_filter(message):
|
|||
power_state = payload.get('power_state', None)
|
||||
host_name = payload.get('host', None)
|
||||
image_meta = payload.get('image_meta', None)
|
||||
flavor_id = payload.get('instance_flavor_id', None)
|
||||
image_id = image_meta.get('base_image_ref', None)
|
||||
|
||||
if not image_id:
|
||||
|
@ -1360,7 +1341,6 @@ def rpc_message_server_state_change_filter(message):
|
|||
state_change['task_state'] = task_state
|
||||
state_change['power_state'] = power_state
|
||||
state_change['host_name'] = host_name
|
||||
state_change['flavor_id'] = flavor_id
|
||||
state_change['image_id'] = image_id
|
||||
state_change['recovery_priority'] = recovery_priority
|
||||
state_change['live_migration_timeout'] = live_migration_timeout
|
||||
|
@ -1413,7 +1393,8 @@ def create_host_services(token, host_name):
|
|||
api_cmd_headers = dict()
|
||||
api_cmd_headers['wrs-header'] = 'true'
|
||||
api_cmd_headers['Content-Type'] = "application/json"
|
||||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
|
||||
# The create is a WRS extension, which is not supported in Pike
|
||||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION_NEWTON
|
||||
|
||||
api_cmd_payload = dict()
|
||||
api_cmd_payload['binary'] = 'nova-compute'
|
||||
|
@ -1424,6 +1405,31 @@ def create_host_services(token, host_name):
|
|||
return response
|
||||
|
||||
|
||||
def get_host_service_id(token, host_name, service_name):
|
||||
"""
|
||||
Asks OpenStack Nova for the service id of a service on a host
|
||||
"""
|
||||
url = token.get_service_url(OPENSTACK_SERVICE.NOVA, strip_version=True)
|
||||
if url is None:
|
||||
raise ValueError("OpenStack Nova URL is invalid")
|
||||
|
||||
api_cmd = url + "/v2.1/%s/os-services?host=%s&binary=%s" % \
|
||||
(token.get_tenant_id(), host_name, service_name)
|
||||
|
||||
api_cmd_headers = dict()
|
||||
api_cmd_headers['wrs-header'] = 'true'
|
||||
api_cmd_headers['Content-Type'] = "application/json"
|
||||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
|
||||
|
||||
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
||||
services = response.result_data.get('services', list())
|
||||
if services:
|
||||
return services[0].get('id')
|
||||
else:
|
||||
raise NotFound("Service %s not found for host %s" % (service_name,
|
||||
host_name))
|
||||
|
||||
|
||||
def delete_host_services(token, host_name):
|
||||
"""
|
||||
Asks OpenStack Nova to delete services on a host
|
||||
|
@ -1432,42 +1438,26 @@ def delete_host_services(token, host_name):
|
|||
if url is None:
|
||||
raise ValueError("OpenStack Nova URL is invalid")
|
||||
|
||||
compute_service_id = None
|
||||
response = dict()
|
||||
|
||||
# Check to see if nova knows about the host or not. Nova returns
|
||||
# internal-error when the host is not known on a delete.
|
||||
try:
|
||||
api_cmd = url + "/v2.1/%s/os-services?host=%s" % (token.get_tenant_id(),
|
||||
host_name)
|
||||
compute_service_id = get_host_service_id(token, host_name,
|
||||
'nova-compute')
|
||||
except NotFound:
|
||||
# No service to delete
|
||||
return response
|
||||
|
||||
api_cmd_headers = dict()
|
||||
api_cmd_headers['wrs-header'] = 'true'
|
||||
api_cmd_headers['Content-Type'] = "application/json"
|
||||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
|
||||
api_cmd = url + "/v2.1/%s/os-services/%s" % (token.get_tenant_id(),
|
||||
compute_service_id)
|
||||
|
||||
response = rest_api_request(token, "GET", api_cmd)
|
||||
services = response.result_data.get('services', list())
|
||||
for service in services:
|
||||
service_name = service.get('binary', '')
|
||||
if 'nova-compute' == service_name:
|
||||
compute_service_id = service.get('id', None)
|
||||
break
|
||||
api_cmd_headers = dict()
|
||||
api_cmd_headers['wrs-header'] = 'true'
|
||||
api_cmd_headers['Content-Type'] = "application/json"
|
||||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
|
||||
|
||||
except OpenStackRestAPIException as e:
|
||||
if httplib.NOT_FOUND != e.http_status_code:
|
||||
raise
|
||||
|
||||
response = dict()
|
||||
if compute_service_id is not None:
|
||||
api_cmd = url + "/v2.1/%s/os-services/%s" % (token.get_tenant_id(),
|
||||
compute_service_id)
|
||||
|
||||
api_cmd_headers = dict()
|
||||
api_cmd_headers['wrs-header'] = 'true'
|
||||
api_cmd_headers['Content-Type'] = "application/json"
|
||||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
|
||||
|
||||
response = rest_api_request(token, "DELETE", api_cmd, api_cmd_headers)
|
||||
response = rest_api_request(token, "DELETE", api_cmd, api_cmd_headers)
|
||||
return response
|
||||
|
||||
|
||||
|
@ -1479,7 +1469,11 @@ def enable_host_services(token, host_name):
|
|||
if url is None:
|
||||
raise ValueError("OpenStack Nova URL is invalid")
|
||||
|
||||
api_cmd = url + "/v2.1/%s/os-services/enable" % token.get_tenant_id()
|
||||
# Get the service ID for the nova-compute service.
|
||||
compute_service_id = get_host_service_id(token, host_name, 'nova-compute')
|
||||
|
||||
api_cmd = url + "/v2.1/%s/os-services/%s" % (token.get_tenant_id(),
|
||||
compute_service_id)
|
||||
|
||||
api_cmd_headers = dict()
|
||||
api_cmd_headers['wrs-header'] = 'true'
|
||||
|
@ -1487,8 +1481,7 @@ def enable_host_services(token, host_name):
|
|||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
|
||||
|
||||
api_cmd_payload = dict()
|
||||
api_cmd_payload['binary'] = 'nova-compute'
|
||||
api_cmd_payload['host'] = host_name
|
||||
api_cmd_payload['status'] = 'enabled'
|
||||
|
||||
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
|
||||
json.dumps(api_cmd_payload))
|
||||
|
@ -1503,7 +1496,11 @@ def disable_host_services(token, host_name):
|
|||
if url is None:
|
||||
raise ValueError("OpenStack Nova URL is invalid")
|
||||
|
||||
api_cmd = url + "/v2.1/%s/os-services/disable" % token.get_tenant_id()
|
||||
# Get the service ID for the nova-compute service.
|
||||
compute_service_id = get_host_service_id(token, host_name, 'nova-compute')
|
||||
|
||||
api_cmd = url + "/v2.1/%s/os-services/%s" % (token.get_tenant_id(),
|
||||
compute_service_id)
|
||||
|
||||
api_cmd_headers = dict()
|
||||
api_cmd_headers['wrs-header'] = 'true'
|
||||
|
@ -1511,8 +1508,8 @@ def disable_host_services(token, host_name):
|
|||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
|
||||
|
||||
api_cmd_payload = dict()
|
||||
api_cmd_payload['binary'] = 'nova-compute'
|
||||
api_cmd_payload['host'] = host_name
|
||||
api_cmd_payload['status'] = 'disabled'
|
||||
api_cmd_payload['disabled_reason'] = 'disabled by VIM'
|
||||
|
||||
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
|
||||
json.dumps(api_cmd_payload))
|
||||
|
@ -1562,7 +1559,11 @@ def notify_host_enabled(token, host_name):
|
|||
if url is None:
|
||||
raise ValueError("OpenStack Nova URL is invalid")
|
||||
|
||||
api_cmd = url + "/v2.1/%s/os-services/force-down" % token.get_tenant_id()
|
||||
# Get the service ID for the nova-compute service.
|
||||
compute_service_id = get_host_service_id(token, host_name, 'nova-compute')
|
||||
|
||||
api_cmd = url + "/v2.1/%s/os-services/%s" % (token.get_tenant_id(),
|
||||
compute_service_id)
|
||||
|
||||
api_cmd_headers = dict()
|
||||
api_cmd_headers['wrs-header'] = 'true'
|
||||
|
@ -1570,8 +1571,6 @@ def notify_host_enabled(token, host_name):
|
|||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
|
||||
|
||||
api_cmd_payload = dict()
|
||||
api_cmd_payload['binary'] = 'nova-compute'
|
||||
api_cmd_payload['host'] = host_name
|
||||
api_cmd_payload['forced_down'] = False
|
||||
|
||||
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
|
||||
|
@ -1587,7 +1586,11 @@ def notify_host_disabled(token, host_name):
|
|||
if url is None:
|
||||
raise ValueError("OpenStack Nova URL is invalid")
|
||||
|
||||
api_cmd = url + "/v2.1/%s/os-services/force-down" % token.get_tenant_id()
|
||||
# Get the service ID for the nova-compute service.
|
||||
compute_service_id = get_host_service_id(token, host_name, 'nova-compute')
|
||||
|
||||
api_cmd = url + "/v2.1/%s/os-services/%s" % (token.get_tenant_id(),
|
||||
compute_service_id)
|
||||
|
||||
api_cmd_headers = dict()
|
||||
api_cmd_headers['wrs-header'] = 'true'
|
||||
|
@ -1595,8 +1598,6 @@ def notify_host_disabled(token, host_name):
|
|||
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
|
||||
|
||||
api_cmd_payload = dict()
|
||||
api_cmd_payload['binary'] = 'nova-compute'
|
||||
api_cmd_payload['host'] = host_name
|
||||
api_cmd_payload['forced_down'] = True
|
||||
|
||||
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
|
||||
|
|
|
@ -252,9 +252,6 @@ def nova_unit_tests(token, test_config):
|
|||
response = nova.enable_host_services(token, test_config['host_name'])
|
||||
print "Host-Services enable response: %s" % response
|
||||
|
||||
hosts = nova.get_hosts(token)
|
||||
print "List of hosts: %s" % hosts
|
||||
|
||||
hypervisors = nova.get_hypervisors(token)
|
||||
print "List of hypervisors: %s" % hypervisors
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
|
||||
# Get a token from keystone
|
||||
TENANT_ID=`openstack token issue | grep "| project_id |" | cut -f3 -d'|' | tr -d '[[:space:]]'`
|
||||
TOKEN_ID=`openstack token issue | grep "| id |" | cut -f3 -d'|' | tr -d '[[:space:]]'`
|
||||
|
||||
# Specify management IP
|
||||
MGMT_IP=192.168.204.2
|
||||
|
||||
1. Create a VM
|
||||
--------------
|
||||
# Note:
|
||||
|
@ -15,10 +18,12 @@ cat > compute_request.txt
|
|||
"compute_data": {"flavour_id": "101",
|
||||
"virtual_memory": {"virtual_mem_size": 512},
|
||||
"virtual_storage": {"type_of_storage": "volume", "size_of_storage": 1},
|
||||
"virtual_cpu": {"num_virtual_cpu": 1}}}
|
||||
"virtual_cpu": {"num_virtual_cpu": 1}},
|
||||
"meta_data": "{\"network_uuid\": \"81edbebc-d89e-40f9-bc02-7fdc9dd324f9\"}"
|
||||
}
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes -d @compute_request.txt
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes -d @compute_request.txt
|
||||
|
||||
|
||||
2. Delete a VM
|
||||
|
@ -26,19 +31,19 @@ http://localhost:4545/api/virtualised-resources/computes -d @compute_request.txt
|
|||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X DELETE -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}
|
||||
|
||||
3. Get a VM
|
||||
-----------
|
||||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X GET -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}
|
||||
|
||||
4. Get all VMs
|
||||
--------------
|
||||
curl -i -X GET -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes
|
||||
|
||||
|
||||
5. Pause a VM
|
||||
|
@ -46,68 +51,67 @@ http://localhost:4545/api/virtualised-resources/computes
|
|||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"pause\"}"
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"pause\"}"
|
||||
|
||||
6. Unpause a VM
|
||||
---------------
|
||||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"unpause\"}"
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"unpause\"}"
|
||||
|
||||
7. Suspend a VM
|
||||
---------------
|
||||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"suspend\"}"
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"suspend\"}"
|
||||
|
||||
8. Resume a VM
|
||||
--------------
|
||||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"resume\"}"
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"resume\"}"
|
||||
|
||||
9. Stop a VM
|
||||
------------
|
||||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"stop\"}"
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"stop\"}"
|
||||
|
||||
10. Start a VM
|
||||
--------------
|
||||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"start\"}"
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"start\"}"
|
||||
|
||||
11. Reboot a VM
|
||||
---------------
|
||||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"reboot\"}"
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}/operate -d "{\"compute_operation\": \"reboot\"}"
|
||||
|
||||
12. Live-Migrate a VM
|
||||
---------------------
|
||||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}/migrate -d "{\"migrate_type\": \"live\"}"
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}/migrate -d "{\"migrate_type\": \"live\"}"
|
||||
|
||||
13. Cold-Migrate a VM
|
||||
---------------------
|
||||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}/migrate -d "{\"migrate_type\": \"cold\"}"
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}/migrate -d "{\"migrate_type\": \"cold\"}"
|
||||
|
||||
14. Evacuate a VM
|
||||
-----------------
|
||||
VM_ID=8bdb775c-9e29-4412-a49f-0895b5faa76a
|
||||
|
||||
curl -i -X POST -H 'Content-Type: application/json' -H "X-Auth-Token: ${TOKEN_ID}" -H 'Accept: application/json' \
|
||||
http://localhost:4545/api/virtualised-resources/computes/${VM_ID}/migrate -d "{\"migrate_type\": \"evacuate\"}"
|
||||
|
||||
http://${MGMT_IP}:4545/api/virtualised-resources/computes/${VM_ID}/migrate -d "{\"migrate_type\": \"evacuate\"}"
|
||||
|
|
|
@ -841,7 +841,7 @@ class TestInstanceResize(TestInstance):
|
|||
flavor_id = None
|
||||
for flavor_name in self._flavor_names:
|
||||
flavor_id = self._get_flavor_id(flavor_name)
|
||||
if flavor_id != self._instance_data['flavor']['id']:
|
||||
if flavor_name != self._instance_data['flavor']['original_name']:
|
||||
self._flavor_id = flavor_id
|
||||
break
|
||||
|
||||
|
@ -919,7 +919,7 @@ class TestInstanceResizeConfirm(TestInstance):
|
|||
flavor_id = None
|
||||
for flavor_name in self._flavor_names:
|
||||
flavor_id = self._get_flavor_id(flavor_name)
|
||||
if flavor_id != self._instance_data['flavor']['id']:
|
||||
if flavor_name != self._instance_data['flavor']['original_name']:
|
||||
break
|
||||
|
||||
if flavor_id is None:
|
||||
|
@ -1015,7 +1015,7 @@ class TestInstanceResizeRevert(TestInstance):
|
|||
flavor_id = None
|
||||
for flavor_name in self._flavor_names:
|
||||
flavor_id = self._get_flavor_id(flavor_name)
|
||||
if flavor_id != self._instance_data['flavor']['id']:
|
||||
if flavor_name != self._instance_data['flavor']['original_name']:
|
||||
break
|
||||
|
||||
if flavor_id is None:
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -10,16 +10,16 @@ from nfv_vim import database
|
|||
from nfv_vim import tables
|
||||
|
||||
|
||||
def test_nfv_vim_database_upgrade_from_17_06():
|
||||
def test_nfv_vim_database_upgrade_from_18_03():
|
||||
"""
|
||||
Test VIM database upgrades from 17.06 GA
|
||||
Test VIM database upgrades from 18.03 GA
|
||||
"""
|
||||
root_dir = os.environ['VIRTUAL_ENV']
|
||||
|
||||
devnull = open(os.devnull, 'w')
|
||||
try:
|
||||
vim_cmd = ("nfv-vim-manage db-load-data -d %s "
|
||||
"-f %s/nfv_vim_db_17.06_GA" % (root_dir, root_dir))
|
||||
"-f %s/nfv_vim_db_18.03_GA" % (root_dir, root_dir))
|
||||
|
||||
subprocess.check_call([vim_cmd], shell=True, stderr=devnull)
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ from nfv_vim.tables._instance_group_table import InstanceGroupTable
|
|||
|
||||
from nfv_vim.nfvi.objects import v1 as nfvi_objects
|
||||
|
||||
import utils
|
||||
|
||||
# Constants
|
||||
|
||||
# Globals
|
||||
|
@ -73,7 +75,8 @@ def create_instance(instance_name, instance_type_name, image_name, host_name,
|
|||
avail_status=list(),
|
||||
action=nfvi.objects.v1.INSTANCE_ACTION.NONE,
|
||||
host_name=host_name,
|
||||
instance_type_uuid=instance_type.uuid,
|
||||
instance_type=utils.instance_type_to_flavor_dict(
|
||||
instance_type),
|
||||
image_uuid=image.uuid,
|
||||
live_migration_timeout=live_migration_timeout)
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ from nfv_vim import objects
|
|||
from nfv_vim.tables._table import Table
|
||||
from nfv_vim.directors._instance_director import InstanceDirector
|
||||
|
||||
import utils
|
||||
|
||||
# Constants
|
||||
_audit_interval = 330
|
||||
_audit_cooldown = 30
|
||||
|
@ -50,7 +52,9 @@ def create_instance(instance_type_name, instance_name, recovery_priority=None):
|
|||
oper_state=nfvi.objects.v1.INSTANCE_OPER_STATE.ENABLED,
|
||||
avail_status=list(),
|
||||
action=nfvi.objects.v1.INSTANCE_ACTION.NONE,
|
||||
host_name='compute-0', instance_type_uuid=instance_type.uuid,
|
||||
host_name='compute-0',
|
||||
instance_type=utils.instance_type_to_flavor_dict(
|
||||
instance_type),
|
||||
image_uuid=image_uuid,
|
||||
recovery_priority=recovery_priority)
|
||||
|
||||
|
@ -176,10 +180,10 @@ def test_instance_director_recovery_list_order(
|
|||
instance_1._elapsed_time_in_state = _recovery_cooldown
|
||||
instance_1._nfvi_instance.avail_status.append(
|
||||
nfvi.objects.v1.INSTANCE_AVAIL_STATUS.FAILED)
|
||||
instance_1._vcpus = 1
|
||||
instance_1._memory_mb = 32
|
||||
instance_1._disk_gb = 2
|
||||
instance_1._swap_gb = 0
|
||||
instance_1._nfvi_instance['instance_type']['vcpus'] = 1
|
||||
instance_1._nfvi_instance['instance_type']['ram'] = 32
|
||||
instance_1._nfvi_instance['instance_type']['disk'] = 2
|
||||
instance_1._nfvi_instance['instance_type']['swap'] = 0
|
||||
_instance_table[instance_1.uuid] = instance_1
|
||||
|
||||
# Validate the Instance Director recovery_list order
|
||||
|
@ -195,10 +199,10 @@ def test_instance_director_recovery_list_order(
|
|||
instance_2._elapsed_time_in_state = _recovery_cooldown
|
||||
instance_2._nfvi_instance.avail_status.append(
|
||||
nfvi.objects.v1.INSTANCE_AVAIL_STATUS.FAILED)
|
||||
instance_2._vcpus = 2
|
||||
instance_2._memory_mb = 32
|
||||
instance_2._disk_gb = 1
|
||||
instance_2._swap_gb = 0
|
||||
instance_2._nfvi_instance['instance_type']['vcpus'] = 2
|
||||
instance_2._nfvi_instance['instance_type']['ram'] = 32
|
||||
instance_2._nfvi_instance['instance_type']['disk'] = 1
|
||||
instance_2._nfvi_instance['instance_type']['swap'] = 0
|
||||
_instance_table[instance_2.uuid] = instance_2
|
||||
|
||||
# -- with two instances in the failed state
|
||||
|
@ -215,10 +219,10 @@ def test_instance_director_recovery_list_order(
|
|||
instance_3._elapsed_time_in_state = _recovery_cooldown
|
||||
instance_3._nfvi_instance.avail_status.append(
|
||||
nfvi.objects.v1.INSTANCE_AVAIL_STATUS.FAILED)
|
||||
instance_3._vcpus = 1
|
||||
instance_3._memory_mb = 32
|
||||
instance_3._disk_gb = 0
|
||||
instance_3._swap_gb = 0
|
||||
instance_3._nfvi_instance['instance_type']['vcpus'] = 1
|
||||
instance_3._nfvi_instance['instance_type']['ram'] = 32
|
||||
instance_3._nfvi_instance['instance_type']['disk'] = 0
|
||||
instance_3._nfvi_instance['instance_type']['swap'] = 0
|
||||
_instance_table[instance_3.uuid] = instance_3
|
||||
|
||||
# -- with three instances in the failed state
|
||||
|
@ -236,10 +240,10 @@ def test_instance_director_recovery_list_order(
|
|||
instance_4._elapsed_time_in_state = _recovery_cooldown
|
||||
instance_4._nfvi_instance.avail_status.append(
|
||||
nfvi.objects.v1.INSTANCE_AVAIL_STATUS.FAILED)
|
||||
instance_4._vcpus = 1
|
||||
instance_4._memory_mb = 32
|
||||
instance_4._disk_gb = 0
|
||||
instance_4._swap_gb = 0
|
||||
instance_4._nfvi_instance['instance_type']['vcpus'] = 1
|
||||
instance_4._nfvi_instance['instance_type']['ram'] = 32
|
||||
instance_4._nfvi_instance['instance_type']['disk'] = 0
|
||||
instance_4._nfvi_instance['instance_type']['swap'] = 0
|
||||
_instance_table[instance_4.uuid] = instance_4
|
||||
|
||||
# -- with four instances in the failed state
|
||||
|
@ -258,10 +262,10 @@ def test_instance_director_recovery_list_order(
|
|||
instance_5._elapsed_time_in_state = _recovery_cooldown
|
||||
instance_5._nfvi_instance.avail_status.append(
|
||||
nfvi.objects.v1.INSTANCE_AVAIL_STATUS.FAILED)
|
||||
instance_5._vcpus = 2
|
||||
instance_5._memory_mb = 32
|
||||
instance_5._disk_gb = 0
|
||||
instance_5._swap_gb = 0
|
||||
instance_5._nfvi_instance['instance_type']['vcpus'] = 2
|
||||
instance_5._nfvi_instance['instance_type']['ram'] = 32
|
||||
instance_5._nfvi_instance['instance_type']['disk'] = 0
|
||||
instance_5._nfvi_instance['instance_type']['swap'] = 0
|
||||
_instance_table[instance_5.uuid] = instance_5
|
||||
|
||||
# -- with five instances in the failed state
|
||||
|
@ -301,7 +305,6 @@ def test_instance_director_recover_instance(
|
|||
dor_is_complete_mock.return_value = True
|
||||
|
||||
instance_1 = create_instance('small', 'instance_1')
|
||||
instance_1._auto_recovery = mock.Mock(return_value=True)
|
||||
instance_1.fail = mock.Mock()
|
||||
instance_1.do_action = mock.Mock()
|
||||
instance_1._nfvi_instance.avail_status.append(
|
||||
|
|
|
@ -23,6 +23,8 @@ from nfv_vim.tables._instance_table import InstanceTable
|
|||
from nfv_vim.tables._instance_group_table import InstanceGroupTable
|
||||
from nfv_vim.strategy._strategy import SwPatchStrategy, strategy_rebuild_from_dict
|
||||
|
||||
import utils
|
||||
|
||||
# Constants
|
||||
|
||||
# Globals
|
||||
|
@ -67,7 +69,9 @@ def create_instance(instance_type_name, instance_name, host_name,
|
|||
oper_state=nfvi.objects.v1.INSTANCE_OPER_STATE.ENABLED,
|
||||
avail_status=list(),
|
||||
action=nfvi.objects.v1.INSTANCE_ACTION.NONE,
|
||||
host_name=host_name, instance_type_uuid=instance_type.uuid,
|
||||
host_name=host_name,
|
||||
instance_type=utils.instance_type_to_flavor_dict(
|
||||
instance_type),
|
||||
image_uuid=image_uuid)
|
||||
|
||||
instance = objects.Instance(nfvi_instance)
|
||||
|
|
|
@ -26,6 +26,8 @@ from nfv_vim.strategy._strategy import SwUpgradeStrategy, strategy_rebuild_from_
|
|||
|
||||
from nfv_vim.nfvi.objects.v1 import UPGRADE_STATE
|
||||
|
||||
import utils
|
||||
|
||||
# Constants
|
||||
|
||||
# Globals
|
||||
|
@ -70,7 +72,8 @@ def create_instance(instance_type_name, instance_name, host_name,
|
|||
oper_state=nfvi.objects.v1.INSTANCE_OPER_STATE.ENABLED,
|
||||
avail_status=list(),
|
||||
action=nfvi.objects.v1.INSTANCE_ACTION.NONE,
|
||||
host_name=host_name, instance_type_uuid=instance_type.uuid,
|
||||
host_name=host_name,
|
||||
instance_type=utils.instance_type_to_flavor_dict(instance_type),
|
||||
image_uuid=image_uuid)
|
||||
|
||||
instance = objects.Instance(nfvi_instance)
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#
|
||||
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||
#
|
||||
# The right to copy, distribute, modify, or otherwise make use
|
||||
# of this software may be licensed only pursuant to the terms
|
||||
# of an applicable Wind River license agreement.
|
||||
#
|
||||
|
||||
from nfv_vim import nfvi
|
||||
|
||||
|
||||
def instance_type_to_flavor_dict(instance_type):
|
||||
flavor = dict()
|
||||
flavor['vcpus'] = instance_type.vcpus
|
||||
flavor['ram'] = instance_type.mem_mb
|
||||
flavor['disk'] = instance_type.disk_gb
|
||||
flavor['ephemeral'] = instance_type.ephemeral_gb
|
||||
flavor['swap'] = instance_type.swap_gb
|
||||
flavor['original_name'] = 'JustAName'
|
||||
extra_specs = dict()
|
||||
extra_specs[
|
||||
nfvi.objects.v1.INSTANCE_TYPE_EXTENSION.LIVE_MIGRATION_TIMEOUT] = \
|
||||
instance_type.live_migration_timeout
|
||||
extra_specs[
|
||||
nfvi.objects.v1.INSTANCE_TYPE_EXTENSION.LIVE_MIGRATION_MAX_DOWNTIME] = \
|
||||
instance_type.live_migration_max_downtime
|
||||
extra_specs[
|
||||
nfvi.objects.v1.INSTANCE_TYPE_EXTENSION.STORAGE_TYPE] = \
|
||||
instance_type.storage_type
|
||||
flavor['extra_specs'] = extra_specs
|
||||
|
||||
return flavor
|
|
@ -72,7 +72,7 @@ deps = {[nfv]deps}
|
|||
coverage
|
||||
setenv = PYTHONDONTWRITEBYTECODE=True
|
||||
#commands = nosetests --pdb --exe -w tests/
|
||||
commands = cp -v ./test_data/nfv_vim_db_17.06_GA {envdir}/
|
||||
commands = cp -v ./test_data/nfv_vim_db_18.03_GA {envdir}/
|
||||
{envbindir}/nosetests --exe -w tests/ '{posargs}'
|
||||
# Use the following for code coverage
|
||||
# {envbindir}/nosetests --exe --cover-erase --cover-branches \
|
||||
|
|
|
@ -315,6 +315,7 @@ class ComputeQueryAttributesResourceType(wsme_types.Base):
|
|||
acceleration_capabilities = unicode
|
||||
virtual_memory = ComputeQueryVirtualMemoryType
|
||||
virtual_cpu = ComputeQueryVirtualCpuType
|
||||
flavour_original_name = unicode
|
||||
|
||||
|
||||
class ComputeQueryResourceType(wsme_types.Base):
|
||||
|
@ -376,9 +377,11 @@ class ComputesAPI(pecan.rest.RestController):
|
|||
virtual_cpu.num_virtual_cpu = response.vcpus
|
||||
|
||||
compute_attributes = ComputeQueryAttributesResourceType()
|
||||
compute_attributes.flavour_id = response.instance_type_uuid
|
||||
compute_attributes.flavour_id = ''
|
||||
compute_attributes.virtual_memory = virtual_memory
|
||||
compute_attributes.virtual_cpu = virtual_cpu
|
||||
compute_attributes.flavour_original_name = \
|
||||
response.instance_type_original_name
|
||||
|
||||
query_result = ComputeQueryResourceType()
|
||||
query_result.compute_id = response.uuid
|
||||
|
@ -448,9 +451,11 @@ class ComputesAPI(pecan.rest.RestController):
|
|||
virtual_cpu.num_virtual_cpu = response.vcpus
|
||||
|
||||
compute_attributes = ComputeQueryAttributesResourceType()
|
||||
compute_attributes.flavour_id = response.instance_type_uuid
|
||||
compute_attributes.flavour_id = ''
|
||||
compute_attributes.virtual_memory = virtual_memory
|
||||
compute_attributes.virtual_cpu = virtual_cpu
|
||||
compute_attributes.flavour_original_name = \
|
||||
response.instance_type_original_name
|
||||
|
||||
query_result = ComputeQueryResourceType()
|
||||
query_result.compute_id = response.uuid
|
||||
|
@ -523,9 +528,11 @@ class ComputesAPI(pecan.rest.RestController):
|
|||
virtual_cpu.num_virtual_cpu = response.vcpus
|
||||
|
||||
compute_attributes = ComputeQueryAttributesResourceType()
|
||||
compute_attributes.flavour_id = response.instance_type_uuid
|
||||
compute_attributes.flavour_id = ''
|
||||
compute_attributes.virtual_memory = virtual_memory
|
||||
compute_attributes.virtual_cpu = virtual_cpu
|
||||
compute_attributes.flavour_original_name = \
|
||||
response.instance_type_original_name
|
||||
|
||||
query_result = ComputeQueryResourceType()
|
||||
query_result.compute_id = response.uuid
|
||||
|
|
|
@ -247,11 +247,11 @@ def database_instance_add(instance_obj):
|
|||
"""
|
||||
db = database_get()
|
||||
session = db.session()
|
||||
query = session.query(model.Instance_v4)
|
||||
query = query.filter(model.Instance_v4.uuid == instance_obj.uuid)
|
||||
query = session.query(model.Instance_v5)
|
||||
query = query.filter(model.Instance_v5.uuid == instance_obj.uuid)
|
||||
instance = query.first()
|
||||
if not instance:
|
||||
instance = model.Instance_v4()
|
||||
instance = model.Instance_v5()
|
||||
instance.uuid = instance_obj.uuid
|
||||
instance.name = instance_obj.name
|
||||
instance.admin_state = instance_obj.admin_state
|
||||
|
@ -259,7 +259,6 @@ def database_instance_add(instance_obj):
|
|||
instance.avail_status = json.dumps(instance_obj.avail_status)
|
||||
instance.action = instance_obj.action
|
||||
instance.host_name = instance_obj.host_name
|
||||
instance.instance_type_uuid = instance_obj.instance_type_uuid
|
||||
instance.image_uuid = instance_obj.image_uuid
|
||||
instance.live_migration_support = instance_obj.supports_live_migration()
|
||||
instance.elapsed_time_in_state = instance_obj.elapsed_time_in_state
|
||||
|
@ -281,7 +280,6 @@ def database_instance_add(instance_obj):
|
|||
instance.avail_status = json.dumps(instance_obj.avail_status)
|
||||
instance.action = instance_obj.action
|
||||
instance.host_name = instance_obj.host_name
|
||||
instance.instance_type_uuid = instance_obj.instance_type_uuid
|
||||
instance.image_uuid = instance_obj.image_uuid
|
||||
instance.live_migration_support = instance_obj.supports_live_migration()
|
||||
instance.elapsed_time_in_state = instance_obj.elapsed_time_in_state
|
||||
|
@ -304,8 +302,8 @@ def database_instance_delete(instance_uuid):
|
|||
"""
|
||||
db = database_get()
|
||||
session = db.session()
|
||||
query = session.query(model.Instance_v4)
|
||||
query.filter(model.Instance_v4.uuid == instance_uuid).delete()
|
||||
query = session.query(model.Instance_v5)
|
||||
query.filter(model.Instance_v5.uuid == instance_uuid).delete()
|
||||
session.commit()
|
||||
|
||||
|
||||
|
@ -315,7 +313,7 @@ def database_instance_get_list():
|
|||
"""
|
||||
db = database_get()
|
||||
session = db.session()
|
||||
query = session.query(model.Instance_v4)
|
||||
query = session.query(model.Instance_v5)
|
||||
instance_objs = list()
|
||||
for instance in query.all():
|
||||
last_action_data_data = json.loads(instance.last_action_data)
|
||||
|
@ -403,7 +401,7 @@ def database_instance_get_list():
|
|||
nfvi_instance_data['avail_status'],
|
||||
nfvi_instance_data['action'],
|
||||
nfvi_instance_data['host_name'],
|
||||
nfvi_instance_data['instance_type_uuid'],
|
||||
nfvi_instance_data['instance_type'],
|
||||
nfvi_instance_data['image_uuid'],
|
||||
nfvi_instance_data['live_migration_support'],
|
||||
attached_volumes,
|
||||
|
|
|
@ -12,33 +12,77 @@ from nfv_common import debug
|
|||
DLOG = debug.debug_get_logger('nfv_vim.database')
|
||||
|
||||
|
||||
def _migrate_instances_v3_to_v4(session, instances_v3, instances_v4):
|
||||
def _migrate_instances_v4_to_v5(session, instances_v4, instances_v5):
|
||||
"""
|
||||
Migrate instances_v3 table to instances_v4 table
|
||||
Migrate instances_v4 table to instances_v5 table
|
||||
"""
|
||||
if 0 == len(instances_v4):
|
||||
for instance_v3 in instances_v3:
|
||||
instance_v4 = model.Instance_v4()
|
||||
instance_v4.data = instance_v3.data
|
||||
nfvi_instance_data = json.loads(instance_v3.nfvi_instance_data)
|
||||
# Use previous recovery_priority if it exists, otherwise use None
|
||||
nfvi_instance_data['recovery_priority'] = \
|
||||
nfvi_instance_data.get('recovery_priority', None)
|
||||
# Use previous timeout if it exists, otherwise use None
|
||||
nfvi_instance_data['live_migration_timeout'] = \
|
||||
nfvi_instance_data.get('live_migration_timeout', None)
|
||||
instance_v4.nfvi_instance_data = json.dumps(nfvi_instance_data)
|
||||
session.add(instance_v4)
|
||||
if 0 == len(instances_v5):
|
||||
instance_type_query = session.query(model.InstanceType)
|
||||
instance_types = instance_type_query.all()
|
||||
|
||||
for instance_v4 in instances_v4:
|
||||
instance_v5 = model.Instance_v5()
|
||||
instance_type_uuid = instance_v4.instance_type_uuid
|
||||
del instance_v4.data['instance_type_uuid']
|
||||
instance_v5.data = instance_v4.data
|
||||
nfvi_instance_data = json.loads(instance_v4.nfvi_instance_data)
|
||||
|
||||
# We can build the flavor details embedded in the instance from
|
||||
# the flavor referenced from the original instance.
|
||||
for instance_type in instance_types:
|
||||
if instance_type.uuid == instance_type_uuid:
|
||||
break
|
||||
else:
|
||||
DLOG.error("Missing instance type: %s" % instance_type_uuid)
|
||||
continue
|
||||
|
||||
flavor = dict()
|
||||
flavor['vcpus'] = instance_type.vcpus
|
||||
flavor['ram'] = instance_type.mem_mb
|
||||
flavor['disk'] = instance_type.disk_gb
|
||||
flavor['ephemeral'] = instance_type.ephemeral_gb
|
||||
flavor['swap'] = instance_type.swap_gb
|
||||
flavor['original_name'] = instance_type.name
|
||||
|
||||
# Re-create the flavor extra_specs, undoing all the mangling that
|
||||
# the VIM did when converting the flavor to an instance_type.
|
||||
extra_specs = dict()
|
||||
guest_services = instance_type.guest_services
|
||||
if 'heartbeat' in guest_services:
|
||||
if guest_services['heartbeat'] == 'configured':
|
||||
extra_specs['sw:wrs:guest:heartbeat'] = 'true'
|
||||
else:
|
||||
extra_specs['sw:wrs:guest:heartbeat'] = 'false'
|
||||
if instance_type.auto_recovery is not None:
|
||||
if instance_type.auto_recovery:
|
||||
extra_specs['sw:wrs:auto_recovery'] = 'true'
|
||||
else:
|
||||
extra_specs['sw:wrs:auto_recovery'] = 'false'
|
||||
if instance_type.live_migration_timeout is not None:
|
||||
extra_specs['hw:wrs:live_migration_timeout'] = \
|
||||
instance_type.live_migration_timeout
|
||||
if instance_type.live_migration_max_downtime is not None:
|
||||
extra_specs['hw:wrs:live_migration_max_downtime'] = \
|
||||
instance_type.live_migration_max_downtime
|
||||
if instance_type.storage_type is not None:
|
||||
extra_specs['aggregate_instance_extra_specs:storage'] = \
|
||||
instance_type.storage_type
|
||||
if extra_specs:
|
||||
flavor['extra_specs'] = extra_specs
|
||||
|
||||
nfvi_instance_data['instance_type'] = flavor
|
||||
instance_v5.nfvi_instance_data = json.dumps(nfvi_instance_data)
|
||||
session.add(instance_v5)
|
||||
|
||||
|
||||
def migrate_tables(session, table_names):
|
||||
"""
|
||||
Migrate database tables
|
||||
"""
|
||||
if 'instances_v3' in table_names and 'instances_v4' in table_names:
|
||||
instances_v3_query = session.query(model.Instance_v3)
|
||||
instances_v3 = instances_v3_query.all()
|
||||
if 'instances_v4' in table_names and 'instances_v5' in table_names:
|
||||
instances_v4_query = session.query(model.Instance_v4)
|
||||
instances_v4 = instances_v4_query.all()
|
||||
_migrate_instances_v3_to_v4(session, instances_v3, instances_v4)
|
||||
instances_v3_query.delete()
|
||||
instances_v5_query = session.query(model.Instance_v5)
|
||||
instances_v5 = instances_v5_query.all()
|
||||
_migrate_instances_v4_to_v5(session, instances_v4, instances_v5)
|
||||
instances_v4_query.delete()
|
||||
|
|
|
@ -7,24 +7,6 @@ import sys
|
|||
import types
|
||||
|
||||
|
||||
def _upgrade_instance_types_v1(table_row_data):
|
||||
"""
|
||||
Upgrade instance_types_v1 table to the current release
|
||||
"""
|
||||
# Once all the patches for 15.12 have been released this code is not needed.
|
||||
# The VIM on startup will re-sync with Nova.
|
||||
return None
|
||||
|
||||
|
||||
def _upgrade_volumes(table_row_data):
|
||||
"""
|
||||
Upgrade volumes table to the current release
|
||||
"""
|
||||
# Once all the patches for 15.12 have been released this code is not needed.
|
||||
# The VIM on startup will re-sync with Cinder.
|
||||
return None
|
||||
|
||||
|
||||
def upgrade_table_row_data(table_name, table_row_data):
|
||||
"""
|
||||
Upgrade a database table row data
|
||||
|
|
|
@ -21,5 +21,5 @@ from _service_host import ServiceHost
|
|||
from _hypervisor import Hypervisor
|
||||
from _instance_type import InstanceType
|
||||
from _instance_group import InstanceGroup
|
||||
from _instance import Instance_v3, Instance_v4
|
||||
from _instance import Instance_v4, Instance_v5
|
||||
from _sw_update import SoftwareUpdate
|
||||
|
|
|
@ -3,44 +3,14 @@
|
|||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
from sqlalchemy import Column, String, Boolean
|
||||
from sqlalchemy import Column, String, Boolean, Text
|
||||
|
||||
from _base import Base, AsDictMixin
|
||||
|
||||
|
||||
class Instance_v3(AsDictMixin, Base):
|
||||
"""
|
||||
Instance Database Table
|
||||
"""
|
||||
__tablename__ = 'instances_v3'
|
||||
|
||||
uuid = Column(String(64), nullable=False, primary_key=True)
|
||||
name = Column(String(64), nullable=False)
|
||||
admin_state = Column(String(64), nullable=False)
|
||||
oper_state = Column(String(64), nullable=False)
|
||||
avail_status = Column(String(64), nullable=False)
|
||||
action = Column(String(64), nullable=False)
|
||||
host_name = Column(String(64), nullable=True)
|
||||
instance_type_uuid = Column(String(64), nullable=False)
|
||||
image_uuid = Column(String(64), nullable=True)
|
||||
live_migration_support = Column(Boolean, nullable=False)
|
||||
elapsed_time_in_state = Column(String(64), nullable=False)
|
||||
elapsed_time_on_host = Column(String(64), nullable=False)
|
||||
action_data = Column(String(2048), nullable=True)
|
||||
last_action_data = Column(String(2048), nullable=True)
|
||||
guest_services = Column(String(2048), nullable=True)
|
||||
nfvi_instance_data = Column(String(2048), nullable=False)
|
||||
recoverable = Column(Boolean, nullable=False)
|
||||
unlock_to_recover = Column(Boolean, nullable=False)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Instance(%r, %r)>" % (self.uuid, self.name)
|
||||
|
||||
|
||||
class Instance_v4(AsDictMixin, Base):
|
||||
"""
|
||||
Instance Database Table
|
||||
Note: Upversioned due to changes in the nfvi_instance_data.
|
||||
"""
|
||||
__tablename__ = 'instances_v4'
|
||||
|
||||
|
@ -65,3 +35,31 @@ class Instance_v4(AsDictMixin, Base):
|
|||
|
||||
def __repr__(self):
|
||||
return "<Instance(%r, %r)>" % (self.uuid, self.name)
|
||||
|
||||
|
||||
class Instance_v5(AsDictMixin, Base):
|
||||
"""
|
||||
Instance Database Table
|
||||
"""
|
||||
__tablename__ = 'instances_v5'
|
||||
|
||||
uuid = Column(String(64), nullable=False, primary_key=True)
|
||||
name = Column(String(64), nullable=False)
|
||||
admin_state = Column(String(64), nullable=False)
|
||||
oper_state = Column(String(64), nullable=False)
|
||||
avail_status = Column(String(64), nullable=False)
|
||||
action = Column(String(64), nullable=False)
|
||||
host_name = Column(String(64), nullable=True)
|
||||
image_uuid = Column(String(64), nullable=True)
|
||||
live_migration_support = Column(Boolean, nullable=False)
|
||||
elapsed_time_in_state = Column(String(64), nullable=False)
|
||||
elapsed_time_on_host = Column(String(64), nullable=False)
|
||||
action_data = Column(String(2048), nullable=True)
|
||||
last_action_data = Column(String(2048), nullable=True)
|
||||
guest_services = Column(String(2048), nullable=True)
|
||||
nfvi_instance_data = Column(Text(), nullable=False)
|
||||
recoverable = Column(Boolean, nullable=False)
|
||||
unlock_to_recover = Column(Boolean, nullable=False)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Instance(%r, %r)>" % (self.uuid, self.name)
|
||||
|
|
|
@ -2250,7 +2250,17 @@ def instance_manage_events(instance, enabling=False):
|
|||
event_id = event_log.EVENT_ID.INSTANCE_COLD_MIGRATE_REVERTED
|
||||
|
||||
elif last_event(event_log.EVENT_ID.INSTANCE_RESIZING):
|
||||
if instance.from_instance_type_uuid == instance.instance_type_uuid:
|
||||
# Note: This isn't going to work, because the unversioned
|
||||
# notifications we get from nova do not include the flavor details.
|
||||
# When we switch to use the versioned notifications, they will
|
||||
# include the flavor. However, I have verified that the original
|
||||
# reason for this clause (CGTS-4099) no longer needs this code -
|
||||
# nova will explicitly fail a resize if the disk size in the new
|
||||
# flavor is smaller than the old flavor (instead of silently
|
||||
# failing). I am leaving this code here in case there are some
|
||||
# other silent failures we want to catch in the future.
|
||||
if instance.from_instance_type_original_name == \
|
||||
instance.instance_type_original_name:
|
||||
event_id = event_log.EVENT_ID.INSTANCE_RESIZE_FAILED
|
||||
|
||||
elif last_event(event_log.EVENT_ID.INSTANCE_RESIZE_CONFIRM_BEGIN):
|
||||
|
|
|
@ -34,7 +34,8 @@ def _create_instance_callback(success, instance_name, instance_uuid):
|
|||
response.avail_status = instance.avail_status
|
||||
response.action = instance.action
|
||||
response.host_name = instance.host_name
|
||||
response.instance_type_uuid = instance.instance_type_uuid
|
||||
response.instance_type_original_name \
|
||||
= instance.instance_type_original_name
|
||||
response.image_uuid = instance.image_uuid
|
||||
response.vcpus = instance.vcpus
|
||||
response.memory_mb = instance.memory_mb
|
||||
|
@ -301,7 +302,8 @@ def vim_instance_api_get_instance(connection, msg):
|
|||
response.avail_status = instance.avail_status
|
||||
response.action = instance.action
|
||||
response.host_name = instance.host_name
|
||||
response.instance_type_uuid = instance.instance_type_uuid
|
||||
response.instance_type_original_name \
|
||||
= instance.instance_type_original_name
|
||||
response.image_uuid = instance.image_uuid
|
||||
response.vcpus = instance.vcpus
|
||||
response.memory_mb = instance.memory_mb
|
||||
|
@ -341,7 +343,8 @@ def vim_instance_api_get_instances(connection, msg):
|
|||
response.avail_status = instance.avail_status
|
||||
response.action = instance.action
|
||||
response.host_name = instance.host_name
|
||||
response.instance_type_uuid = instance.instance_type_uuid
|
||||
response.instance_type_original_name \
|
||||
= instance.instance_type_original_name
|
||||
response.image_uuid = instance.image_uuid
|
||||
response.vcpus = instance.vcpus
|
||||
response.memory_mb = instance.memory_mb
|
||||
|
|
|
@ -227,12 +227,18 @@ def _nfvi_instance_state_change_callback(nfvi_instance):
|
|||
nfvi.nfvi_get_instance(nfvi_instance.uuid,
|
||||
_query_nfvi_instance_callback())
|
||||
else:
|
||||
# Make sure we don't overwrite some information, if it isn't available
|
||||
# We are handling a notification from nova, which will not have all
|
||||
# the data for the nfvi_instance we store as part of our instance
|
||||
# object. As part of the processing of the notification, we are going
|
||||
# to save the nfvi_instance to the database, so make sure we don't
|
||||
# overwrite data that did not come in the notification, by retrieving
|
||||
# it from the instance object. Yes - this is ugly. No - I'm not going
|
||||
# to rewrite this now.
|
||||
if nfvi_instance.tenant_id is None:
|
||||
nfvi_instance.tenant_id = instance.tenant_uuid
|
||||
|
||||
if nfvi_instance.instance_type_uuid is None:
|
||||
nfvi_instance.instance_type_uuid = instance.instance_type_uuid
|
||||
if nfvi_instance.instance_type is None:
|
||||
nfvi_instance.instance_type = instance._nfvi_instance.instance_type
|
||||
|
||||
if nfvi_instance.image_uuid is None:
|
||||
nfvi_instance.image_uuid = instance.image_uuid
|
||||
|
|
|
@ -78,7 +78,6 @@ from _nfvi_network_module import nfvi_update_subnet
|
|||
from _nfvi_network_module import nfvi_delete_subnet
|
||||
from _nfvi_network_module import nfvi_get_subnet
|
||||
from _nfvi_network_module import nfvi_get_subnets
|
||||
from _nfvi_compute_module import nfvi_get_service_hosts
|
||||
from _nfvi_compute_module import nfvi_get_host_aggregates
|
||||
from _nfvi_compute_module import nfvi_get_hypervisors
|
||||
from _nfvi_compute_module import nfvi_get_hypervisor
|
||||
|
|
|
@ -12,15 +12,6 @@ DLOG = debug.debug_get_logger('nfv_vim.nfvi.nfvi_compute_module')
|
|||
_compute_plugin = None
|
||||
|
||||
|
||||
def nfvi_get_service_hosts(callback):
|
||||
"""
|
||||
Get a list of service hosts
|
||||
"""
|
||||
cmd_id = _compute_plugin.invoke_plugin('get_service_hosts',
|
||||
callback=callback)
|
||||
return cmd_id
|
||||
|
||||
|
||||
def nfvi_get_host_aggregates(callback):
|
||||
"""
|
||||
Get a list of host aggregates
|
||||
|
|
|
@ -40,13 +40,6 @@ class NFVIComputeAPI(object):
|
|||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_service_hosts(self, future, callback):
|
||||
"""
|
||||
Get a list of service hosts from the plugin
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_host_aggregates(self, future, callback):
|
||||
"""
|
||||
|
|
|
@ -9,6 +9,7 @@ from datetime import datetime
|
|||
from _object import ObjectData
|
||||
|
||||
from nfv_common.helpers import Object, Constant, Constants, Singleton
|
||||
from _instance_type import INSTANCE_TYPE_EXTENSION
|
||||
|
||||
|
||||
@six.add_metaclass(Singleton)
|
||||
|
@ -389,7 +390,7 @@ class Instance(ObjectData):
|
|||
NFVI Instance Object
|
||||
"""
|
||||
def __init__(self, uuid, name, tenant_id, admin_state, oper_state,
|
||||
avail_status, action, host_name, instance_type_uuid,
|
||||
avail_status, action, host_name, instance_type,
|
||||
image_uuid=None, live_migration_support=None,
|
||||
attached_volumes=None, nfvi_data=None,
|
||||
recovery_priority=None, live_migration_timeout=None):
|
||||
|
@ -402,7 +403,7 @@ class Instance(ObjectData):
|
|||
admin_state=admin_state, oper_state=oper_state,
|
||||
avail_status=avail_status, action=action,
|
||||
host_name=host_name,
|
||||
instance_type_uuid=instance_type_uuid,
|
||||
instance_type=instance_type,
|
||||
image_uuid=image_uuid,
|
||||
live_migration_support=live_migration_support,
|
||||
attached_volumes=attached_volumes,
|
||||
|
@ -410,3 +411,125 @@ class Instance(ObjectData):
|
|||
live_migration_timeout=live_migration_timeout))
|
||||
|
||||
self.nfvi_data = nfvi_data
|
||||
|
||||
@property
|
||||
def instance_type_vcpus(self):
|
||||
"""
|
||||
Returns the vcpus from the flavor
|
||||
"""
|
||||
return self.get('instance_type').get('vcpus')
|
||||
|
||||
@property
|
||||
def instance_type_mem_mb(self):
|
||||
"""
|
||||
Returns the ram from the flavor
|
||||
"""
|
||||
return self.get('instance_type').get('ram')
|
||||
|
||||
@property
|
||||
def instance_type_disk_gb(self):
|
||||
"""
|
||||
Returns the disk from the flavor
|
||||
"""
|
||||
return self.get('instance_type').get('disk')
|
||||
|
||||
@property
|
||||
def instance_type_ephemeral_gb(self):
|
||||
"""
|
||||
Returns the ephemeral from the flavor
|
||||
"""
|
||||
return self.get('instance_type').get('ephemeral')
|
||||
|
||||
@property
|
||||
def instance_type_swap_gb(self):
|
||||
"""
|
||||
Returns the swap from the flavor
|
||||
"""
|
||||
return self.get('instance_type').get('swap')
|
||||
|
||||
@property
|
||||
def instance_type_original_name(self):
|
||||
"""
|
||||
Returns the original name from the flavor
|
||||
"""
|
||||
return self.get('instance_type').get('original_name')
|
||||
|
||||
@property
|
||||
def instance_type_guest_services(self):
|
||||
"""
|
||||
Returns the guest services from the flavor extra specs
|
||||
"""
|
||||
guest_services = dict()
|
||||
flavor_data_extra = self.get('instance_type').get('extra_specs', None)
|
||||
if flavor_data_extra is not None:
|
||||
heartbeat = flavor_data_extra.get(
|
||||
INSTANCE_TYPE_EXTENSION.GUEST_HEARTBEAT, None)
|
||||
if heartbeat and 'true' == heartbeat.lower():
|
||||
guest_heartbeat = INSTANCE_GUEST_SERVICE_STATE.CONFIGURED
|
||||
else:
|
||||
guest_heartbeat = None
|
||||
if guest_heartbeat is not None:
|
||||
guest_services['heartbeat'] = guest_heartbeat
|
||||
|
||||
return guest_services
|
||||
|
||||
@property
|
||||
def instance_type_auto_recovery(self):
|
||||
"""
|
||||
Returns the auto recovery from the flavor extra specs
|
||||
"""
|
||||
auto_recovery = None
|
||||
flavor_data_extra = self.get('instance_type').get('extra_specs', None)
|
||||
if flavor_data_extra is not None:
|
||||
auto_recovery = flavor_data_extra.get(
|
||||
INSTANCE_TYPE_EXTENSION.INSTANCE_AUTO_RECOVERY, None)
|
||||
if auto_recovery is not None:
|
||||
if 'false' == auto_recovery.lower():
|
||||
auto_recovery = False
|
||||
elif 'true' == auto_recovery.lower():
|
||||
auto_recovery = True
|
||||
else:
|
||||
raise AttributeError("sw:wrs:auto_recovery is %s, "
|
||||
"expecting 'true' or 'false'"
|
||||
% auto_recovery)
|
||||
|
||||
return auto_recovery
|
||||
|
||||
@property
|
||||
def instance_type_live_migration_timeout(self):
|
||||
"""
|
||||
Returns the live migration timeout from the flavor extra specs
|
||||
"""
|
||||
live_migration_timeout = None
|
||||
flavor_data_extra = self.get('instance_type').get('extra_specs', None)
|
||||
if flavor_data_extra is not None:
|
||||
live_migration_timeout = flavor_data_extra.get(
|
||||
INSTANCE_TYPE_EXTENSION.LIVE_MIGRATION_TIMEOUT, None)
|
||||
|
||||
return live_migration_timeout
|
||||
|
||||
@property
|
||||
def instance_type_live_migration_max_downtime(self):
|
||||
"""
|
||||
Returns the live migration max downtime from the flavor extra specs
|
||||
"""
|
||||
live_migration_max_downtime = None
|
||||
flavor_data_extra = self.get('instance_type').get('extra_specs', None)
|
||||
if flavor_data_extra is not None:
|
||||
live_migration_max_downtime = flavor_data_extra.get(
|
||||
INSTANCE_TYPE_EXTENSION.LIVE_MIGRATION_MAX_DOWNTIME, None)
|
||||
|
||||
return live_migration_max_downtime
|
||||
|
||||
@property
|
||||
def instance_type_storage_type(self):
|
||||
"""
|
||||
Returns the storage type from the flavor extra specs
|
||||
"""
|
||||
storage_type = None
|
||||
flavor_data_extra = self.get('instance_type').get('extra_specs', None)
|
||||
if flavor_data_extra is not None:
|
||||
storage_type = flavor_data_extra.get(
|
||||
INSTANCE_TYPE_EXTENSION.STORAGE_TYPE, None)
|
||||
|
||||
return storage_type
|
||||
|
|
|
@ -805,16 +805,10 @@ class Instance(ObjectData):
|
|||
self._events = list()
|
||||
self._guest_heartbeat_alarms = list()
|
||||
self._guest_heartbeat_events = list()
|
||||
self._vcpus = None
|
||||
self._memory_mb = None
|
||||
self._disk_gb = None
|
||||
self._ephemeral_gb = None
|
||||
self._swap_gb = None
|
||||
self._live_migrate_from_host = None
|
||||
self._cold_migrate_from_host = None
|
||||
self._evacuate_from_host = None
|
||||
self._resize_from_instance_type = None
|
||||
self._auto_recovery = None
|
||||
self._resize_from_instance_type_original_name = None
|
||||
self._max_live_migrate_wait_in_secs = None
|
||||
self._max_live_migration_downtime_in_ms = None
|
||||
self._max_cold_migrate_wait_in_secs = None
|
||||
|
@ -957,20 +951,20 @@ class Instance(ObjectData):
|
|||
return None
|
||||
|
||||
@property
|
||||
def instance_type_uuid(self):
|
||||
def instance_type_original_name(self):
|
||||
"""
|
||||
Returns the instance type identifier
|
||||
Returns the instance type original name
|
||||
"""
|
||||
if self._nfvi_instance is not None:
|
||||
return self._nfvi_instance.instance_type_uuid
|
||||
return self._nfvi_instance.instance_type_original_name
|
||||
return None
|
||||
|
||||
@property
|
||||
def from_instance_type_uuid(self):
|
||||
def from_instance_type_original_name(self):
|
||||
"""
|
||||
Returns the from instance type identifier
|
||||
Returns the from instance type original name
|
||||
"""
|
||||
return self._resize_from_instance_type
|
||||
return self._resize_from_instance_type_original_name
|
||||
|
||||
@property
|
||||
def image_uuid(self):
|
||||
|
@ -1091,100 +1085,35 @@ class Instance(ObjectData):
|
|||
"""
|
||||
Returns the number of vcpus needed for the instance
|
||||
"""
|
||||
from nfv_vim import tables
|
||||
|
||||
if self._vcpus is not None:
|
||||
return self._vcpus
|
||||
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid, None)
|
||||
if instance_type is not None:
|
||||
if instance_type.have_details():
|
||||
self._vcpus = instance_type.vcpus
|
||||
|
||||
if self._vcpus is None:
|
||||
return 0
|
||||
return self._vcpus
|
||||
return self._nfvi_instance.instance_type_vcpus
|
||||
|
||||
@property
|
||||
def memory_mb(self):
|
||||
"""
|
||||
Returns the memory needed for this instance
|
||||
"""
|
||||
from nfv_vim import tables
|
||||
|
||||
if self._memory_mb is not None:
|
||||
return self._memory_mb
|
||||
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid, None)
|
||||
if instance_type is not None:
|
||||
if instance_type.have_details():
|
||||
self._memory_mb = instance_type.mem_mb
|
||||
|
||||
if self._memory_mb is None:
|
||||
return 0
|
||||
return self._memory_mb
|
||||
return self._nfvi_instance.instance_type_mem_mb
|
||||
|
||||
@property
|
||||
def disk_gb(self):
|
||||
"""
|
||||
Returns the disk size needed for this instance
|
||||
"""
|
||||
from nfv_vim import tables
|
||||
|
||||
if self._disk_gb is not None:
|
||||
return self._disk_gb
|
||||
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid, None)
|
||||
if instance_type is not None:
|
||||
if instance_type.have_details():
|
||||
self._disk_gb = instance_type.disk_gb
|
||||
|
||||
if self._disk_gb is None:
|
||||
return 0
|
||||
return self._disk_gb
|
||||
return self._nfvi_instance.instance_type_disk_gb
|
||||
|
||||
@property
|
||||
def ephemeral_gb(self):
|
||||
"""
|
||||
Returns the swap size needed for this instance
|
||||
Returns the ephemeral size needed for this instance
|
||||
"""
|
||||
from nfv_vim import tables
|
||||
|
||||
if self._ephemeral_gb is not None:
|
||||
return self._ephemeral_gb
|
||||
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid, None)
|
||||
if instance_type is not None:
|
||||
if instance_type.have_details():
|
||||
self._ephemeral_gb = instance_type.ephemeral_gb
|
||||
|
||||
if self._ephemeral_gb is None:
|
||||
return 0
|
||||
return self._ephemeral_gb
|
||||
return self._nfvi_instance.instance_type_ephemeral_gb
|
||||
|
||||
@property
|
||||
def swap_gb(self):
|
||||
"""
|
||||
Returns the swap size needed for this instance
|
||||
"""
|
||||
from nfv_vim import tables
|
||||
|
||||
if self._swap_gb is not None:
|
||||
return self._swap_gb
|
||||
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid, None)
|
||||
if instance_type is not None:
|
||||
if instance_type.have_details():
|
||||
self._swap_gb = instance_type.swap_gb
|
||||
|
||||
if self._swap_gb is None:
|
||||
return 0
|
||||
return self._swap_gb
|
||||
return self._nfvi_instance.instance_type_swap_gb
|
||||
|
||||
@property
|
||||
def fail_reason(self):
|
||||
|
@ -1226,20 +1155,13 @@ class Instance(ObjectData):
|
|||
"""
|
||||
Returns the guest services for this instance
|
||||
"""
|
||||
from nfv_vim import tables
|
||||
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
if instance_type_table is not None:
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid,
|
||||
None)
|
||||
if instance_type is not None:
|
||||
if instance_type.have_details():
|
||||
if instance_type.guest_services:
|
||||
for service in instance_type.guest_services.keys():
|
||||
self._guest_services.provision(service)
|
||||
else:
|
||||
if self._guest_services.are_provisioned():
|
||||
self._guest_services.delete()
|
||||
if self._nfvi_instance.instance_type_guest_services:
|
||||
for service in \
|
||||
self._nfvi_instance.instance_type_guest_services.keys():
|
||||
self._guest_services.provision(service)
|
||||
else:
|
||||
if self._guest_services.are_provisioned():
|
||||
self._guest_services.delete()
|
||||
|
||||
return self._guest_services
|
||||
|
||||
|
@ -1300,34 +1222,21 @@ class Instance(ObjectData):
|
|||
"""
|
||||
from nfv_vim import tables
|
||||
|
||||
if self._auto_recovery is not None:
|
||||
DLOG.debug("Auto-Recovery is %s for %s." % (self._auto_recovery,
|
||||
self.name))
|
||||
return self._auto_recovery
|
||||
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
if instance_type_table is not None:
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid,
|
||||
None)
|
||||
if instance_type is not None:
|
||||
if instance_type.have_details() \
|
||||
and instance_type.auto_recovery is not None:
|
||||
self._auto_recovery = instance_type.auto_recovery
|
||||
auto_recovery = self._nfvi_instance.instance_type_auto_recovery
|
||||
|
||||
# instance type attributes overwrite image ones
|
||||
if self._auto_recovery is None:
|
||||
if auto_recovery is None:
|
||||
image_table = tables.tables_get_image_table()
|
||||
image = image_table.get(self.image_uuid, None)
|
||||
if image is not None and image.auto_recovery is not None:
|
||||
self._auto_recovery = image.auto_recovery
|
||||
auto_recovery = image.auto_recovery
|
||||
|
||||
# turn on instance auto recovery by default
|
||||
if self._auto_recovery is None:
|
||||
self._auto_recovery = True
|
||||
if auto_recovery is None:
|
||||
auto_recovery = True
|
||||
|
||||
DLOG.debug("Auto-Recovery set to %s for %s."
|
||||
% (self._auto_recovery, self.name))
|
||||
return self._auto_recovery
|
||||
DLOG.debug("Auto-Recovery is %s for %s." % (auto_recovery, self.name))
|
||||
return auto_recovery
|
||||
|
||||
@property
|
||||
def max_live_migrate_wait_in_secs(self):
|
||||
|
@ -1344,16 +1253,10 @@ class Instance(ObjectData):
|
|||
timeout_from_image = int(image.live_migration_timeout)
|
||||
|
||||
# check the flavor for the live migration timeout
|
||||
timeout_from_flavor = None
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
if instance_type_table is not None:
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid,
|
||||
None)
|
||||
if instance_type is not None:
|
||||
if instance_type.have_details() \
|
||||
and instance_type.live_migration_timeout is not None:
|
||||
timeout_from_flavor \
|
||||
= int(instance_type.live_migration_timeout)
|
||||
timeout_from_flavor = \
|
||||
self._nfvi_instance.instance_type_live_migration_timeout
|
||||
if timeout_from_flavor is not None:
|
||||
timeout_from_flavor = int(timeout_from_flavor)
|
||||
|
||||
# check the instance for the live migration timeout
|
||||
timeout_from_instance = None
|
||||
|
@ -1454,15 +1357,10 @@ class Instance(ObjectData):
|
|||
= image.live_migration_max_downtime
|
||||
|
||||
# instance type attributes overwrite image ones
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
if instance_type_table is not None:
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid,
|
||||
None)
|
||||
if instance_type is not None:
|
||||
if instance_type.have_details() \
|
||||
and instance_type.live_migration_max_downtime is not None:
|
||||
self._max_live_migration_downtime_in_ms \
|
||||
= instance_type.live_migration_max_downtime
|
||||
if self._nfvi_instance.instance_type_live_migration_max_downtime is \
|
||||
not None:
|
||||
self._max_live_migration_downtime_in_ms = \
|
||||
self._nfvi_instance.instance_type_live_migration_max_downtime
|
||||
|
||||
# convert value to integer
|
||||
if self._max_live_migration_downtime_in_ms is not None:
|
||||
|
@ -1534,8 +1432,6 @@ class Instance(ObjectData):
|
|||
"""
|
||||
Returns true if the instance can be cold-migrated
|
||||
"""
|
||||
from nfv_vim import tables
|
||||
|
||||
if not system_initiated:
|
||||
# Always allow user initiated cold migration
|
||||
return True
|
||||
|
@ -1544,13 +1440,7 @@ class Instance(ObjectData):
|
|||
# Always allow cold migration when booted from a volume
|
||||
return True
|
||||
|
||||
storage_type = None
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
if instance_type_table is not None:
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid,
|
||||
None)
|
||||
if instance_type is not None and instance_type.have_details():
|
||||
storage_type = instance_type.storage_type
|
||||
storage_type = self._nfvi_instance.instance_type_storage_type
|
||||
|
||||
if STORAGE_TYPE.REMOTE_BACKED == storage_type:
|
||||
# Always allow cold migration with remote storage
|
||||
|
@ -1580,8 +1470,6 @@ class Instance(ObjectData):
|
|||
"""
|
||||
Returns true if the instance can be evacuated
|
||||
"""
|
||||
from nfv_vim import tables
|
||||
|
||||
if not system_initiated:
|
||||
# Always allow user initiated evacuate
|
||||
return True
|
||||
|
@ -1590,13 +1478,7 @@ class Instance(ObjectData):
|
|||
# Always allow evacuate when booted from a volume
|
||||
return True
|
||||
|
||||
storage_type = None
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
if instance_type_table is not None:
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid,
|
||||
None)
|
||||
if instance_type is not None and instance_type.have_details():
|
||||
storage_type = instance_type.storage_type
|
||||
storage_type = self._nfvi_instance.instance_type_storage_type
|
||||
|
||||
if STORAGE_TYPE.REMOTE_BACKED == storage_type:
|
||||
# Always allow evacuate with remote storage
|
||||
|
@ -1626,27 +1508,20 @@ class Instance(ObjectData):
|
|||
"""
|
||||
Returns true if this instance supports live-migration
|
||||
"""
|
||||
from nfv_vim import tables
|
||||
|
||||
if self._live_migration_support is not None:
|
||||
if not self._live_migration_support:
|
||||
return False
|
||||
|
||||
instance_type_table = tables.tables_get_instance_type_table()
|
||||
if instance_type_table is not None:
|
||||
instance_type = instance_type_table.get(self.instance_type_uuid,
|
||||
None)
|
||||
if instance_type is not None and instance_type.have_details():
|
||||
if self.image_uuid is None:
|
||||
if (instance_type.swap_gb or
|
||||
instance_type.ephemeral_gb):
|
||||
return (STORAGE_TYPE.REMOTE_BACKED ==
|
||||
instance_type.storage_type)
|
||||
return True
|
||||
else:
|
||||
return (instance_type.storage_type in [
|
||||
STORAGE_TYPE.LOCAL_IMAGE_BACKED,
|
||||
STORAGE_TYPE.REMOTE_BACKED])
|
||||
if self.image_uuid is None:
|
||||
if (self._nfvi_instance.instance_type_swap_gb or
|
||||
self._nfvi_instance.instance_type_ephemeral_gb):
|
||||
return (STORAGE_TYPE.REMOTE_BACKED ==
|
||||
self._nfvi_instance.instance_type_storage_type)
|
||||
return True
|
||||
else:
|
||||
return (self._nfvi_instance.instance_type_storage_type in [
|
||||
STORAGE_TYPE.LOCAL_IMAGE_BACKED,
|
||||
STORAGE_TYPE.REMOTE_BACKED])
|
||||
|
||||
return True
|
||||
|
||||
|
@ -2649,13 +2524,14 @@ class Instance(ObjectData):
|
|||
if nfvi.objects.v1.INSTANCE_ACTION.REBUILDING != self.action:
|
||||
cleanup_evacuate_from_host = True
|
||||
|
||||
cleanup_resize_from_instance_type = False
|
||||
cleanup_resize_from_instance_type_original_name = False
|
||||
if nfvi.objects.v1.INSTANCE_ACTION.RESIZING == nfvi_action:
|
||||
if nfvi.objects.v1.INSTANCE_ACTION.RESIZING != self.action:
|
||||
self._resize_from_instance_type = self.instance_type_uuid
|
||||
self._resize_from_instance_type_original_name = \
|
||||
self._nfvi_instance.instance_type_original_name
|
||||
else:
|
||||
if nfvi.objects.v1.INSTANCE_ACTION.RESIZING != self.action:
|
||||
cleanup_resize_from_instance_type = True
|
||||
cleanup_resize_from_instance_type_original_name = True
|
||||
|
||||
if nfvi.objects.v1.INSTANCE_AVAIL_STATUS.CRASHED \
|
||||
in nfvi_avail_status:
|
||||
|
@ -2713,8 +2589,8 @@ class Instance(ObjectData):
|
|||
if cleanup_evacuate_from_host:
|
||||
self._evacuate_from_host = None
|
||||
|
||||
if cleanup_resize_from_instance_type:
|
||||
self._resize_from_instance_type = None
|
||||
if cleanup_resize_from_instance_type_original_name:
|
||||
self._resize_from_instance_type_original_name = None
|
||||
|
||||
if need_recovery:
|
||||
instance_director.recover_instance(self, force_fail=True)
|
||||
|
@ -3137,7 +3013,6 @@ class Instance(ObjectData):
|
|||
data['action'] = self.action
|
||||
data['host_name'] = self.host_name
|
||||
data['image_uuid'] = self.image_uuid
|
||||
data['instance_type_uuid'] = self.instance_type_uuid
|
||||
data['action_data'] = self.action_data.as_dict()
|
||||
data['last_action_data'] = self.last_action_data.as_dict()
|
||||
if self.guest_services.are_provisioned():
|
||||
|
|
|
@ -81,7 +81,7 @@ class APIResponseCreateInstance(RPCMessage):
|
|||
action = None
|
||||
host_uuid = None
|
||||
host_name = None
|
||||
instance_type_uuid = None
|
||||
instance_type_original_name = None
|
||||
image_uuid = None
|
||||
vcpus = None
|
||||
memory_mb = None
|
||||
|
@ -108,7 +108,7 @@ class APIResponseCreateInstance(RPCMessage):
|
|||
msg['action'] = self.action
|
||||
msg['host_uuid'] = self.host_uuid
|
||||
msg['host_name'] = self.host_name
|
||||
msg['instance_type_uuid'] = self.instance_type_uuid
|
||||
msg['instance_type_original_name'] = self.instance_type_original_name
|
||||
msg['image_uuid'] = self.image_uuid
|
||||
msg['vcpus'] = self.vcpus
|
||||
msg['memory_mb'] = self.memory_mb
|
||||
|
@ -130,7 +130,8 @@ class APIResponseCreateInstance(RPCMessage):
|
|||
self.action = msg.get('action', None)
|
||||
self.host_uuid = msg.get('host_uuid', None)
|
||||
self.host_name = msg.get('host_name', None)
|
||||
self.instance_type_uuid = msg.get('instance_type_uuid', None)
|
||||
self.instance_type_original_name = msg.get(
|
||||
'instance_type_original_name', None)
|
||||
self.image_uuid = msg.get('image_uuid', None)
|
||||
self.vcpus = msg.get('vcpus', None)
|
||||
self.memory_mb = msg.get('memory_mb', None)
|
||||
|
@ -678,7 +679,7 @@ class APIResponseGetInstance(RPCMessage):
|
|||
action = None
|
||||
host_uuid = None
|
||||
host_name = None
|
||||
instance_type_uuid = None
|
||||
instance_type_original_name = None
|
||||
image_uuid = None
|
||||
vcpus = None
|
||||
memory_mb = None
|
||||
|
@ -704,7 +705,7 @@ class APIResponseGetInstance(RPCMessage):
|
|||
msg['action'] = self.action
|
||||
msg['host_uuid'] = self.host_uuid
|
||||
msg['host_name'] = self.host_name
|
||||
msg['instance_type_uuid'] = self.instance_type_uuid
|
||||
msg['instance_type_original_name'] = self.instance_type_original_name
|
||||
msg['image_uuid'] = self.image_uuid
|
||||
msg['vcpus'] = self.vcpus
|
||||
msg['memory_mb'] = self.memory_mb
|
||||
|
@ -725,7 +726,8 @@ class APIResponseGetInstance(RPCMessage):
|
|||
self.action = msg.get('action', None)
|
||||
self.host_uuid = msg.get('host_uuid', None)
|
||||
self.host_name = msg.get('host_name', None)
|
||||
self.instance_type_uuid = msg.get('instance_type_uuid', None)
|
||||
self.instance_type_original_name = msg.get(
|
||||
'instance_type_original_name', None)
|
||||
self.image_uuid = msg.get('image_uuid', None)
|
||||
self.vcpus = msg.get('vcpus', None)
|
||||
self.memory_mb = msg.get('memory_mb', None)
|
||||
|
|
Loading…
Reference in New Issue