nfv/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/openstack/nova.py

1662 lines
56 KiB
Python
Executable File

#
# Copyright (c) 2015-2016 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import six
import json
from nfv_common import debug
from nfv_common.helpers import Constants, Constant, Singleton
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 pike release.
NOVA_API_VERSION = '2.53'
NOVA_API_VERSION_NEWTON = '2.38'
@six.add_metaclass(Singleton)
class HypervisorState(Constants):
"""
HYPERVISOR STATE Constants
"""
UP = Constant('up')
DOWN = Constant('down')
@six.add_metaclass(Singleton)
class HypervisorStatus(Constants):
"""
HYPERVISOR STATUS Constants
"""
ENABLED = Constant('enabled')
DISABLED = Constant('disabled')
@six.add_metaclass(Singleton)
class VmState(Constants):
"""
VM STATE Constants
"""
ACTIVE = Constant('active')
BUILDING = Constant('building')
RESIZED = Constant('resized')
PAUSED = Constant('paused')
SUSPENDED = Constant('suspended')
STOPPED = Constant('stopped')
DELETED = Constant('deleted')
ERROR = Constant('error')
@six.add_metaclass(Singleton)
class VmTaskState(Constants):
"""
VM TASK-STATE Constants
"""
NONE = Constant('none')
MIGRATING = Constant('migrating')
MIGRATING_ROLLBACK = Constant('migrating-rollback')
DELETING = Constant('deleting')
SOFT_DELETING = Constant('soft-deleting')
POWERING_OFF = Constant('powering-off')
POWERING_ON = Constant('powering-on')
PAUSING = Constant('pausing')
UNPAUSING = Constant('unpausing')
SUSPENDING = Constant('suspending')
RESUMING = Constant('resuming')
REBOOTING = Constant('rebooting')
REBOOT_PENDING = Constant('reboot_pending')
REBOOT_STARTED = Constant('reboot_started')
REBOOTING_HARD = Constant('rebooting_hard')
REBOOT_PENDING_HARD = Constant('reboot_pending_hard')
REBOOT_STARTED_HARD = Constant('reboot_started_hard')
REBUILDING = Constant('rebuilding')
REBUILD_BLOCK_DEVICE_MAPPING = Constant('rebuild_block_device_mapping')
REBUILD_SPAWNING = Constant('rebuild_spawning')
RESIZE_PREP = Constant('resize_prep')
RESIZE_MIGRATING = Constant('resize_migrating')
RESIZE_MIGRATED = Constant('resize_migrated')
RESIZE_FINISH = Constant('resize_finish')
RESIZE_REVERTING = Constant('resize_reverting')
RESIZE_CONFIRMING = Constant('resize_confirming')
@six.add_metaclass(Singleton)
class VmTaskStatus(Constants):
"""
VM TASK-STATUS Constants
"""
NONE = Constant('none')
START = Constant('start')
COMPLETE = Constant('complete')
@six.add_metaclass(Singleton)
class VmPowerState(Constants):
"""
VM POWER-STATE Constants
"""
NO_STATE = Constant(0)
RUNNING = Constant(1)
PAUSED = Constant(3)
SHUTDOWN = Constant(4)
CRASHED = Constant(6)
SUSPENDED = Constant(7)
BUILDING = Constant(9)
@six.add_metaclass(Singleton)
class VmPowerStateStr(Constants):
"""
VM POWER-STATE String Constants
"""
NO_STATE = Constant('pending')
RUNNING = Constant('running')
PAUSED = Constant('paused')
SHUTDOWN = Constant('shutdown')
CRASHED = Constant('crashed')
SUSPENDED = Constant('suspended')
BUILDING = Constant('building')
@six.add_metaclass(Singleton)
class VmAction(Constants):
"""
VM ACTION Constants
"""
PAUSE = Constant('pause')
UNPAUSE = Constant('unpause')
SUSPEND = Constant('suspend')
RESUME = Constant('resume')
LIVE_MIGRATE = Constant('os-migrateLive')
MIGRATE = Constant('migrate')
RESIZE = Constant('resize')
CONFIRM_RESIZE = Constant('confirmResize')
REVERT_RESIZE = Constant('revertResize')
REBOOT = Constant('reboot')
REBUILD = Constant('rebuild')
START = Constant('os-start')
STOP = Constant('os-stop')
@six.add_metaclass(Singleton)
class VmRebootType(Constants):
"""
VM REBOOT TYPE Constants
"""
SOFT = Constant('SOFT')
HARD = Constant('HARD')
@six.add_metaclass(Singleton)
class RPCMessageTypes(Constants):
"""
RPC Message Type Constants
"""
NOVA_SERVER_STATE_CHANGE = Constant('nova-server-state-change')
NOVA_SERVER_ACTION_CHANGE = Constant('nova-server-action-change')
NOVA_SERVER_DELETE = Constant('nova-server-delete')
# Constant Instantiation
HYPERVISOR_STATE = HypervisorState()
HYPERVISOR_STATUS = HypervisorStatus()
VM_STATE = VmState()
VM_TASK_STATE = VmTaskState()
VM_TASK_STATUS = VmTaskStatus()
VM_POWER_STATE = VmPowerState()
VM_POWER_STATE_STR = VmPowerStateStr()
VM_ACTION = VmAction()
VM_REBOOT_TYPE = VmRebootType()
RPC_MESSAGE_TYPE = RPCMessageTypes()
def vm_power_state_str(power_state):
"""
Convert the VM POWER-STATE to a string
"""
if VM_POWER_STATE.NO_STATE == power_state:
return "no-state"
elif VM_POWER_STATE.RUNNING == power_state:
return "running"
elif VM_POWER_STATE.PAUSED == power_state:
return "paused"
elif VM_POWER_STATE.SHUTDOWN == power_state:
return "shutdown"
elif VM_POWER_STATE.CRASHED == power_state:
return "crashed"
elif VM_POWER_STATE.SUSPENDED == power_state:
return "suspended"
elif VM_POWER_STATE.BUILDING == power_state:
return "building"
else:
return "unknown"
def get_host_aggregates(token):
"""
Asks OpenStack Nova for a list of host aggregates
"""
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-aggregates" % 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_hypervisor(token, hypervisor_uuid):
"""
Asks OpenStack Nova for a hypervisor details
"""
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-hypervisors/%s" % (token.get_tenant_id(),
hypervisor_uuid)
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_hypervisors(token):
"""
Asks OpenStack Nova for a list of hypervisors
"""
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-hypervisors" % 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_flavors(token, page_limit=None, next_page=None):
"""
Asks OpenStack Nova for a list of flavors
"""
if next_page is None:
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/flavors?is_public=None" % token.get_tenant_id()
if page_limit is not None:
api_cmd += "&limit=%s" % page_limit
else:
api_cmd = next_page
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 create_flavor(token, flavor_id, flavor_name, vcpus, ram_mb, disk_gb,
ephemeral_gb=None, swap_mb=None):
"""
Asks OpenStack Nova to create a flavor
"""
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/flavors" % token.get_tenant_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
api_cmd_payload = dict()
api_cmd_payload['flavor'] = dict()
api_cmd_payload['flavor']['id'] = flavor_id
api_cmd_payload['flavor']['name'] = flavor_name
api_cmd_payload['flavor']['vcpus'] = vcpus
api_cmd_payload['flavor']['ram'] = ram_mb
api_cmd_payload['flavor']['disk'] = disk_gb
if ephemeral_gb is not None:
api_cmd_payload['flavor']['OS-FLV-EXT-DATA:ephemeral'] = ephemeral_gb
if swap_mb is not None:
api_cmd_payload['flavor']['swap'] = swap_mb
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
return response
def delete_flavor(token, flavor_id):
"""
Asks OpenStack Nova to delete a flavor
"""
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/flavors/%s" % (token.get_tenant_id(), flavor_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, "DELETE", api_cmd, api_cmd_headers)
return response
def get_flavor(token, flavor_id):
"""
Asks OpenStack Nova to get a flavor
"""
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/flavors/%s" % (token.get_tenant_id(), flavor_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 set_flavor_extra_specs(token, flavor_id, extra_specs):
"""
Asks OpenStack Nova to set a flavor with extra specs
"""
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/flavors/%s/os-extra_specs" % (token.get_tenant_id(),
flavor_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
api_cmd_payload = dict()
api_cmd_payload['extra_specs'] = extra_specs
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
return response
def get_flavor_extra_specs(token, flavor_id):
"""
Asks OpenStack Nova to get a flavor
"""
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/flavors/%s/os-extra_specs" % (token.get_tenant_id(),
flavor_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_server_groups(token, all_projects=True):
"""
Asks OpenStack Nova for a list of servers
"""
tenant_id = token.get_tenant_id()
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-server-groups" % tenant_id
if all_projects:
api_cmd += "?all_projects=True"
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_servers(token, page_limit=None, next_page=None, all_tenants=True,
context=None):
"""
Asks OpenStack Nova for a list of servers
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
if next_page is None:
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/servers" % tenant_id
if page_limit is not None:
api_cmd += "?limit=%s" % page_limit
if all_tenants:
api_cmd += "&all_tenants=1"
elif all_tenants:
api_cmd += "?all_tenants=1"
else:
api_cmd = next_page
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
if context is None:
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "GET", api_cmd,
api_cmd_headers)
return response
def create_server(token, server_name, flavor_id, image_id, block_devices=None,
networks=None, context=None):
"""
Asks OpenStack Nova to create a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers" % tenant_id
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
server = dict()
server['name'] = server_name
server['flavorRef'] = flavor_id
if image_id is not None:
server['imageRef'] = image_id
if block_devices is not None:
server['block_device_mapping_v2'] = block_devices
if networks is not None:
network_list = list()
for network in networks:
if network['uuid'] is not None:
network_list.append(network)
if network_list:
server['networks'] = network_list
api_cmd_payload = dict()
api_cmd_payload['server'] = server
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def delete_server(token, server_id, context=None):
"""
Asks OpenStack Nova to delete a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "DELETE", api_cmd, api_cmd_headers)
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "DELETE", api_cmd,
api_cmd_headers)
return response
def get_server(token, server_id, context=None):
"""
Asks OpenStack Nova to get server details
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "GET", api_cmd,
api_cmd_headers)
return response
def live_migrate_server(token, server_id, to_host_name=None,
block_storage_migration='auto', context=None):
"""
Asks OpenStack Nova to live migrate a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
server = dict()
server['block_migration'] = block_storage_migration
if to_host_name:
server['host'] = to_host_name
else:
server['host'] = None
api_cmd_payload = dict()
api_cmd_payload['os-migrateLive'] = server
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def cold_migrate_server(token, server_id, to_host_name=None, migrate=None,
context=None):
"""
Asks OpenStack Nova to cold migrate a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_payload = dict()
if to_host_name is not None:
server = dict()
server['host'] = to_host_name
api_cmd_payload['migrate'] = server
else:
api_cmd_payload['migrate'] = migrate
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def resize_server(token, server_id, flavor_id, context=None):
"""
Asks OpenStack Nova to resize a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
resize = dict()
resize['flavorRef'] = str(flavor_id)
api_cmd_payload = dict()
api_cmd_payload['resize'] = resize
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def resize_server_confirm(token, server_id, context=None):
"""
Asks OpenStack Nova to confirm resize of a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_payload = dict()
api_cmd_payload['confirmResize'] = None
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def resize_server_revert(token, server_id, context=None):
"""
Asks OpenStack Nova to revert resize of a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_payload = dict()
api_cmd_payload['revertResize'] = None
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def cold_migrate_server_confirm(token, server_id, context=None):
"""
Asks OpenStack Nova to confirm cold migrate of a server
"""
return resize_server_confirm(token, server_id, context)
def cold_migrate_server_revert(token, server_id, context=None):
"""
Asks OpenStack Nova to revert cold migrate of a server
"""
return resize_server_revert(token, server_id, context)
def evacuate_server(token, server_id, admin_password=None, to_host_name=None,
context=None):
"""
Asks OpenStack Nova to evacuate a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
server = dict()
if admin_password is not None:
server['adminPass'] = admin_password
if to_host_name is not None:
server['host'] = to_host_name
api_cmd_payload = dict()
api_cmd_payload['evacuate'] = server
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def reboot_server(token, server_id, reboot_type, context=None):
"""
Asks OpenStack Nova to reboot a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
reboot = dict()
reboot['type'] = reboot_type
api_cmd_payload = dict()
api_cmd_payload['reboot'] = reboot
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def rebuild_server(token, server_id, server_name, image_id,
admin_password=None, context=None):
"""
Asks OpenStack Nova to rebuild a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
rebuild = dict()
rebuild['name'] = server_name
rebuild['imageRef'] = image_id
if admin_password is not None:
rebuild['adminPass'] = admin_password
api_cmd_payload = dict()
api_cmd_payload['rebuild'] = rebuild
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def pause_server(token, server_id, context=None):
"""
Asks OpenStack Nova to pause a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_payload = dict()
api_cmd_payload['pause'] = None
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def unpause_server(token, server_id, context=None):
"""
Asks OpenStack Nova to unpause a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_payload = dict()
api_cmd_payload['unpause'] = None
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def suspend_server(token, server_id, context=None):
"""
Asks OpenStack Nova to suspend a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_payload = dict()
api_cmd_payload['suspend'] = None
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def resume_server(token, server_id, context=None):
"""
Asks OpenStack Nova to resume a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_payload = dict()
api_cmd_payload['resume'] = None
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def start_server(token, server_id, context=None):
"""
Asks OpenStack Nova to start a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_payload = dict()
api_cmd_payload['os-start'] = None
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def stop_server(token, server_id, context=None):
"""
Asks OpenStack Nova to stop a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_payload = dict()
api_cmd_payload['os-stop'] = None
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def reset_server_state(token, server_id, state, context=None):
"""
Asks OpenStack Nova to reset a server to the given state
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/action" % (tenant_id, server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
server_state = dict()
server_state['state'] = state
api_cmd_payload = dict()
api_cmd_payload['os-resetState'] = server_state
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
def attach_volume(token, server_id, volume_id, device_name, context=None):
"""
Asks OpenStack Nova to attach a volume to a server
"""
if context is None:
tenant_id = token.get_tenant_id()
else:
tenant_id = context.tenant_id
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/servers/%s/os-volume_attachments" % (tenant_id,
server_id)
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
volume_attach = dict()
volume_attach['volumeId'] = volume_id
volume_attach['device'] = device_name
api_cmd_payload = dict()
api_cmd_payload['volumeAttachment'] = volume_attach
if context is None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
else:
if context.version is not None:
api_cmd_headers['X-OpenStack-Nova-API-Version'] = context.version
response = rest_api_request_with_context(context, "POST",
api_cmd, api_cmd_headers,
context.content)
return response
_rpc_message_service_action_event_types = {
'compute.instance.pause.start':
(VM_TASK_STATE.PAUSING, VM_TASK_STATUS.START),
'compute.instance.pause.end':
(VM_TASK_STATE.PAUSING, VM_TASK_STATUS.COMPLETE),
'compute.instance.unpause.start':
(VM_TASK_STATE.UNPAUSING, VM_TASK_STATUS.START),
'compute.instance.unpause.end':
(VM_TASK_STATE.UNPAUSING, VM_TASK_STATUS.COMPLETE),
'compute.instance.suspend':
(VM_TASK_STATE.SUSPENDING, VM_TASK_STATUS.COMPLETE),
'compute.instance.resume.start':
(VM_TASK_STATE.RESUMING, VM_TASK_STATUS.START),
'compute.instance.resume.end':
(VM_TASK_STATE.RESUMING, VM_TASK_STATUS.COMPLETE),
'compute.instance.reboot.start':
(VM_TASK_STATE.REBOOTING, VM_TASK_STATUS.START),
'compute.instance.reboot.end':
(VM_TASK_STATE.REBOOTING, VM_TASK_STATUS.COMPLETE),
'compute.instance.power_off.start':
(VM_TASK_STATE.POWERING_OFF, VM_TASK_STATUS.START),
'compute.instance.power_off.end':
(VM_TASK_STATE.POWERING_OFF, VM_TASK_STATUS.COMPLETE),
'compute.instance.power_on.start':
(VM_TASK_STATE.POWERING_ON, VM_TASK_STATUS.START),
'compute.instance.power_on.end':
(VM_TASK_STATE.POWERING_ON, VM_TASK_STATUS.COMPLETE),
'compute.instance.live_migration.pre.start':
(VM_TASK_STATE.MIGRATING, VM_TASK_STATUS.START),
'compute.instance.live_migration.post.dest.end':
(VM_TASK_STATE.MIGRATING, VM_TASK_STATUS.COMPLETE),
'compute.instance.live_migration._rollback.start':
(VM_TASK_STATE.MIGRATING_ROLLBACK, VM_TASK_STATUS.START),
'compute.instance.live_migration.rollback.dest.end':
(VM_TASK_STATE.MIGRATING_ROLLBACK, VM_TASK_STATUS.COMPLETE),
'compute.instance.resize.confirm.start':
(VM_TASK_STATE.RESIZE_CONFIRMING, VM_TASK_STATUS.START),
'compute.instance.resize.confirm.end':
(VM_TASK_STATE.RESIZE_CONFIRMING, VM_TASK_STATUS.COMPLETE),
'compute.instance.resize.revert.start':
(VM_TASK_STATE.RESIZE_REVERTING, VM_TASK_STATUS.START),
'compute.instance.resize.revert.end':
(VM_TASK_STATE.RESIZE_REVERTING, VM_TASK_STATUS.COMPLETE),
}
def rpc_message_server_action_change_filter(message):
"""
Filter OpenStack Nova RPC messages for server action changes
"""
for event_type in _rpc_message_service_action_event_types:
payload = None
if event_type == message.get('event_type', ""):
payload = message.get('payload', {})
else:
oslo_version = message.get('oslo.version', "")
if oslo_version in ["2.0"]:
oslo_message = json.loads(message.get('oslo.message', None))
if oslo_message is not None:
if event_type == oslo_message.get('event_type', ""):
payload = oslo_message.get('payload', {})
if payload is not None:
server_uuid = payload.get('instance_id', None)
if server_uuid is not None:
task_state, task_status \
= _rpc_message_service_action_event_types[event_type]
action_change = dict()
action_change['server_uuid'] = server_uuid
action_change['task_state'] = task_state
action_change['task_status'] = task_status
action_change['reason'] = payload.get('exception', None)
return action_change
return None
def rpc_message_server_state_change_filter(message):
"""
Filter OpenStack Nova RPC messages for server state changes
"""
payload = None
event_type = message.get('event_type', "")
if event_type == "compute.instance.update":
payload = message.get('payload', {})
else:
oslo_version = message.get('oslo.version', "")
if oslo_version in ["2.0"]:
oslo_message = json.loads(message.get('oslo.message', None))
if oslo_message is not None:
event_type = oslo_message.get('event_type', "")
if event_type == "compute.instance.update":
payload = oslo_message.get('payload', {})
if payload is not None:
server_uuid = payload.get('instance_id', None)
server_name = payload.get('display_name', None)
tenant_id = payload.get('tenant_id', None)
prev_vm_state = payload.get('old_state', None)
prev_task_state = payload.get('old_task_state', None)
vm_state = payload.get('state', None)
task_state = payload.get('new_task_state', None)
power_state = payload.get('power_state', None)
host_name = payload.get('host', None)
image_meta = payload.get('image_meta', None)
image_id = image_meta.get('base_image_ref', None)
if not image_id:
image_id = None
instance_metadata = payload.get('metadata', {})
recovery_priority = get_recovery_priority(instance_metadata,
server_name)
live_migration_timeout = get_live_migration_timeout(instance_metadata,
server_name)
DLOG.verbose("Nova-RPC(instance-state-update): server_uuid=%s, "
"prev_vm_state=%s, prev_task_state=%s, vm_state=%s, "
"task_state=%s, power_state=%s, host_name=%s, "
"recovery_priority=%s, live_migration_timeout=%s"
% (server_uuid, prev_vm_state, prev_task_state,
vm_state, task_state, power_state, host_name,
recovery_priority, live_migration_timeout))
if server_uuid is not None:
state_change = dict()
state_change['server_uuid'] = server_uuid
state_change['server_name'] = server_name
state_change['tenant_id'] = tenant_id
state_change['vm_state'] = vm_state
state_change['task_state'] = task_state
state_change['power_state'] = power_state
state_change['host_name'] = host_name
state_change['image_id'] = image_id
state_change['recovery_priority'] = recovery_priority
state_change['live_migration_timeout'] = live_migration_timeout
return state_change
return None
def rpc_message_server_delete_filter(message):
"""
Filter OpenStack Nova RPC messages for server delete
"""
payload = None
event_type = message.get('event_type', "")
if event_type == "compute.instance.delete.start":
payload = message.get('payload', {})
else:
oslo_version = message.get('oslo.version', "")
if oslo_version in ["2.0"]:
oslo_message = json.loads(message.get('oslo.message', None))
if oslo_message is not None:
event_type = oslo_message.get('event_type', "")
if event_type == "compute.instance.delete.start":
payload = oslo_message.get('payload', {})
if payload is not None:
server_uuid = payload.get('instance_id', None)
DLOG.verbose("Nova-RPC(instance-deleting): server_uuid=%s." % server_uuid)
if server_uuid is not None:
delete = dict()
delete['server_uuid'] = server_uuid
return delete
return None
def create_host_services(token, host_name):
"""
Asks OpenStack Nova to create services 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/create" % token.get_tenant_id()
api_cmd_headers = dict()
api_cmd_headers['wrs-header'] = 'true'
api_cmd_headers['Content-Type'] = "application/json"
# The create is a StarlingX 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'
api_cmd_payload['host'] = host_name
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
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
"""
url = token.get_service_url(OPENSTACK_SERVICE.NOVA, strip_version=True)
if url is None:
raise ValueError("OpenStack Nova URL is invalid")
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:
compute_service_id = get_host_service_id(token, host_name,
'nova-compute')
except NotFound:
# No service to delete
return response
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)
return response
def enable_host_services(token, host_name):
"""
Asks OpenStack Nova to enable services 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")
# 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'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
api_cmd_payload = dict()
api_cmd_payload['status'] = 'enabled'
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
return response
def disable_host_services(token, host_name):
"""
Asks OpenStack Nova to disable services 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")
# 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'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
api_cmd_payload = dict()
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))
return response
def query_host_services(token, host_name):
"""
Asks OpenStack Nova for the administrative state of services 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" % (token.get_tenant_id(),
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
response = rest_api_request(token, "GET", api_cmd)
host_status = 'unknown'
services = response.result_data.get('services', list())
for service in services:
service_name = service.get('binary', '')
if 'nova-compute' == service_name:
host_status = service.get('status', 'unknown')
break
if not ('enabled' == host_status or 'disabled' == host_status):
DLOG.error("Nova administrative status query failed for %s, "
"defaulting to disabled." % host_name)
host_status = 'disabled'
return host_status
def notify_host_enabled(token, host_name):
"""
Notify OpenStack Nova that a host is enabled
"""
url = token.get_service_url(OPENSTACK_SERVICE.NOVA, strip_version=True)
if url is None:
raise ValueError("OpenStack Nova URL is invalid")
# 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'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
api_cmd_payload = dict()
api_cmd_payload['forced_down'] = False
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
return response
def notify_host_disabled(token, host_name):
"""
Notify OpenStack Nova that a host is disabled
"""
url = token.get_service_url(OPENSTACK_SERVICE.NOVA, strip_version=True)
if url is None:
raise ValueError("OpenStack Nova URL is invalid")
# 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'
api_cmd_headers['Content-Type'] = "application/json"
api_cmd_headers['X-OpenStack-Nova-API-Version'] = NOVA_API_VERSION
api_cmd_payload = dict()
api_cmd_payload['forced_down'] = True
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
json.dumps(api_cmd_payload))
return response
def query_host_aggregates(token):
"""
Asks OpenStack Nova for the host aggregates
"""
url = token.get_service_url(OPENSTACK_SERVICE.NOVA, strip_version=True)
if url is None:
raise ValueError("OpenStack Nova URL is invalid")
api_cmd = "/v2.1/%s/os-aggregates" % token.get_tenant_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, "GET", api_cmd)
return response
def get_recovery_priority(metadata, instance_name):
# Check instance metadata for the recovery priority
recovery_priority = None
recovery_priority_str = metadata.get('sw:wrs:recovery_priority',
None)
if recovery_priority_str is not None:
try:
recovery_priority = int(recovery_priority_str)
if recovery_priority not in range(1, 11):
DLOG.error("Invalid recovery priority %s for %s" %
(recovery_priority_str,
instance_name))
recovery_priority = None
except ValueError:
DLOG.error("Invalid recovery priority %s for %s" %
(recovery_priority_str,
instance_name))
recovery_priority = None
return recovery_priority
def get_live_migration_timeout(metadata, instance_name):
# Check instance metadata for the live migration timeout
live_migration_timeout = None
live_migration_timeout_str = metadata.get('hw:wrs:live_migration_timeout',
None)
if live_migration_timeout_str is not None:
try:
live_migration_timeout = int(live_migration_timeout_str)
except ValueError:
DLOG.error("Invalid live migration timeout %s for %s" %
(live_migration_timeout_str,
instance_name))
live_migration_timeout = None
return live_migration_timeout