diff --git a/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_compute_api.py b/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_compute_api.py index ecc2d6dd..80cf7c89 100755 --- a/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_compute_api.py +++ b/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_compute_api.py @@ -24,6 +24,7 @@ from nfv_plugins.nfvi_plugins.openstack import exceptions from nfv_plugins.nfvi_plugins.openstack import openstack from nfv_plugins.nfvi_plugins.openstack import nova from nfv_plugins.nfvi_plugins.openstack import rest_api +from nfv_plugins.nfvi_plugins.openstack.objects import OPENSTACK_SERVICE DLOG = debug.debug_get_logger('nfv_plugins.nfvi_plugins.compute_api') @@ -383,6 +384,513 @@ class NFVIComputeAPI(nfvi.api.v1.NFVIComputeAPI): self._max_action_request_wait_in_secs = 45 self._auto_accept_action_requests = False + def _host_supports_nova_compute(self, personality): + return (('compute' in personality) and + (self._directory.get_service_info( + OPENSTACK_SERVICE.NOVA) is not None)) + + def notify_host_enabled(self, future, host_uuid, host_name, + host_personality, callback): + """ + Notify host enabled + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + # Only applies to compute hosts + if not self._host_supports_nova_compute(host_personality): + response['completed'] = True + response['reason'] = '' + return + + response['reason'] = 'failed to get token from keystone' + + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s." % host_uuid) + return + + self._token = future.result.data + + response['reason'] = 'failed to notify nova that host is enabled' + + future.work(nova.notify_host_enabled, self._token, + host_name) + future.result = (yield) + + if not future.result.is_complete(): + return + + response['completed'] = True + response['reason'] = '' + + 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 notify " + "nova host services enabled, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to notify " + "nova host services enabled, error=%s." % e) + + finally: + callback.send(response) + callback.close() + + def notify_host_disabled(self, future, host_uuid, host_name, + host_personality, callback): + """ + Notify host disabled + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_nova_compute(host_personality): + response['reason'] = 'failed to get token from keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s." % host_uuid) + return + + self._token = future.result.data + + response['reason'] = 'failed to notify nova that ' \ + 'host is disabled' + + future.work(nova.notify_host_disabled, self._token, + host_name) + + try: + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Nova notify-host-disabled.") + return + + except exceptions.OpenStackRestAPIException as e: + if httplib.NOT_FOUND != e.http_status_code: + raise + + response['completed'] = True + response['reason'] = '' + + 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 notify " + "nova host services disabled, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to notify " + "nova host services disabled, error=%s." % e) + + finally: + callback.send(response) + callback.close() + + def create_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Create Host Services, notify Nova to create services for a host + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_nova_compute(host_personality): + response['reason'] = 'failed to get openstack token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to create nova services' + + # Send the create request to Nova. + future.work(nova.create_host_services, self._token, + host_name) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Nova create-host-services failed, operation " + "did not complete, host_uuid=%s, host_name=%s." + % (host_uuid, host_name)) + return + + result_data = future.result.data['service'] + if not ('created' == result_data['status'] and + host_name == result_data['host'] and + 'nova-compute' == result_data['binary']): + DLOG.error("Nova create-host-services failed, invalid " + "response, host_uuid=%s, host_name=%s, " + "response=%s." + % (host_uuid, host_name, response)) + return + + response['reason'] = 'failed to disable nova services' + + # Send the disable request to Nova. + future.work(nova.disable_host_services, self._token, + host_name) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Nova disable-host-services failed, operation " + "did not complete, host_uuid=%s, host_name=%s." + % (host_uuid, host_name)) + return + + result_data = future.result.data['service'] + + if not ('disabled' == result_data['status'] and + host_name == result_data['host'] and + 'nova-compute' == result_data['binary']): + DLOG.error("Nova disable-host-services failed, invalid " + "response, host_uuid=%s, host_name=%s, " + "response=%s." + % (host_uuid, host_name, response)) + return + + response['completed'] = True + response['reason'] = '' + + 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 create " + "nova services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to create %s nova " + "services, error=%s." % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def delete_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Delete Host Services, Notify Nova to delete services for a host. + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_nova_compute(host_personality): + response['reason'] = 'failed to get openstack token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to delete nova services' + + # Send the delete request to Nova. + future.work(nova.delete_host_services, self._token, + host_name) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Nova delete-host-services failed, operation " + "did not complete, host_uuid=%s, host_name=%s." + % (host_uuid, host_name)) + return + + response['completed'] = True + response['reason'] = '' + + 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 delete " + "nova services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to delete %s " + "nova services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def enable_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Enable Host Services, Notify Nova to enable services for a host. + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_nova_compute(host_personality): + response['reason'] = 'failed to get openstack token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to enable nova services' + + # Send the Enable request to Nova. + future.work(nova.enable_host_services, self._token, + host_name) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Nova enable-host-services failed, operation " + "did not complete, host_uuid=%s, host_name=%s." + % (host_uuid, host_name)) + return + + result_data = future.result.data['service'] + if not ('enabled' == result_data['status'] and + host_name == result_data['host'] and + 'nova-compute' == result_data['binary']): + DLOG.error("Nova enable-host-services failed, operation " + "did not complete, host_uuid=%s, host_name=%s." + % (host_uuid, host_name)) + return + + response['completed'] = True + response['reason'] = '' + + 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 enable " + "nova services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to enable %s " + "nova services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def disable_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Disable Host Services, notify nova to disable services for a host + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + # The following only applies to compute hosts + if self._host_supports_nova_compute(host_personality): + response['reason'] = 'failed to get openstack token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to disable nova services' + + # Send the Disable request to Nova. + future.work(nova.disable_host_services, self._token, + host_name) + + try: + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Nova disable-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." + % (host_uuid, host_name)) + return + + result_data = future.result.data['service'] + if not ('disabled' == result_data['status'] and + host_name == result_data['host'] and + 'nova-compute' == result_data['binary']): + DLOG.error("Nova disable-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." + % (host_uuid, host_name)) + return + + except exceptions.OpenStackRestAPIException as e: + if httplib.NOT_FOUND != e.http_status_code: + raise + + response['completed'] = True + response['reason'] = '' + + 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 disable " + "nova services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to disable %s " + "nova services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def query_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Query Host Services, return state of Nova Services for a host + """ + response = dict() + response['completed'] = False + response['result-data'] = 'enabled' + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_nova_compute(host_personality): + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + # Send Query request to Nova. + future.work(nova.query_host_services, self._token, + host_name) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Nova query-host-services failed, operation " + "did not complete, host_uuid=%s, host_name=%s." + % (host_uuid, host_name)) + return + + if future.result.data != 'enabled': + response['result-data'] = 'disabled' + response['completed'] = True + return + + 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 query " + "nova services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to query %s " + "nova services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + def _action_request_complete(self, request_uuid, http_status_code, http_headers=None, http_body=None): """ diff --git a/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_guest_api.py b/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_guest_api.py index 6ed08bee..3132bb45 100755 --- a/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_guest_api.py +++ b/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_guest_api.py @@ -15,6 +15,7 @@ from nfv_plugins.nfvi_plugins.openstack import rest_api from nfv_plugins.nfvi_plugins.openstack import exceptions from nfv_plugins.nfvi_plugins.openstack import openstack from nfv_plugins.nfvi_plugins.openstack import guest +from nfv_plugins.nfvi_plugins.openstack.objects import OPENSTACK_SERVICE DLOG = debug.debug_get_logger('nfv_plugins.nfvi_plugins.guest_api') @@ -205,6 +206,7 @@ class NFVIGuestAPI(nfvi.api.v1.NFVIGuestAPI): super(NFVIGuestAPI, self).__init__() self._token = None self._directory = None + self._openstack_directory = None self._rest_api_server = None self._host_services_query_callback = None self._guest_services_query_callback = None @@ -212,6 +214,11 @@ class NFVIGuestAPI(nfvi.api.v1.NFVIGuestAPI): self._guest_services_alarm_notify_callbacks = list() self._guest_services_action_notify_callbacks = list() + def _host_supports_nova_compute(self, personality): + return (('compute' in personality) and + (self._openstack_directory.get_service_info( + OPENSTACK_SERVICE.NOVA) is not None)) + def guest_services_create(self, future, instance_uuid, host_name, services, callback): """ @@ -589,6 +596,361 @@ class NFVIGuestAPI(nfvi.api.v1.NFVIGuestAPI): callback.send(response) callback.close() + def create_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Create Host Services, notify Guest to create services for a host + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_nova_compute(host_personality): + response['reason'] = 'failed to get platform token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to create guest services' + + try: + # Send the create request to Guest. + future.work(guest.host_services_create, + self._token, + host_uuid, host_name) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Guest host-services-create failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." + % (host_uuid, host_name)) + return + + response['reason'] = 'failed to disable guest services' + + # Send the disable request to Guest + future.work(guest.host_services_disable, + self._token, + host_uuid, host_name) + future.result = (yield) + + if not future.result.is_complete(): + # do not return since the disable will be retried + # by audit + DLOG.error("Guest host-services-disable failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." + % (host_uuid, host_name)) + + except exceptions.OpenStackRestAPIException as e: + # Guest can send a 404 if it hasn't got the host + # inventory yet. + # Guest will catch up later, no need to fail here. + if httplib.NOT_FOUND != e.http_status_code: + raise + + response['completed'] = True + response['reason'] = '' + + 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 create " + "guest services on host, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to create %s " + "guest services, error=%s." % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def delete_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Delete Host Services, notify Guest to delete services for a host + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_nova_compute(host_personality): + response['reason'] = 'failed to get platform token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to delete guest services' + + # Send the delete request to Guest. + future.work(guest.host_services_delete, self._token, + host_uuid) + try: + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Guest host-services-delete for host " + "failed, operation did not complete, " + "host_uuid=%s, host_name=%s." + % (host_uuid, host_name)) + return + + except exceptions.OpenStackRestAPIException as e: + if httplib.NOT_FOUND != e.http_status_code: + raise + + response['completed'] = True + response['reason'] = '' + + 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 delete " + "host services on host, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to delete %s " + "guest services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def enable_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Enable Host Services, notify Guest to enable services for a host. + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_nova_compute(host_personality): + response['reason'] = 'failed to get platform token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to enable guest services' + + # Send the Enable request to Guest + future.work(guest.host_services_enable, self._token, + host_uuid, host_name) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Guest host-services-enable failed, operation " + "did not complete, host_uuid=%s, host_name=%s." + % (host_uuid, host_name)) + return + + response['completed'] = True + response['reason'] = '' + + 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 enable " + "guest services on host, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to enable %s " + "guest services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def disable_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Notifies Guest to disable their services for the specified + host (as applicable) + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + # The following only applies to compute hosts + if self._host_supports_nova_compute(host_personality): + response['reason'] = 'failed to get platform token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to disable guest services' + + # Send the Disable request to Guest. + future.work(guest.host_services_disable, self._token, + host_uuid, host_name) + + try: + future.result = (yield) + + if not future.result.is_complete(): + # Do not return since the disable will be retried + # by audit + DLOG.error("Guest host-services-disable failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." + % (host_uuid, host_name)) + + except exceptions.OpenStackRestAPIException as e: + if httplib.NOT_FOUND != e.http_status_code: + raise + + response['completed'] = True + response['reason'] = '' + + 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 disable " + "guest services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to disable %s " + "guest services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def query_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Query Host Services, return state of Guest services for a host. + """ + response = dict() + response['completed'] = False + response['result-data'] = 'enabled' + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_nova_compute(host_personality): + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + # Send Query request to Guest + future.work(guest.host_services_query, self._token, + host_uuid, host_name) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Guest query-host-services failed, operation " + "did not complete, host_uuid=%s, host_name=%s." + % (host_uuid, host_name)) + + else: + result_data = future.result.data + response['result-data'] = result_data['state'] + + 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 query " + "host services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to query %s " + "nova or neutron openstack services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + def host_services_rest_api_get_handler(self, request_dispatch): """ Host-Services Rest-API GET handler @@ -852,6 +1214,8 @@ class NFVIGuestAPI(nfvi.api.v1.NFVIGuestAPI): config.load(config_file) self._directory = openstack.get_directory( config, openstack.SERVICE_CATEGORY.PLATFORM) + self._openstack_directory = openstack.get_directory( + config, openstack.SERVICE_CATEGORY.OPENSTACK) self._rest_api_server = rest_api.rest_api_get_server( config.CONF['guest-rest-api']['host'], diff --git a/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_infrastructure_api.py b/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_infrastructure_api.py index 5c52a44e..e69dee0f 100755 --- a/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_infrastructure_api.py +++ b/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_infrastructure_api.py @@ -20,9 +20,6 @@ from nfv_plugins.nfvi_plugins.openstack import openstack from nfv_plugins.nfvi_plugins.openstack import sysinv from nfv_plugins.nfvi_plugins.openstack import fm from nfv_plugins.nfvi_plugins.openstack import mtc -from nfv_plugins.nfvi_plugins.openstack import nova -from nfv_plugins.nfvi_plugins.openstack import neutron -from nfv_plugins.nfvi_plugins.openstack import guest from nfv_plugins.nfvi_plugins.openstack.objects import OPENSTACK_SERVICE DLOG = debug.debug_get_logger('nfv_plugins.nfvi_plugins.infrastructure_api') @@ -122,7 +119,8 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): @staticmethod def _host_supports_kubernetes(personality): - # TODO(bwensley): This check will disappear once kubernetes is the default + # TODO(bwensley): This check will disappear once kubernetes is the + # default if os.path.isfile('/etc/kubernetes/admin.conf'): return ('compute' in personality or 'controller' in personality) else: @@ -167,15 +165,10 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): self._data_port_fault_handling_enabled = False self._host_listener = None - def _host_supports_neutron(self, personality): - return (('compute' in personality or 'controller' in personality) and - (self._openstack_directory.get_service_info( - OPENSTACK_SERVICE.NEUTRON) is not None)) - def _host_supports_nova_compute(self, personality): return (('compute' in personality) and - (self._openstack_directory.get_service_info( - OPENSTACK_SERVICE.NOVA) is not None)) + (self._openstack_directory.get_service_info( + OPENSTACK_SERVICE.NOVA) is not None)) def get_system_info(self, future, callback): """ @@ -787,239 +780,11 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): callback.send(response) callback.close() - def create_host_services(self, future, host_uuid, host_name, - host_personality, callback): - """ - Create Host Services, notifies Nova, Neutron and Guest to create their - services for the specified host - """ - response = dict() - response['completed'] = False - response['reason'] = '' - - try: - future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) - - if (self._host_supports_neutron(host_personality) or - self._host_supports_nova_compute(host_personality)): - response['reason'] = 'failed to get openstack token from ' \ - 'keystone' - if self._openstack_token is None or \ - self._openstack_token.is_expired(): - future.work(openstack.get_token, self._openstack_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s, host_name=%s." % (host_uuid, - host_name)) - return - - self._openstack_token = future.result.data - - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to get platform token from ' \ - 'keystone' - if self._platform_token is None or \ - self._platform_token.is_expired(): - future.work(openstack.get_token, self._platform_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s, host_name=%s." % (host_uuid, - host_name)) - return - - self._platform_token = future.result.data - - if self._host_supports_neutron(host_personality): - response['reason'] = 'failed to get neutron extensions' - if self._neutron_extensions is None: - future.work(neutron.get_extensions, self._openstack_token) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron get-extensions did not complete.") - return - - self._neutron_extensions = future.result.data - - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to create nova services' - - # Send the create request to Nova. - future.work(nova.create_host_services, self._openstack_token, - host_name) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Nova create-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - result_data = future.result.data['service'] - if not ('created' == result_data['status'] and - host_name == result_data['host'] and - 'nova-compute' == result_data['binary']): - DLOG.error("Nova create-host-services failed, invalid " - "response, host_uuid=%s, host_name=%s, response=%s." - % (host_uuid, host_name, response)) - return - - response['reason'] = 'failed to disable nova services' - - # Send the disable request to Nova. - future.work(nova.disable_host_services, self._openstack_token, - host_name) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Nova disable-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - result_data = future.result.data['service'] - - if not ('disabled' == result_data['status'] and - host_name == result_data['host'] and - 'nova-compute' == result_data['binary']): - DLOG.error("Nova disable-host-services failed, invalid " - "response, host_uuid=%s, host_name=%s, response=%s." - % (host_uuid, host_name, response)) - return - - if self._host_supports_neutron(host_personality): - if neutron.lookup_extension(neutron.EXTENSION_NAMES.HOST, - self._neutron_extensions): - - # Send Delete request to Neutron - response['reason'] = \ - 'failed to delete existing neutron services' - - future.work(neutron.delete_host_services_by_name, - self._openstack_token, - host_name, host_uuid, only_if_changed=True) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron delete-host-services-by-name failed, " - "operation did not complete, host_uuid=%s, " - "host_name=%s." % (host_uuid, host_name)) - return - - response['reason'] = 'failed to create neutron services' - - # Send the create request to Neutron. - future.work(neutron.create_host_services, - self._openstack_token, - host_name, host_uuid) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron create-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - result_data = future.result.data['host'] - if not ('down' == result_data['availability'] and - host_name == result_data['name'] and - host_uuid == result_data['id']): - DLOG.error("Neutron create-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - response['reason'] = 'failed to disable neutron services' - - # Send the disable request to Neutron - future.work(neutron.disable_host_services, - self._openstack_token, - host_uuid) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron disable-host-services failed, " - "operation did not complete, host_uuid=%s, " - "host_name=%s." % (host_uuid, host_name)) - return - - result_data = future.result.data['host'] - if not ('down' == result_data['availability'] and - host_name == result_data['name'] and - host_uuid == result_data['id']): - DLOG.error("Neutron disable-host-services failed, " - "operation did not complete, host_uuid=%s, " - "host_name=%s." % (host_uuid, host_name)) - return - - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to create guest services' - - try: - # Send the create request to Guest. - future.work(guest.host_services_create, - self._platform_token, - host_uuid, host_name) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Guest host-services-create failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - response['reason'] = 'failed to disable guest services' - - # Send the disable request to Guest - future.work(guest.host_services_disable, - self._platform_token, - host_uuid, host_name) - future.result = (yield) - - if not future.result.is_complete(): - # do not return since the disable will be retried by audit - DLOG.error("Guest host-services-disable failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - - except exceptions.OpenStackRestAPIException as e: - # Guest can send a 404 if it hasn't got the host inventory yet. - # Guest will catch up later, no need to fail here. - if httplib.NOT_FOUND != e.http_status_code: - raise - - response['completed'] = True - response['reason'] = '' - - except exceptions.OpenStackRestAPIException as e: - if httplib.UNAUTHORIZED == e.http_status_code: - response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED - if self._platform_token is not None: - self._platform_token.set_expired() - if self._openstack_token is not None: - self._openstack_token.set_expired() - - else: - DLOG.exception("Caught exception while trying to create " - "host services, error=%s." % e) - - except Exception as e: - DLOG.exception("Caught exception while trying to create %s nova " - "or neutron services, error=%s." % (host_name, e)) - - finally: - callback.send(response) - callback.close() - def delete_host_services(self, future, host_uuid, host_name, host_personality, callback): """ - Delete Host Services, notifies Nova, Neutron and Guest to delete their - services for the specified host + Delete Host Services, notifies kubernetes client to delete services + for a host. """ response = dict() response['completed'] = False @@ -1028,107 +793,6 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): try: future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) - if (self._host_supports_neutron(host_personality) or - self._host_supports_nova_compute(host_personality)): - response['reason'] = 'failed to get openstack token from ' \ - 'keystone' - if self._openstack_token is None or \ - self._openstack_token.is_expired(): - future.work(openstack.get_token, self._openstack_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s, host_name=%s." % (host_uuid, - host_name)) - return - - self._openstack_token = future.result.data - - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to get platform token from ' \ - 'keystone' - if self._platform_token is None or \ - self._platform_token.is_expired(): - future.work(openstack.get_token, self._platform_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s, host_name=%s." % (host_uuid, - host_name)) - return - - self._platform_token = future.result.data - - if self._host_supports_neutron(host_personality): - response['reason'] = 'failed to get neutron extensions' - - if self._neutron_extensions is None: - future.work(neutron.get_extensions, self._openstack_token) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron get-extensions did not complete.") - return - - self._neutron_extensions = future.result.data - - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to delete nova services' - - # Send the delete request to Nova. - future.work(nova.delete_host_services, self._openstack_token, - host_name) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Nova delete-host-services failed, operation did " - "not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - if self._host_supports_neutron(host_personality): - if neutron.lookup_extension(neutron.EXTENSION_NAMES.HOST, - self._neutron_extensions): - - response['reason'] = 'failed to delete neutron services' - - # Send the delete request to Neutron. - future.work(neutron.delete_host_services, - self._openstack_token, host_uuid) - try: - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron delete-host-services failed, " - "operation did not complete, host_uuid=%s, " - "host_name=%s." % (host_uuid, host_name)) - return - - except exceptions.OpenStackRestAPIException as e: - if httplib.NOT_FOUND != e.http_status_code: - raise - - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to delete guest services' - - # Send the delete request to Guest. - future.work(guest.host_services_delete, self._platform_token, - host_uuid) - try: - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Guest host-services-delete failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - except exceptions.OpenStackRestAPIException as e: - if httplib.NOT_FOUND != e.http_status_code: - raise - if self._host_supports_kubernetes(host_personality): response['reason'] = 'failed to delete kubernetes services' @@ -1145,21 +809,9 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): response['completed'] = True response['reason'] = '' - except exceptions.OpenStackRestAPIException as e: - if httplib.UNAUTHORIZED == e.http_status_code: - response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED - if self._openstack_token is not None: - self._openstack_token.set_expired() - if self._platform_token is not None: - self._platform_token.set_expired() - - else: - DLOG.exception("Caught exception while trying to delete " - "host services, error=%s." % e) - except Exception as e: DLOG.exception("Caught exception while trying to delete %s " - "nova or neutron openstack services, error=%s." + "kubernetes host services, error=%s." % (host_name, e)) finally: @@ -1169,8 +821,8 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): def enable_host_services(self, future, host_uuid, host_name, host_personality, callback): """ - Enable Host Services, notifies Nova, Neutron, Guest and Kubernetes to - enable their services for the specified host + Enable Host Services, notify kubernetes client to enable services + for a host. """ response = dict() response['completed'] = False @@ -1179,39 +831,6 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): try: future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) - if (self._host_supports_neutron(host_personality) or - self._host_supports_nova_compute(host_personality)): - response['reason'] = 'failed to get openstack token from ' \ - 'keystone' - if self._openstack_token is None or \ - self._openstack_token.is_expired(): - future.work(openstack.get_token, self._openstack_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s, host_name=%s." % (host_uuid, - host_name)) - return - - self._openstack_token = future.result.data - - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to get platform token from ' \ - 'keystone' - if self._platform_token is None or \ - self._platform_token.is_expired(): - future.work(openstack.get_token, self._platform_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s, host_name=%s." % (host_uuid, - host_name)) - return - - self._platform_token = future.result.data - if self._host_supports_kubernetes(host_personality): response['reason'] = 'failed to enable kubernetes services' @@ -1227,110 +846,24 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): % (host_uuid, host_name)) return - if self._host_supports_neutron(host_personality): - response['reason'] = 'failed to get neutron extensions' - - if self._neutron_extensions is None: - future.work(neutron.get_extensions, self._openstack_token) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron get-extensions did not complete.") - return - - self._neutron_extensions = future.result.data - - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to enable nova services' - - # Send the Enable request to Nova. - future.work(nova.enable_host_services, self._openstack_token, - host_name) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Nova enable-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - result_data = future.result.data['service'] - if not ('enabled' == result_data['status'] and - host_name == result_data['host'] and - 'nova-compute' == result_data['binary']): - DLOG.error("Nova enable-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - if self._host_supports_neutron(host_personality): - if neutron.lookup_extension(neutron.EXTENSION_NAMES.HOST, - self._neutron_extensions): - response['reason'] = 'failed to enable neutron services' - - # Send the Enable request to Neutron - future.work(neutron.enable_host_services, - self._openstack_token, host_uuid) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron enable-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - result_data = future.result.data['host'] - if not ('up' == result_data['availability'] and - host_name == result_data['name'] and - host_uuid == result_data['id']): - DLOG.error("Neutron enable-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to enable guest services' - - # Send the Enable request to Guest - future.work(guest.host_services_enable, self._platform_token, - host_uuid, host_name) - future.result = (yield) - - if not future.result.is_complete(): - # do not return since the enable will be retried by audit - DLOG.error("Guest host-services-enable failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - response['completed'] = True response['reason'] = '' - except exceptions.OpenStackRestAPIException as e: - if httplib.UNAUTHORIZED == e.http_status_code: - response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED - if self._openstack_token is not None: - self._openstack_token.set_expired() - if self._platform_token is not None: - self._platform_token.set_expired() - - else: - DLOG.exception("Caught exception while trying to enable " - "host services, error=%s." % e) - except Exception as e: DLOG.exception("Caught exception while trying to enable %s " - "host services, error=%s." + "kubernetes host services, error=%s." % (host_name, e)) finally: callback.send(response) callback.close() - def disable_host_services(self, future, host_uuid, host_name, - host_personality, callback): + def disable_host_services(self, future, host_uuid, + host_name, host_personality, + callback): """ - Disable Host Services, notifies Nova, Guest and Kubernetes to disable - their services for the specified host (as applicable) + Disable Host Services, notifies kubernetes client to disable services + for a host. """ response = dict() response['completed'] = False @@ -1339,85 +872,6 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): try: future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) - # The following only applies to compute hosts - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to get openstack token from ' \ - 'keystone' - if self._openstack_token is None or \ - self._openstack_token.is_expired(): - future.work(openstack.get_token, self._openstack_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s, host_name=%s." % (host_uuid, - host_name)) - return - - self._openstack_token = future.result.data - - response['reason'] = 'failed to get platform token from ' \ - 'keystone' - if self._platform_token is None or \ - self._platform_token.is_expired(): - future.work(openstack.get_token, self._platform_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s, host_name=%s." % (host_uuid, - host_name)) - return - - self._platform_token = future.result.data - - response['reason'] = 'failed to disable nova services' - - # Send the Disable request to Nova. - future.work(nova.disable_host_services, self._openstack_token, - host_name) - - try: - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Nova disable-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - result_data = future.result.data['service'] - if not ('disabled' == result_data['status'] and - host_name == result_data['host'] and - 'nova-compute' == result_data['binary']): - DLOG.error("Nova disable-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - except exceptions.OpenStackRestAPIException as e: - if httplib.NOT_FOUND != e.http_status_code: - raise - - response['reason'] = 'failed to disable guest services' - - # Send the Disable request to Guest. - future.work(guest.host_services_disable, self._platform_token, - host_uuid, host_name) - - try: - future.result = (yield) - - if not future.result.is_complete(): - # Do not return since the disable will be retried by audit - DLOG.error("Guest host-services-disable failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - - except exceptions.OpenStackRestAPIException as e: - if httplib.NOT_FOUND != e.http_status_code: - raise - if self._host_supports_kubernetes(host_personality): if True: # For now, we do not want to apply the NoExecute taint. @@ -1451,157 +905,9 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): response['completed'] = True response['reason'] = '' - except exceptions.OpenStackRestAPIException as e: - if httplib.UNAUTHORIZED == e.http_status_code: - response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED - if self._openstack_token is not None: - self._openstack_token.set_expired() - if self._platform_token is not None: - self._platform_token.set_expired() - - else: - DLOG.exception("Caught exception while trying to disable " - "host services, error=%s." % e) - except Exception as e: DLOG.exception("Caught exception while trying to disable %s " - "host services, error=%s." - % (host_name, e)) - - finally: - callback.send(response) - callback.close() - - def query_host_services(self, future, host_uuid, host_name, - host_personality, callback): - """ - Query Host Services, returns the aggregate administrative state - of the Nova and Neutron services for the specified host. - """ - response = dict() - response['completed'] = False - response['result-data'] = 'enabled' - response['reason'] = '' - - try: - future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) - - if (self._host_supports_neutron(host_personality) or - self._host_supports_nova_compute(host_personality)): - if self._openstack_token is None or \ - self._openstack_token.is_expired(): - future.work(openstack.get_token, self._openstack_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s, host_name=%s." % (host_uuid, - host_name)) - return - - self._openstack_token = future.result.data - - if self._platform_token is None or \ - self._platform_token.is_expired(): - future.work(openstack.get_token, self._platform_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s, host_name=%s." % (host_uuid, - host_name)) - return - - self._platform_token = future.result.data - - if self._host_supports_neutron(host_personality): - if self._neutron_extensions is None: - future.work(neutron.get_extensions, self._openstack_token) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron get-extensions did not complete.") - return - - self._neutron_extensions = future.result.data - - if self._host_supports_nova_compute(host_personality): - # Send Query request to Nova. - future.work(nova.query_host_services, self._openstack_token, - host_name) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Nova query-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - if future.result.data != 'enabled': - response['result-data'] = 'disabled' - response['completed'] = True - return - - if self._host_supports_neutron(host_personality): - if neutron.lookup_extension(neutron.EXTENSION_NAMES.HOST, - self._neutron_extensions): - # Send Query request to Neutron - future.work(neutron.query_host_services, - self._openstack_token, host_name) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron query-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - return - - if future.result.data is None or future.result.data != 'up': - response['result-data'] = 'disabled' - response['completed'] = True - return - - if self._host_supports_nova_compute(host_personality): - # Send Query request to Guest - future.work(guest.host_services_query, self._platform_token, - host_uuid, host_name) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Guest query-host-services failed, operation " - "did not complete, host_uuid=%s, host_name=%s." - % (host_uuid, host_name)) - - else: - result_data = future.result.data - if 'disabled' == result_data['state']: - future.work(guest.host_services_enable, - self._platform_token, - host_uuid, host_name) - future.result = (yield) - if not future.result.is_complete(): - DLOG.error("Guest host-services-enable failed," - " operation did not complete, host_uuid=%s," - "host_name=%s." - % (host_uuid, host_name)) - - 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._openstack_token is not None: - self._openstack_token.set_expired() - if self._platform_token is not None: - self._platform_token.set_expired() - - else: - DLOG.exception("Caught exception while trying to query " - "host services, error=%s." % e) - - except Exception as e: - DLOG.exception("Caught exception while trying to query %s " - "nova or neutron openstack services, error=%s." + "kubernetes host services, error=%s." % (host_name, e)) finally: @@ -2230,172 +1536,6 @@ class NFVIInfrastructureAPI(nfvi.api.v1.NFVIInfrastructureAPI): callback.send(response) callback.close() - def notify_host_enabled(self, future, host_uuid, host_name, - host_personality, callback): - """ - Notify host enabled - """ - response = dict() - response['completed'] = False - response['reason'] = '' - - try: - future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) - - # Only applies to compute hosts - if not self._host_supports_nova_compute(host_personality): - response['completed'] = True - response['reason'] = '' - return - - response['reason'] = 'failed to get token from keystone' - - if self._openstack_token is None or \ - self._openstack_token.is_expired(): - future.work(openstack.get_token, self._openstack_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s." % host_uuid) - return - - self._openstack_token = future.result.data - - response['reason'] = 'failed to notify nova that host is enabled' - - future.work(nova.notify_host_enabled, self._openstack_token, - host_name) - future.result = (yield) - - if not future.result.is_complete(): - return - - response['completed'] = True - response['reason'] = '' - - except exceptions.OpenStackRestAPIException as e: - if httplib.UNAUTHORIZED == e.http_status_code: - response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED - if self._openstack_token is not None: - self._openstack_token.set_expired() - - else: - DLOG.exception("Caught exception while trying to notify " - "host services enabled, error=%s." % e) - - except Exception as e: - DLOG.exception("Caught exception while trying to notify " - "host that a host is enabled, error=%s." % e) - - finally: - callback.send(response) - callback.close() - - def notify_host_disabled(self, future, host_uuid, host_name, - host_personality, callback): - """ - Notify host disabled - """ - response = dict() - response['completed'] = False - response['reason'] = '' - - try: - future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) - - if (self._host_supports_neutron(host_personality) or - self._host_supports_nova_compute(host_personality)): - response['reason'] = 'failed to get token from keystone' - if self._openstack_token is None or \ - self._openstack_token.is_expired(): - future.work(openstack.get_token, self._openstack_directory) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("OpenStack get-token did not complete, " - "host_uuid=%s." % host_uuid) - return - - self._openstack_token = future.result.data - - if self._host_supports_neutron(host_personality): - response['reason'] = 'failed to get neutron extensions' - - if self._neutron_extensions is None: - future.work(neutron.get_extensions, self._openstack_token) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron get-extensions did not complete.") - return - - self._neutron_extensions = future.result.data - - if self._host_supports_nova_compute(host_personality): - response['reason'] = 'failed to notify nova that host is disabled' - - future.work(nova.notify_host_disabled, self._openstack_token, - host_name) - - try: - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Nova notify-host-disabled.") - return - - except exceptions.OpenStackRestAPIException as e: - if httplib.NOT_FOUND != e.http_status_code: - raise - - if self._host_supports_neutron(host_personality): - if neutron.lookup_extension(neutron.EXTENSION_NAMES.HOST, - self._neutron_extensions): - response['reason'] = 'failed to disable neutron services' - - # Send the Disable request to Neutron - future.work(neutron.disable_host_services, - self._openstack_token, - host_uuid) - future.result = (yield) - - if not future.result.is_complete(): - DLOG.error("Neutron disable-host-services failed, " - "operation did not complete, host_uuid=%s, " - "host_name=%s." % (host_uuid, host_name)) - return - - result_data = future.result.data['host'] - if not ('down' == result_data['availability'] and - host_name == result_data['name'] and - host_uuid == result_data['id']): - DLOG.error("Neutron disable-host-services failed, " - "operation did not complete, host_uuid=%s, " - "host_name=%s." % (host_uuid, host_name)) - return - - response['completed'] = True - response['reason'] = '' - - except exceptions.OpenStackRestAPIException as e: - if httplib.UNAUTHORIZED == e.http_status_code: - response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED - if self._openstack_token is not None: - self._openstack_token.set_expired() - - else: - DLOG.exception("Caught exception while trying to notify " - "host services disabled, error=%s." % e) - - except Exception as e: - DLOG.exception("Caught exception while trying to notify " - "host that a host is disabled, error=%s." % e) - - finally: - callback.send(response) - callback.close() - def notify_host_failed(self, future, host_uuid, host_name, host_personality, callback): """ diff --git a/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_network_api.py b/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_network_api.py index 5452ce09..45e7dcb5 100755 --- a/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_network_api.py +++ b/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_network_api.py @@ -67,6 +67,7 @@ class NFVINetworkAPI(nfvi.api.v1.NFVINetworkAPI): super(NFVINetworkAPI, self).__init__() self._token = None self._directory = None + self._neutron_extensions = None @property def name(self): @@ -84,6 +85,11 @@ class NFVINetworkAPI(nfvi.api.v1.NFVINetworkAPI): def signature(self): return self._signature + def _host_supports_neutron(self, personality): + return (('compute' in personality or 'controller' in personality) and + (self._directory.get_service_info( + OPENSTACK_SERVICE.NEUTRON) is not None)) + def get_networks(self, future, paging, callback): """ Get a list of networks @@ -754,6 +760,465 @@ class NFVINetworkAPI(nfvi.api.v1.NFVINetworkAPI): callback.send(response) callback.close() + def create_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Create Host Services, notify neutron to create services for a host. + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_neutron(host_personality): + response['reason'] = 'failed to get openstack token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to get neutron extensions' + if self._neutron_extensions is None: + future.work(neutron.get_extensions, self._token) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron get-extensions did not complete.") + return + + self._neutron_extensions = future.result.data + + if neutron.lookup_extension(neutron.EXTENSION_NAMES.HOST, + self._neutron_extensions): + + # Send Delete request to Neutron + response['reason'] = \ + 'failed to delete existing neutron services' + + future.work(neutron.delete_host_services_by_name, + self._token, + host_name, host_uuid, only_if_changed=True) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron delete-host-services-by-name " + "failed, operation did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + response['reason'] = 'failed to create neutron services' + + # Send the create request to Neutron. + future.work(neutron.create_host_services, + self._token, + host_name, host_uuid) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron create-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." + % (host_uuid, host_name)) + return + + result_data = future.result.data['host'] + if not ('down' == result_data['availability'] and + host_name == result_data['name'] and + host_uuid == result_data['id']): + DLOG.error("Neutron create-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." + % (host_uuid, host_name)) + return + + response['reason'] = 'failed to disable neutron services' + + # Send the disable request to Neutron + future.work(neutron.disable_host_services, + self._token, + host_uuid) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron disable-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." % (host_uuid, host_name)) + return + + result_data = future.result.data['host'] + if not ('down' == result_data['availability'] and + host_name == result_data['name'] and + host_uuid == result_data['id']): + DLOG.error("Neutron disable-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." % (host_uuid, host_name)) + return + + response['completed'] = True + response['reason'] = '' + + 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 create " + "neutron services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to create %s " + "neutron services, error=%s." % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def delete_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Delete Host Services, notify neutron to delete services for a host. + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_neutron(host_personality): + response['reason'] = 'failed to get openstack token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to get neutron extensions' + + if self._neutron_extensions is None: + future.work(neutron.get_extensions, self._token) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron get-extensions did not complete.") + return + + self._neutron_extensions = future.result.data + + if neutron.lookup_extension(neutron.EXTENSION_NAMES.HOST, + self._neutron_extensions): + + response['reason'] = 'failed to delete neutron services' + + # Send the delete request to Neutron. + future.work(neutron.delete_host_services, + self._token, host_uuid) + try: + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron delete-host-services failed, " + "operation did not complete, " + "host_uuid=%s, host_name=%s." + % (host_uuid, host_name)) + return + + except exceptions.OpenStackRestAPIException as e: + if httplib.NOT_FOUND != e.http_status_code: + raise + + response['completed'] = True + response['reason'] = '' + + 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 delete " + "neutron services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to delete %s " + "neutron openstack services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def enable_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Enable Host Services, notify neutron to enable services for a host. + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_neutron(host_personality): + response['reason'] = 'failed to get openstack token from ' \ + 'keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + response['reason'] = 'failed to get neutron extensions' + + if self._neutron_extensions is None: + future.work(neutron.get_extensions, self._token) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron get-extensions did not complete.") + return + + self._neutron_extensions = future.result.data + + if neutron.lookup_extension(neutron.EXTENSION_NAMES.HOST, + self._neutron_extensions): + response['reason'] = 'failed to enable neutron services' + + # Send the Enable request to Neutron + future.work(neutron.enable_host_services, + self._token, host_uuid) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron enable-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." + % (host_uuid, host_name)) + return + + result_data = future.result.data['host'] + if not ('up' == result_data['availability'] and + host_name == result_data['name'] and + host_uuid == result_data['id']): + DLOG.error("Neutron enable-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." % (host_uuid, host_name)) + return + + response['completed'] = True + response['reason'] = '' + + 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 enable " + "neutron services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to enable %s " + "neutron services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def query_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Query Neutron Services for a host. + """ + response = dict() + response['completed'] = False + response['result-data'] = 'enabled' + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_neutron(host_personality): + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s, host_name=%s." % (host_uuid, + host_name)) + return + + self._token = future.result.data + + if self._neutron_extensions is None: + future.work(neutron.get_extensions, self._token) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron get-extensions did not complete.") + return + + self._neutron_extensions = future.result.data + + if neutron.lookup_extension(neutron.EXTENSION_NAMES.HOST, + self._neutron_extensions): + # Send Query request to Neutron + future.work(neutron.query_host_services, + self._token, host_name) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron query-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." % (host_uuid, host_name)) + return + + if future.result.data is None or \ + future.result.data != 'up': + response['result-data'] = 'disabled' + response['completed'] = True + return + + 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 query " + "neutron host services, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to query %s " + "neutron openstack services, error=%s." + % (host_name, e)) + + finally: + callback.send(response) + callback.close() + + def notify_host_disabled(self, future, host_uuid, host_name, + host_personality, callback): + """ + Notify host disabled + """ + response = dict() + response['completed'] = False + response['reason'] = '' + + try: + future.set_timeouts(config.CONF.get('nfvi-timeouts', None)) + + if self._host_supports_neutron(host_personality): + response['reason'] = 'failed to get token from keystone' + 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(): + DLOG.error("OpenStack get-token did not complete, " + "host_uuid=%s." % host_uuid) + return + + self._token = future.result.data + + response['reason'] = 'failed to get neutron extensions' + + if self._neutron_extensions is None: + future.work(neutron.get_extensions, self._token) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron get-extensions did not complete.") + return + + self._neutron_extensions = future.result.data + + if neutron.lookup_extension(neutron.EXTENSION_NAMES.HOST, + self._neutron_extensions): + response['reason'] = 'failed to disable neutron services' + + # Send the Disable request to Neutron + future.work(neutron.disable_host_services, + self._token, + host_uuid) + future.result = (yield) + + if not future.result.is_complete(): + DLOG.error("Neutron disable-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." % (host_uuid, host_name)) + return + + result_data = future.result.data['host'] + if not ('down' == result_data['availability'] and + host_name == result_data['name'] and + host_uuid == result_data['id']): + DLOG.error("Neutron disable-host-services failed, " + "operation did not complete, host_uuid=%s, " + "host_name=%s." % (host_uuid, host_name)) + return + + response['completed'] = True + response['reason'] = '' + + 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 notify " + "neutron host services disabled, error=%s." % e) + + except Exception as e: + DLOG.exception("Caught exception while trying to notify " + "neutron host services disabled, error=%s." % e) + + finally: + callback.send(response) + callback.close() + def initialize(self, config_file): """ Initialize the plugin diff --git a/nfv/nfv-vim/nfv_vim/directors/_host_director.py b/nfv/nfv-vim/nfv_vim/directors/_host_director.py index 688a691b..a4a02039 100755 --- a/nfv/nfv-vim/nfv_vim/directors/_host_director.py +++ b/nfv/nfv-vim/nfv_vim/directors/_host_director.py @@ -68,18 +68,19 @@ class HostDirector(object): nfvi.nfvi_lock_host(host_uuid, host_name, self._nfvi_lock_host_callback()) @coroutine - def _nfvi_disable_host_services_callback(self): + def _nfvi_disable_host_services_callback(self, service): """ NFVI Disable Host Services Callback """ from nfv_vim import directors response = (yield) - DLOG.verbose("NFVI Disable Host Services callback response=%s." % - response) + DLOG.verbose("NFVI Disable Host %s Services callback " + "response=%s." % (service, response)) if not response['completed']: - DLOG.info("Disable of host services on host %s failed, reason=%s." - % (response['host_name'], response['reason'])) + DLOG.info("Disable of %s services on host %s failed" + ", reason=%s." + % (service, response['host_name'], response['reason'])) host_table = tables.tables_get_host_table() host = host_table.get(response['host_name'], None) @@ -101,27 +102,41 @@ class HostDirector(object): sw_mgmt_director.disable_host_services_failed(host) def _nfvi_disable_host_services(self, host_uuid, host_name, - host_personality): + host_personality, service): """ NFVI Disable Host Services """ - nfvi.nfvi_disable_host_services( - host_uuid, host_name, host_personality, - self._nfvi_disable_host_services_callback()) + if service == objects.HOST_SERVICES.COMPUTE: + nfvi.nfvi_disable_compute_host_services( + host_uuid, host_name, host_personality, + self._nfvi_disable_host_services_callback( + objects.HOST_SERVICES.COMPUTE)) + elif service == objects.HOST_SERVICES.GUEST: + nfvi.nfvi_disable_guest_host_services( + host_uuid, host_name, host_personality, + self._nfvi_disable_host_services_callback( + objects.HOST_SERVICES.GUEST)) + elif service == objects.HOST_SERVICES.CONTAINER: + nfvi.nfvi_disable_container_host_services( + host_uuid, host_name, host_personality, + self._nfvi_disable_host_services_callback( + objects.HOST_SERVICES.CONTAINER)) + else: + DLOG.error("Trying to disable unknown service: %s" % service) @coroutine - def _nfvi_enable_host_services_callback(self): + def _nfvi_enable_host_services_callback(self, service): """ NFVI Enable Host Services Callback """ from nfv_vim import directors response = (yield) - DLOG.verbose("NFVI Enable Host Services callback response=%s." % - response) + DLOG.verbose("NFVI Enable Host %s Services callback " + "response=%s." % (service, response)) if not response['completed']: - DLOG.info("Enable of host services on host %s failed, reason=%s." - % (response['host_name'], response['reason'])) + DLOG.info("Enable of %s services on host %s failed, reason=%s." + % (service, response['host_name'], response['reason'])) host_table = tables.tables_get_host_table() host = host_table.get(response['host_name'], None) @@ -136,20 +151,40 @@ class HostDirector(object): if OPERATION_TYPE.ENABLE_HOST_SERVICES != \ self._host_operation.operation_type: DLOG.verbose("Unexpected host %s operation %s, ignoring." - % (host.name, self._host_operation.operation_type)) + % (host.name, + self._host_operation.operation_type)) return sw_mgmt_director = directors.get_sw_mgmt_director() sw_mgmt_director.enable_host_services_failed(host) def _nfvi_enable_host_services(self, host_uuid, host_name, - host_personality): + host_personality, service): """ NFVI Enable Host Services """ - nfvi.nfvi_enable_host_services( - host_uuid, host_name, host_personality, - self._nfvi_enable_host_services_callback()) + if service == objects.HOST_SERVICES.COMPUTE: + nfvi.nfvi_enable_compute_host_services( + host_uuid, host_name, host_personality, + self._nfvi_enable_host_services_callback( + objects.HOST_SERVICES.COMPUTE)) + elif service == objects.HOST_SERVICES.GUEST: + nfvi.nfvi_enable_guest_host_services( + host_uuid, host_name, host_personality, + self._nfvi_enable_host_services_callback( + objects.HOST_SERVICES.GUEST)) + elif service == objects.HOST_SERVICES.CONTAINER: + nfvi.nfvi_enable_container_host_services( + host_uuid, host_name, host_personality, + self._nfvi_enable_host_services_callback( + objects.HOST_SERVICES.CONTAINER)) + elif service == objects.HOST_SERVICES.NETWORK: + nfvi.nfvi_enable_network_host_services( + host_uuid, host_name, host_personality, + self._nfvi_enable_host_services_callback( + objects.HOST_SERVICES.NETWORK)) + else: + DLOG.error("Trying to enable unknown service: %s" % service) @coroutine def _nfvi_unlock_host_callback(self): @@ -630,11 +665,12 @@ class HostDirector(object): return host_operation - def disable_host_services(self, host_names): + def disable_host_services(self, host_names, service): """ - Disable host services on a list of hosts + Disable a host service on a list of hosts """ - DLOG.info("Disable host services: %s" % host_names) + DLOG.info("Disable host services: %s service: %s" % + (host_names, service)) host_operation = Operation(OPERATION_TYPE.DISABLE_HOST_SERVICES) @@ -646,6 +682,7 @@ class HostDirector(object): self._host_operation = None host_table = tables.tables_get_host_table() + host_list = list() for host_name in host_names: host = host_table.get(host_name, None) if host is None: @@ -655,23 +692,28 @@ class HostDirector(object): return host_operation host.host_services_locked = True - if objects.HOST_SERVICE_STATE.DISABLED == host.host_service_state: + if (objects.HOST_SERVICE_STATE.DISABLED == + host.host_service_state(service)): host_operation.add_host(host.name, OPERATION_STATE.COMPLETED) else: host_operation.add_host(host.name, OPERATION_STATE.INPROGRESS) - self._nfvi_disable_host_services(host.uuid, host.name, - host.personality) + host_list.append(host) + + for host in host_list: + self._nfvi_disable_host_services( + host.uuid, host.name, host.personality, service) if host_operation.is_inprogress(): self._host_operation = host_operation return host_operation - def enable_host_services(self, host_names): + def enable_host_services(self, host_names, service): """ - Enable host services on a list of hosts + Enable a host service on a list of hosts """ - DLOG.info("Enable host services: %s" % host_names) + DLOG.info("Enable host services: %s service: %s" % + (host_names, service)) host_operation = Operation(OPERATION_TYPE.ENABLE_HOST_SERVICES) @@ -683,6 +725,7 @@ class HostDirector(object): self._host_operation = None host_table = tables.tables_get_host_table() + host_list = list() for host_name in host_names: host = host_table.get(host_name, None) if host is None: @@ -692,12 +735,16 @@ class HostDirector(object): return host_operation host.host_services_locked = False - if objects.HOST_SERVICE_STATE.ENABLED == host.host_service_state: + if (objects.HOST_SERVICE_STATE.ENABLED == + host.host_service_state(service)): host_operation.add_host(host.name, OPERATION_STATE.COMPLETED) else: host_operation.add_host(host.name, OPERATION_STATE.INPROGRESS) - self._nfvi_enable_host_services(host.uuid, host.name, - host.personality) + host_list.append(host) + + for host in host_list: + self._nfvi_enable_host_services( + host.uuid, host.name, host.personality, service) if host_operation.is_inprogress(): self._host_operation = host_operation diff --git a/nfv/nfv-vim/nfv_vim/host_fsm/_host_state_enabled.py b/nfv/nfv-vim/nfv_vim/host_fsm/_host_state_enabled.py index ee4c7da0..a9672d70 100755 --- a/nfv/nfv-vim/nfv_vim/host_fsm/_host_state_enabled.py +++ b/nfv/nfv-vim/nfv_vim/host_fsm/_host_state_enabled.py @@ -53,7 +53,8 @@ class EnabledState(state_machine.State): return HOST_STATE.DISABLING elif HOST_EVENT.TASK_COMPLETED == event: - if objects.HOST_SERVICE_STATE.ENABLED != host.host_service_state: + if objects.HOST_SERVICE_STATE.ENABLED != \ + host.host_service_state_aggregate(): if not host.host_services_locked: DLOG.info("Host services are not enabled on %s. " "Disabling host." % host.name) diff --git a/nfv/nfv-vim/nfv_vim/host_fsm/_host_task_work.py b/nfv/nfv-vim/nfv_vim/host_fsm/_host_task_work.py index ec42b174..445d13f8 100755 --- a/nfv/nfv-vim/nfv_vim/host_fsm/_host_task_work.py +++ b/nfv/nfv-vim/nfv_vim/host_fsm/_host_task_work.py @@ -90,11 +90,12 @@ class NotifyHostEnabledTaskWork(state_machine.StateTaskWork): """ Notify Host Enabled Task Work """ - def __init__(self, task, host, force_pass=False): + def __init__(self, task, host, service, force_pass=False): super(NotifyHostEnabledTaskWork, self).__init__( - 'notify-host-enabled_%s' % host.name, task, + 'notify-host-enabled_%s_%s' % (host.name, service), task, force_pass=force_pass, timeout_in_secs=120) self._host_reference = weakref.ref(host) + self._service = service @property def _host(self): @@ -133,10 +134,22 @@ class NotifyHostEnabledTaskWork(state_machine.StateTaskWork): """ Run notify host enabled """ - DLOG.verbose("Notify-Host-Enabled for %s." % self._host.name) - nfvi.nfvi_notify_host_enabled(self._host.uuid, self._host.name, - self._host.personality, - self._callback()) + from nfv_vim import objects + + DLOG.verbose("Notify-Host-Enabled for %s %s." % (self._host.name, + self._service)) + + if self._service == objects.HOST_SERVICES.COMPUTE: + nfvi.nfvi_notify_compute_host_enabled( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + else: + reason = ("Trying to notify host enabled for unknown " + "host service %s" % self._service) + DLOG.error(reason) + self._host.update_failure_reason(reason) + return state_machine.STATE_TASK_WORK_RESULT.FAILED, reason + return state_machine.STATE_TASK_WORK_RESULT.WAIT, empty_reason @@ -144,11 +157,12 @@ class NotifyHostDisabledTaskWork(state_machine.StateTaskWork): """ Notify Host Disabled Task Work """ - def __init__(self, task, host, force_pass=False): + def __init__(self, task, host, service, force_pass=False): super(NotifyHostDisabledTaskWork, self).__init__( - 'notify-host-disabled_%s' % host.name, task, + 'notify-host-disabled_%s_%s' % (host.name, service), task, force_pass=force_pass, timeout_in_secs=120) self._host_reference = weakref.ref(host) + self._service = service @property def _host(self): @@ -187,10 +201,26 @@ class NotifyHostDisabledTaskWork(state_machine.StateTaskWork): """ Run notify host disabled """ - DLOG.verbose("Notify-Host-Disabled for %s." % self._host.name) - nfvi.nfvi_notify_host_disabled(self._host.uuid, self._host.name, - self._host.personality, - self._callback()) + from nfv_vim import objects + + DLOG.verbose("Notify-Host-Disabled for %s %s." % (self._host.name, + self._service)) + + if self._service == objects.HOST_SERVICES.COMPUTE: + nfvi.nfvi_notify_compute_host_disabled( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.NETWORK: + nfvi.nfvi_notify_network_host_disabled( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + else: + reason = ("Trying to notify host disabled for unknown " + "host service %s" % self._service) + DLOG.error(reason) + self._host.update_failure_reason(reason) + return state_machine.STATE_TASK_WORK_RESULT.FAILED, reason + return state_machine.STATE_TASK_WORK_RESULT.WAIT, empty_reason @@ -478,11 +508,12 @@ class CreateHostServicesTaskWork(state_machine.StateTaskWork): """ Create Host Services Task Work """ - def __init__(self, task, host, force_pass=False): + def __init__(self, task, host, service, force_pass=False): super(CreateHostServicesTaskWork, self).__init__( - 'create-host-services_%s' % host.name, task, + 'create-host-services_%s_%s' % (host.name, service), task, force_pass=force_pass, timeout_in_secs=120) self._host_reference = weakref.ref(host) + self._service = service @property def _host(self): @@ -501,8 +532,10 @@ class CreateHostServicesTaskWork(state_machine.StateTaskWork): response = (yield) if self.task is not None: - DLOG.verbose("Create-Host-Services callback for %s, response=%s." - % (self._host.name, response)) + DLOG.verbose("Create-Host-Services callback for %s %s, " + "response=%s." % (self._host.name, + self._service, + response)) if response['completed']: self.task.task_work_complete( state_machine.STATE_TASK_WORK_RESULT.SUCCESS, @@ -516,6 +549,7 @@ class CreateHostServicesTaskWork(state_machine.StateTaskWork): empty_reason) else: self._host.host_services_update( + self._service, objects.HOST_SERVICE_STATE.FAILED, response.get('reason', None)) @@ -527,10 +561,29 @@ class CreateHostServicesTaskWork(state_machine.StateTaskWork): """ Run create host services """ - DLOG.verbose("Create-Host-Services for %s." % self._host.name) - nfvi.nfvi_create_host_services(self._host.uuid, self._host.name, - self._host.personality, - self._callback()) + from nfv_vim import objects + DLOG.verbose("Create-Host-Services for %s %s." + % (self._host.name, self._service)) + + if self._service == objects.HOST_SERVICES.COMPUTE: + nfvi.nfvi_create_compute_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.GUEST: + nfvi.nfvi_create_guest_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.NETWORK: + nfvi.nfvi_create_network_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + else: + reason = ("Trying to create unknown " + "host service %s" % self._service) + DLOG.error(reason) + self._host.update_failure_reason(reason) + return state_machine.STATE_TASK_WORK_RESULT.FAILED, reason + return state_machine.STATE_TASK_WORK_RESULT.WAIT, empty_reason @@ -538,11 +591,12 @@ class DeleteHostServicesTaskWork(state_machine.StateTaskWork): """ Delete Host Services Task Work """ - def __init__(self, task, host, force_pass=False): + def __init__(self, task, host, service, force_pass=False): super(DeleteHostServicesTaskWork, self).__init__( - 'delete-host-services_%s' % host.name, task, + 'delete-host-services_%s_%s' % (host.name, service), task, force_pass=force_pass, timeout_in_secs=120) self._host_reference = weakref.ref(host) + self._service = service @property def _host(self): @@ -561,8 +615,9 @@ class DeleteHostServicesTaskWork(state_machine.StateTaskWork): response = (yield) if self.task is not None: - DLOG.verbose("Delete-Host-Services callback for %s, response=%s." - % (self._host.name, response)) + DLOG.verbose("Delete-Host-Services callback for %s %s, " + "response=%s." + % (self._host.name, self._service, response)) if response['completed']: self.task.task_work_complete( state_machine.STATE_TASK_WORK_RESULT.SUCCESS, @@ -580,6 +635,7 @@ class DeleteHostServicesTaskWork(state_machine.StateTaskWork): self._host.update_failure_reason(reason) self._host.host_services_update( + self._service, objects.HOST_SERVICE_STATE.FAILED, reason) self.task.task_work_complete( @@ -590,6 +646,7 @@ class DeleteHostServicesTaskWork(state_machine.StateTaskWork): Run delete host services """ from nfv_vim import directors + from nfv_vim import objects DLOG.verbose("Delete-Host-Services for %s." % self._host.name) @@ -601,9 +658,29 @@ class DeleteHostServicesTaskWork(state_machine.StateTaskWork): self._host.update_failure_reason(reason) return state_machine.STATE_TASK_WORK_RESULT.FAILED, reason - nfvi.nfvi_delete_host_services(self._host.uuid, self._host.name, - self._host.personality, - self._callback()) + if self._service == objects.HOST_SERVICES.COMPUTE: + nfvi.nfvi_delete_compute_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.GUEST: + nfvi.nfvi_delete_guest_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.NETWORK: + nfvi.nfvi_delete_network_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.CONTAINER: + nfvi.nfvi_delete_container_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + else: + reason = ("Trying to delete unknown " + "host service %s" % self._service) + DLOG.error(reason) + self._host.update_failure_reason(reason) + return state_machine.STATE_TASK_WORK_RESULT.FAILED, reason + return state_machine.STATE_TASK_WORK_RESULT.WAIT, empty_reason @@ -611,11 +688,12 @@ class EnableHostServicesTaskWork(state_machine.StateTaskWork): """ Enable Host Services Task Work """ - def __init__(self, task, host, force_pass=False): + def __init__(self, task, host, service, force_pass=False): super(EnableHostServicesTaskWork, self).__init__( - 'enable-host-services_%s' % host.name, task, + 'enable-host-services_%s_%s' % (host.name, service), task, force_pass=force_pass, timeout_in_secs=120) self._host_reference = weakref.ref(host) + self._service = service @property def _host(self): @@ -634,8 +712,9 @@ class EnableHostServicesTaskWork(state_machine.StateTaskWork): response = (yield) if self.task is not None: - DLOG.verbose("Enable-Host-Services callback for %s, response=%s." - % (self._host.name, response)) + DLOG.verbose("Enable-Host-Services callback for service: %s %s %s, " + "response=%s." % (self._service, self._host.name, + self._service, response)) if response['completed']: self.task.task_work_complete( state_machine.STATE_TASK_WORK_RESULT.SUCCESS, @@ -649,6 +728,7 @@ class EnableHostServicesTaskWork(state_machine.StateTaskWork): empty_reason) else: self._host.host_services_update( + self._service, objects.HOST_SERVICE_STATE.FAILED, response.get('reason', None)) @@ -660,11 +740,35 @@ class EnableHostServicesTaskWork(state_machine.StateTaskWork): """ Run enable host services """ - DLOG.verbose("Enable-Host-Services for %s." % self._host.name) + from nfv_vim import objects + + DLOG.verbose("Enable-Host-Services for %s for service %s." + % (self._host.name, self._service)) self._host.host_services_locked = False - nfvi.nfvi_enable_host_services(self._host.uuid, self._host.name, - self._host.personality, - self._callback()) + + if self._service == objects.HOST_SERVICES.COMPUTE: + nfvi.nfvi_enable_compute_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.GUEST: + nfvi.nfvi_enable_guest_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.NETWORK: + nfvi.nfvi_enable_network_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.CONTAINER: + nfvi.nfvi_enable_container_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + else: + reason = ("Trying to enable unknown " + "host service %s" % self._service) + DLOG.error(reason) + self._host.update_failure_reason(reason) + return state_machine.STATE_TASK_WORK_RESULT.FAILED, reason + return state_machine.STATE_TASK_WORK_RESULT.WAIT, empty_reason @@ -672,11 +776,12 @@ class DisableHostServicesTaskWork(state_machine.StateTaskWork): """ Disable Host Services Task Work """ - def __init__(self, task, host, force_pass=False): + def __init__(self, task, host, service, force_pass=False): super(DisableHostServicesTaskWork, self).__init__( - 'disable-host-services_%s' % host.name, task, + 'disable-host-services_%s_%s' % (host.name, service), task, force_pass=force_pass, timeout_in_secs=120) self._host_reference = weakref.ref(host) + self._service = service @property def _host(self): @@ -695,8 +800,9 @@ class DisableHostServicesTaskWork(state_machine.StateTaskWork): response = (yield) if self.task is not None: - DLOG.verbose("Disable-Host-Services callback for %s, response=%s." - % (self._host.name, response)) + DLOG.verbose("Disable-Host-Services callback for service: %s, %s %s, " + "response=%s." % (self._service, self._host.name, + self._service, response)) if response['completed']: self.task.task_work_complete( state_machine.STATE_TASK_WORK_RESULT.SUCCESS, @@ -710,6 +816,7 @@ class DisableHostServicesTaskWork(state_machine.StateTaskWork): empty_reason) else: self._host.host_services_update( + self._service, objects.HOST_SERVICE_STATE.FAILED, response.get('reason', None)) @@ -721,10 +828,30 @@ class DisableHostServicesTaskWork(state_machine.StateTaskWork): """ Run disable host services """ - DLOG.verbose("Disable-Host-Services for %s." % self._host.name) - nfvi.nfvi_disable_host_services(self._host.uuid, self._host.name, - self._host.personality, - self._callback()) + from nfv_vim import objects + + DLOG.verbose("Disable-Host-Services for %s service %s." + % (self._host.name, self._service)) + + if self._service == objects.HOST_SERVICES.COMPUTE: + nfvi.nfvi_disable_compute_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.GUEST: + nfvi.nfvi_disable_guest_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.CONTAINER: + nfvi.nfvi_disable_container_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + else: + reason = ("Trying to disable unknown " + "host service %s" % self._service) + DLOG.error(reason) + self._host.update_failure_reason(reason) + return state_machine.STATE_TASK_WORK_RESULT.FAILED, reason + return state_machine.STATE_TASK_WORK_RESULT.WAIT, empty_reason @@ -769,7 +896,7 @@ class NotifyHostServicesEnabledTaskWork(state_machine.StateTaskWork): state_machine.STATE_TASK_WORK_RESULT.SUCCESS, empty_reason) else: - self._host.host_services_update( + self._host.host_services_update_all( objects.HOST_SERVICE_STATE.FAILED, response.get('reason', None)) @@ -829,7 +956,7 @@ class NotifyHostServicesDisabledTaskWork(state_machine.StateTaskWork): state_machine.STATE_TASK_WORK_RESULT.SUCCESS, empty_reason) else: - self._host.host_services_update( + self._host.host_services_update_all( objects.HOST_SERVICE_STATE.FAILED, response.get('reason', None)) @@ -842,6 +969,7 @@ class NotifyHostServicesDisabledTaskWork(state_machine.StateTaskWork): Run notify host services disabled """ DLOG.verbose("Notify-Host-Services-Disabled for %s." % self._host.name) + nfvi.nfvi_notify_host_services_disabled(self._host.uuid, self._host.name, self._callback()) @@ -906,11 +1034,12 @@ class AuditHostServicesTaskWork(state_machine.StateTaskWork): """ Audit Host Services Task Work """ - def __init__(self, task, host, force_pass=False): + def __init__(self, task, host, service, force_pass=False): super(AuditHostServicesTaskWork, self).__init__( - 'audit-host-services_%s' % host.name, task, + 'audit-host-services_%s_%s' % (host.name, service), task, force_pass=force_pass, timeout_in_secs=120) self._host_reference = weakref.ref(host) + self._service = service @property def _host(self): @@ -925,22 +1054,24 @@ class AuditHostServicesTaskWork(state_machine.StateTaskWork): """ Callback for audit host services """ - from nfv_vim import directors from nfv_vim import objects + DLOG.verbose("query callback for service: %s" % self._service) response = (yield) if self.task is not None: + DLOG.verbose("query callback for service %s %s" + % (self._service, response['result-data'])) + if response['completed']: if 'enabled' == response['result-data']: self._host.host_services_update( + self._service, objects.HOST_SERVICE_STATE.ENABLED) else: self._host.host_services_update( + self._service, objects.HOST_SERVICE_STATE.DISABLED) - host_director = directors.get_host_director() - host_director.host_audit(self._host) - self.task.task_work_complete( state_machine.STATE_TASK_WORK_RESULT.SUCCESS, empty_reason) @@ -948,24 +1079,26 @@ class AuditHostServicesTaskWork(state_machine.StateTaskWork): if self.force_pass: if self._host.is_enabled(): self._host.host_services_update( + self._service, objects.HOST_SERVICE_STATE.ENABLED) else: self._host.host_services_update( + self._service, objects.HOST_SERVICE_STATE.DISABLED) - DLOG.info("Audit-Host-Services callback for %s, failed, " - "force-passing, defaulting state to %s." - % (self._host.name, self._host.host_service_state)) - - host_director = directors.get_host_director() - host_director.host_audit(self._host) + DLOG.info("Audit-Host-Services callback for %s, " + "failed, force-passing, " + "defaulting state to %s." + % (self._host.name, + self._host.host_service_state(self._service))) self.task.task_work_complete( state_machine.STATE_TASK_WORK_RESULT.SUCCESS, empty_reason) else: - DLOG.error("Audit-Host-Services callback for %s, " - "response=%s." % (self._host.name, response)) + DLOG.error("Audit-Host-Services callback for %s, %s" + "response=%s." % (self._host.name, + self._service, response)) self.task.task_work_complete( state_machine.STATE_TASK_WORK_RESULT.FAILED, response['reason']) @@ -974,11 +1107,63 @@ class AuditHostServicesTaskWork(state_machine.StateTaskWork): """ Run audit host services """ - nfvi.nfvi_query_host_services(self._host.uuid, self._host.name, - self._host.personality, self._callback()) + from nfv_vim import objects + + DLOG.verbose("Query-Host-Services for %s %s" % (self._host.name, + self._service)) + + if self._service == objects.HOST_SERVICES.COMPUTE: + nfvi.nfvi_query_compute_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.GUEST: + nfvi.nfvi_query_guest_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + elif self._service == objects.HOST_SERVICES.NETWORK: + nfvi.nfvi_query_network_host_services( + self._host.uuid, self._host.name, self._host.personality, + self._callback()) + else: + reason = ("Trying to query unknown " + "host service %s" % self._service) + DLOG.error(reason) + self._host.update_failure_reason(reason) + return state_machine.STATE_TASK_WORK_RESULT.FAILED, reason + return state_machine.STATE_TASK_WORK_RESULT.WAIT, empty_reason +class AuditHostServicesCompleteTaskWork(state_machine.StateTaskWork): + """ + Audit Host Services Complete Task Work + """ + def __init__(self, task, host, force_pass=False): + super(AuditHostServicesCompleteTaskWork, self).__init__( + 'audit-host-services_%s' % host.name, task, + force_pass=force_pass, timeout_in_secs=120) + self._host_reference = weakref.ref(host) + + @property + def _host(self): + """ + Returns the host + """ + host = self._host_reference() + return host + + def run(self): + """ + Run audit instances + """ + from nfv_vim import directors + + host_director = directors.get_host_director() + host_director.host_audit(self._host) + + return state_machine.STATE_TASK_WORK_RESULT.SUCCESS, empty_reason + + class AuditInstancesTaskWork(state_machine.StateTaskWork): """ Audit Instances Task Work diff --git a/nfv/nfv-vim/nfv_vim/host_fsm/_host_tasks.py b/nfv/nfv-vim/nfv_vim/host_fsm/_host_tasks.py index e1715387..b145c5c2 100755 --- a/nfv/nfv-vim/nfv_vim/host_fsm/_host_tasks.py +++ b/nfv/nfv-vim/nfv_vim/host_fsm/_host_tasks.py @@ -25,6 +25,7 @@ from nfv_vim.host_fsm._host_task_work import NotifyHostServicesDeleteFailedTaskW from nfv_vim.host_fsm._host_task_work import NotifyInstancesHostDisablingTaskWork from nfv_vim.host_fsm._host_task_work import NotifyInstancesHostDisabledTaskWork from nfv_vim.host_fsm._host_task_work import AuditHostServicesTaskWork +from nfv_vim.host_fsm._host_task_work import AuditHostServicesCompleteTaskWork from nfv_vim.host_fsm._host_task_work import AuditInstancesTaskWork DLOG = debug.debug_get_logger('nfv_vim.state_machine.host_task') @@ -34,10 +35,21 @@ class AddHostTask(state_machine.StateTask): """ Add Host Task """ + def __init__(self, host): + from nfv_vim import objects + self._host_reference = weakref.ref(host) task_work_list = list() - task_work_list.append(CreateHostServicesTaskWork(self, host)) + if host.host_service_configured(objects.HOST_SERVICES.COMPUTE): + task_work_list.append(CreateHostServicesTaskWork( + self, host, objects.HOST_SERVICES.COMPUTE)) + if host.host_service_configured(objects.HOST_SERVICES.NETWORK): + task_work_list.append(CreateHostServicesTaskWork( + self, host, objects.HOST_SERVICES.NETWORK)) + if host.host_service_configured(objects.HOST_SERVICES.GUEST): + task_work_list.append(CreateHostServicesTaskWork( + self, host, objects.HOST_SERVICES.GUEST)) super(AddHostTask, self).__init__( 'add-host_%s' % host.name, task_work_list) @@ -71,10 +83,24 @@ class DeleteHostTask(state_machine.StateTask): """ Delete Host Task """ + def __init__(self, host): + from nfv_vim import objects + self._host_reference = weakref.ref(host) task_work_list = list() - task_work_list.append(DeleteHostServicesTaskWork(self, host)) + if host.host_service_configured(objects.HOST_SERVICES.COMPUTE): + task_work_list.append(DeleteHostServicesTaskWork( + self, host, objects.HOST_SERVICES.COMPUTE)) + if host.host_service_configured(objects.HOST_SERVICES.NETWORK): + task_work_list.append(DeleteHostServicesTaskWork( + self, host, objects.HOST_SERVICES.NETWORK)) + if host.host_service_configured(objects.HOST_SERVICES.GUEST): + task_work_list.append(DeleteHostServicesTaskWork( + self, host, objects.HOST_SERVICES.GUEST)) + if host.host_service_configured(objects.HOST_SERVICES.CONTAINER): + task_work_list.append(DeleteHostServicesTaskWork( + self, host, objects.HOST_SERVICES.CONTAINER)) task_work_list.append(NotifyHostServicesDeletedTaskWork( self, host, force_pass=True)) super(DeleteHostTask, self).__init__( @@ -110,11 +136,27 @@ class EnableHostTask(state_machine.StateTask): """ Enable Host Task """ + def __init__(self, host): + from nfv_vim import objects + self._host_reference = weakref.ref(host) task_work_list = list() - task_work_list.append(NotifyHostEnabledTaskWork(self, host)) - task_work_list.append(EnableHostServicesTaskWork(self, host)) + if host.host_service_configured(objects.HOST_SERVICES.COMPUTE): + task_work_list.append(NotifyHostEnabledTaskWork( + self, host, objects.HOST_SERVICES.COMPUTE)) + if host.host_service_configured(objects.HOST_SERVICES.CONTAINER): + task_work_list.append(EnableHostServicesTaskWork( + self, host, objects.HOST_SERVICES.CONTAINER)) + if host.host_service_configured(objects.HOST_SERVICES.COMPUTE): + task_work_list.append(EnableHostServicesTaskWork( + self, host, objects.HOST_SERVICES.COMPUTE)) + if host.host_service_configured(objects.HOST_SERVICES.NETWORK): + task_work_list.append(EnableHostServicesTaskWork( + self, host, objects.HOST_SERVICES.NETWORK)) + if host.host_service_configured(objects.HOST_SERVICES.GUEST): + task_work_list.append(EnableHostServicesTaskWork( + self, host, objects.HOST_SERVICES.GUEST)) task_work_list.append(NotifyHostServicesEnabledTaskWork( self, host, force_pass=True)) task_work_list.append(QueryHypervisorTaskWork( @@ -172,11 +214,24 @@ class DisableHostTask(state_machine.StateTask): notify_host_services_task = NotifyHostServicesDisabledTaskWork task_work_list = list() - task_work_list.append(DisableHostServicesTaskWork(self, host)) + if host.host_service_configured(objects.HOST_SERVICES.COMPUTE): + task_work_list.append(DisableHostServicesTaskWork( + self, host, objects.HOST_SERVICES.COMPUTE)) + if host.host_service_configured(objects.HOST_SERVICES.GUEST): + task_work_list.append(DisableHostServicesTaskWork( + self, host, objects.HOST_SERVICES.GUEST)) + if host.host_service_configured(objects.HOST_SERVICES.CONTAINER): + task_work_list.append(DisableHostServicesTaskWork( + self, host, objects.HOST_SERVICES.CONTAINER)) task_work_list.append(QueryHypervisorTaskWork( self, host, force_pass=True)) task_work_list.append(NotifyInstancesHostDisablingTaskWork(self, host)) - task_work_list.append(NotifyHostDisabledTaskWork(self, host)) + if host.host_service_configured(objects.HOST_SERVICES.COMPUTE): + task_work_list.append(NotifyHostDisabledTaskWork( + self, host, objects.HOST_SERVICES.COMPUTE)) + if host.host_service_configured(objects.HOST_SERVICES.NETWORK): + task_work_list.append(NotifyHostDisabledTaskWork( + self, host, objects.HOST_SERVICES.NETWORK)) task_work_list.append(NotifyInstancesHostDisabledTaskWork(self, host)) task_work_list.append(notify_host_services_task( self, host, force_pass=True)) @@ -409,11 +464,23 @@ class AuditEnabledHostTask(state_machine.StateTask): """ Audit Enabled Host Task """ + def __init__(self, host): + from nfv_vim import objects + self._host_reference = weakref.ref(host) task_work_list = list() - task_work_list.append(AuditHostServicesTaskWork( - self, host, force_pass=True)) + if host.host_service_configured(objects.HOST_SERVICES.COMPUTE): + task_work_list.append(AuditHostServicesTaskWork( + self, host, objects.HOST_SERVICES.COMPUTE, force_pass=True)) + if host.host_service_configured(objects.HOST_SERVICES.NETWORK): + task_work_list.append(AuditHostServicesTaskWork( + self, host, objects.HOST_SERVICES.NETWORK, force_pass=True)) + if host.host_service_configured(objects.HOST_SERVICES.GUEST): + task_work_list.append(AuditHostServicesTaskWork( + self, host, objects.HOST_SERVICES.GUEST, force_pass=True)) + task_work_list.append(AuditHostServicesCompleteTaskWork( + self, host)) super(AuditEnabledHostTask, self).__init__( 'audit-enabled-host_%s' % host.name, task_work_list) diff --git a/nfv/nfv-vim/nfv_vim/nfvi/__init__.py b/nfv/nfv-vim/nfv_vim/nfvi/__init__.py index 6f956336..4b13f897 100755 --- a/nfv/nfv-vim/nfv_vim/nfvi/__init__.py +++ b/nfv/nfv-vim/nfv_vim/nfvi/__init__.py @@ -15,6 +15,11 @@ from nfv_vim.nfvi._nfvi_guest_module import nfvi_guest_services_delete # noqa: from nfv_vim.nfvi._nfvi_guest_module import nfvi_guest_services_query # noqa: F401 from nfv_vim.nfvi._nfvi_guest_module import nfvi_guest_services_vote # noqa: F401 from nfv_vim.nfvi._nfvi_guest_module import nfvi_guest_services_notify # noqa: F401 +from nfv_vim.nfvi._nfvi_guest_module import nfvi_disable_guest_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_guest_module import nfvi_enable_guest_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_guest_module import nfvi_create_guest_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_guest_module import nfvi_delete_guest_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_guest_module import nfvi_query_guest_host_services # noqa: F401 from nfv_vim.nfvi._nfvi_guest_module import nfvi_register_host_services_query_callback # noqa: F401 from nfv_vim.nfvi._nfvi_guest_module import nfvi_register_guest_services_query_callback # noqa: F401 from nfv_vim.nfvi._nfvi_guest_module import nfvi_register_guest_services_state_notify_callback # noqa: F401 @@ -28,19 +33,15 @@ from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_get_upgrade # noqa: F from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_upgrade_start # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_upgrade_activate # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_upgrade_complete # noqa: F401 -from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_create_host_services # noqa: F401 -from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_delete_host_services # noqa: F401 -from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_enable_host_services # noqa: F401 -from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_disable_host_services # noqa: F401 -from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_query_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_disable_container_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_enable_container_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_delete_container_host_services # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_notify_host_services_enabled # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_notify_host_services_disabled # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_notify_host_services_disable_extend # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_notify_host_services_disable_failed # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_notify_host_services_deleted # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_notify_host_services_delete_failed # noqa: F401 -from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_notify_host_enabled # noqa: F401 -from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_notify_host_disabled # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_notify_host_failed # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_lock_host # noqa: F401 from nfv_vim.nfvi._nfvi_infrastructure_module import nfvi_unlock_host # noqa: F401 @@ -70,6 +71,11 @@ from nfv_vim.nfvi._nfvi_block_storage_module import nfvi_delete_volume # noqa: from nfv_vim.nfvi._nfvi_block_storage_module import nfvi_update_volume # noqa: F401 from nfv_vim.nfvi._nfvi_block_storage_module import nfvi_get_volume # noqa: F401 from nfv_vim.nfvi._nfvi_block_storage_module import nfvi_get_volume_snapshots # noqa: F401 +from nfv_vim.nfvi._nfvi_network_module import nfvi_notify_network_host_disabled # noqa: F401 +from nfv_vim.nfvi._nfvi_network_module import nfvi_enable_network_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_network_module import nfvi_delete_network_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_network_module import nfvi_create_network_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_network_module import nfvi_query_network_host_services # noqa: F401 from nfv_vim.nfvi._nfvi_network_module import nfvi_network_plugin_disabled # noqa: F401 from nfv_vim.nfvi._nfvi_network_module import nfvi_get_networks # noqa: F401 from nfv_vim.nfvi._nfvi_network_module import nfvi_create_network # noqa: F401 @@ -81,6 +87,13 @@ from nfv_vim.nfvi._nfvi_network_module import nfvi_update_subnet # noqa: F401 from nfv_vim.nfvi._nfvi_network_module import nfvi_delete_subnet # noqa: F401 from nfv_vim.nfvi._nfvi_network_module import nfvi_get_subnet # noqa: F401 from nfv_vim.nfvi._nfvi_network_module import nfvi_get_subnets # noqa: F401 +from nfv_vim.nfvi._nfvi_compute_module import nfvi_notify_compute_host_enabled # noqa: F401 +from nfv_vim.nfvi._nfvi_compute_module import nfvi_notify_compute_host_disabled # noqa: F401 +from nfv_vim.nfvi._nfvi_compute_module import nfvi_disable_compute_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_compute_module import nfvi_enable_compute_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_compute_module import nfvi_delete_compute_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_compute_module import nfvi_create_compute_host_services # noqa: F401 +from nfv_vim.nfvi._nfvi_compute_module import nfvi_query_compute_host_services # noqa: F401 from nfv_vim.nfvi._nfvi_compute_module import nfvi_compute_plugin_disabled # noqa: F401 from nfv_vim.nfvi._nfvi_compute_module import nfvi_get_host_aggregates # noqa: F401 from nfv_vim.nfvi._nfvi_compute_module import nfvi_get_hypervisors # noqa: F401 diff --git a/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_compute_module.py b/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_compute_module.py index c05b6552..ddf8a022 100755 --- a/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_compute_module.py +++ b/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_compute_module.py @@ -380,6 +380,90 @@ def nfvi_register_instance_delete_callback(callback): callback=callback) +def nfvi_notify_compute_host_enabled(host_uuid, host_name, host_personality, + callback): + """ + Notify compute host is enabled + """ + cmd_id = _compute_plugin.invoke_plugin('notify_host_enabled', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_notify_compute_host_disabled(host_uuid, host_name, host_personality, + callback): + """ + Notify compute host is disabled + """ + cmd_id = _compute_plugin.invoke_plugin('notify_host_disabled', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_disable_compute_host_services(host_uuid, host_name, host_personality, + callback): + """ + Disable compute host services + """ + cmd_id = _compute_plugin.invoke_plugin('disable_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_enable_compute_host_services(host_uuid, host_name, host_personality, + callback): + """ + Enable compute host services + """ + cmd_id = _compute_plugin.invoke_plugin('enable_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_delete_compute_host_services(host_uuid, host_name, host_personality, + callback): + """ + Delete compute services + """ + cmd_id = _compute_plugin.invoke_plugin('delete_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_create_compute_host_services(host_uuid, host_name, host_personality, + callback): + """ + Create compute services + """ + cmd_id = _compute_plugin.invoke_plugin('create_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_query_compute_host_services(host_uuid, host_name, host_personality, + callback): + """ + Query compute services + """ + cmd_id = _compute_plugin.invoke_plugin('query_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + def nfvi_compute_initialize(config, pool): """ Initialize the NFVI compute package diff --git a/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_guest_module.py b/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_guest_module.py index 78de174a..75e81d12 100755 --- a/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_guest_module.py +++ b/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_guest_module.py @@ -80,6 +80,66 @@ def nfvi_guest_services_notify(instance_uuid, host_name, action_type, return cmd_id +def nfvi_disable_guest_host_services(host_uuid, host_name, + host_personality, callback): + """ + Disable guest services + """ + cmd_id = _guest_plugin.invoke_plugin('disable_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_enable_guest_host_services(host_uuid, host_name, host_personality, + callback): + """ + Enable guest services + """ + cmd_id = _guest_plugin.invoke_plugin('enable_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_delete_guest_host_services(host_uuid, host_name, host_personality, + callback): + """ + Delete guest services + """ + cmd_id = _guest_plugin.invoke_plugin('delete_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_create_guest_host_services(host_uuid, host_name, host_personality, + callback): + """ + Create guest services + """ + cmd_id = _guest_plugin.invoke_plugin('create_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_query_guest_host_services(host_uuid, host_name, host_personality, + callback): + """ + Query guest services + """ + cmd_id = _guest_plugin.invoke_plugin('query_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + def nfvi_register_host_services_query_callback(callback): """ Register for host services query diff --git a/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_infrastructure_module.py b/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_infrastructure_module.py index f716a0dc..6dee9ac7 100755 --- a/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_infrastructure_module.py +++ b/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_infrastructure_module.py @@ -85,63 +85,42 @@ def nfvi_upgrade_complete(callback): return cmd_id -def nfvi_create_host_services(host_uuid, host_name, host_personality, - callback): +def nfvi_disable_container_host_services(host_uuid, host_name, + host_personality, + callback): """ - Create host services on a host + Disable container services on a host """ - cmd_id = _infrastructure_plugin.invoke_plugin('create_host_services', - host_uuid, host_name, - host_personality, - callback=callback) + cmd_id = _infrastructure_plugin.invoke_plugin( + 'disable_host_services', + host_uuid, host_name, host_personality, + callback=callback) return cmd_id -def nfvi_delete_host_services(host_uuid, host_name, host_personality, - callback): +def nfvi_enable_container_host_services(host_uuid, host_name, + host_personality, + callback): """ - Delete host services from a host + Enable container services on a host """ - cmd_id = _infrastructure_plugin.invoke_plugin('delete_host_services', - host_uuid, host_name, - host_personality, - callback=callback) + cmd_id = _infrastructure_plugin.invoke_plugin( + 'enable_host_services', + host_uuid, host_name, host_personality, + callback=callback) return cmd_id -def nfvi_enable_host_services(host_uuid, host_name, host_personality, - callback): +def nfvi_delete_container_host_services(host_uuid, host_name, + host_personality, + callback): """ - Enable host services on a host + Delete container services on a host """ - cmd_id = _infrastructure_plugin.invoke_plugin('enable_host_services', - host_uuid, host_name, - host_personality, - callback=callback) - return cmd_id - - -def nfvi_disable_host_services(host_uuid, host_name, host_personality, - callback): - """ - Disable host services on a host - """ - cmd_id = _infrastructure_plugin.invoke_plugin('disable_host_services', - host_uuid, host_name, - host_personality, - callback=callback) - return cmd_id - - -def nfvi_query_host_services(host_uuid, host_name, host_personality, - callback): - """ - Query the administrative state of host services on a host - """ - cmd_id = _infrastructure_plugin.invoke_plugin('query_host_services', - host_uuid, host_name, - host_personality, - callback=callback) + cmd_id = _infrastructure_plugin.invoke_plugin( + 'delete_host_services', + host_uuid, host_name, host_personality, + callback=callback) return cmd_id @@ -207,29 +186,6 @@ def nfvi_notify_host_services_delete_failed(host_uuid, host_name, return cmd_id -def nfvi_notify_host_enabled(host_uuid, host_name, host_personality, callback): - """ - Notify host is enabled - """ - cmd_id = _infrastructure_plugin.invoke_plugin('notify_host_enabled', - host_uuid, host_name, - host_personality, - callback=callback) - return cmd_id - - -def nfvi_notify_host_disabled(host_uuid, host_name, host_personality, - callback): - """ - Notify host is disabled - """ - cmd_id = _infrastructure_plugin.invoke_plugin('notify_host_disabled', - host_uuid, host_name, - host_personality, - callback=callback) - return cmd_id - - def nfvi_notify_host_failed(host_uuid, host_name, host_personality, callback): """ Notify host is failed diff --git a/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_network_module.py b/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_network_module.py index c109245b..9551c46a 100755 --- a/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_network_module.py +++ b/nfv/nfv-vim/nfv_vim/nfvi/_nfvi_network_module.py @@ -117,6 +117,66 @@ def nfvi_get_subnet(subnet_id, callback): return cmd_id +def nfvi_notify_network_host_disabled(host_uuid, host_name, host_personality, + callback): + """ + Notify network host is disabled + """ + cmd_id = _network_plugin.invoke_plugin('notify_host_disabled', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_enable_network_host_services(host_uuid, host_name, host_personality, + callback): + """ + Enable network services + """ + cmd_id = _network_plugin.invoke_plugin('enable_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_delete_network_host_services(host_uuid, host_name, host_personality, + callback): + """ + Delete network services + """ + cmd_id = _network_plugin.invoke_plugin('delete_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_create_network_host_services(host_uuid, host_name, host_personality, + callback): + """ + Create network services + """ + cmd_id = _network_plugin.invoke_plugin('create_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + +def nfvi_query_network_host_services(host_uuid, host_name, host_personality, + callback): + """ + Query network services + """ + cmd_id = _network_plugin.invoke_plugin('query_host_services', + host_uuid, host_name, + host_personality, + callback=callback) + return cmd_id + + def nfvi_network_initialize(config, pool): """ Initialize the NFVI network package diff --git a/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_compute_api.py b/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_compute_api.py index fc306a0d..e0e1fbf3 100755 --- a/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_compute_api.py +++ b/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_compute_api.py @@ -276,6 +276,62 @@ class NFVIComputeAPI(object): """ pass + @abc.abstractmethod + def notify_host_enabled(self, future, host_uuid, host_name, + host_personality, callback): + """ + Notify compute host enabled using the plugin + """ + pass + + @abc.abstractmethod + def notify_host_disabled(self, future, host_uuid, host_name, + host_personality, callback): + """ + Notify compute host disabled using the plugin + """ + pass + + @abc.abstractmethod + def disable_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Disable compute services on a host using the plugin + """ + pass + + @abc.abstractmethod + def enable_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Enable compute services on a host using the plugin + """ + pass + + @abc.abstractmethod + def delete_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Delete compute services on a host using the plugin + """ + pass + + @abc.abstractmethod + def create_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Create compute services on a host using the plugin + """ + pass + + @abc.abstractmethod + def query_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Query compute services on a host using the plugin + """ + pass + @abc.abstractmethod def initialize(self, config_file): """ diff --git a/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_guest_api.py b/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_guest_api.py index f9d08dbd..a86e1d81 100755 --- a/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_guest_api.py +++ b/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_guest_api.py @@ -86,6 +86,46 @@ class NFVIGuestAPI(object): """ pass + @abc.abstractmethod + def disable_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Disable guest services on a host using the plugin + """ + pass + + @abc.abstractmethod + def enable_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Enable guest services on a host using the plugin + """ + pass + + @abc.abstractmethod + def delete_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Delete guest services on a host using the plugin + """ + pass + + @abc.abstractmethod + def create_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Create guest services on a host using the plugin + """ + pass + + @abc.abstractmethod + def query_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Query guest services on a host using the plugin + """ + pass + @abc.abstractmethod def register_host_services_query_callback(self, callback): """ diff --git a/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_infrastructure_api.py b/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_infrastructure_api.py index ad04882c..b5040c0b 100755 --- a/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_infrastructure_api.py +++ b/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_infrastructure_api.py @@ -68,43 +68,29 @@ class NFVIInfrastructureAPI(object): """ pass - @abc.abstractmethod - def create_host_services(self, future, host_uuid, host_name, - host_personality, callback): - """ - Create host services on a host using the plugin - """ - pass - @abc.abstractmethod def delete_host_services(self, future, host_uuid, host_name, host_personality, callback): """ - Delete host services on a host using the plugin + Delete infrastructure host services using the plugin """ pass @abc.abstractmethod - def enable_host_services(self, future, host_uuid, host_name, - host_personality, callback): + def enable_host_services(self, future, host_uuid, + host_name, host_personality, + callback): """ - Enable host services on a host using the plugin + Enable infrastructure host services using the plugin """ pass @abc.abstractmethod - def disable_host_services(self, future, host_uuid, host_name, - host_personality, callback): + def disable_host_services(self, future, host_uuid, + host_name, host_personality, + callback): """ - Disable host services on a host using the plugin - """ - pass - - @abc.abstractmethod - def query_host_services(self, future, host_uuid, host_name, - host_personality, callback): - """ - Query host services on a host using the plugin + Disable infrastructure host services using the plugin """ pass @@ -114,6 +100,7 @@ class NFVIInfrastructureAPI(object): """ Notify host services are now enabled using the plugin """ + pass @abc.abstractmethod def notify_host_services_disabled(self, future, host_uuid, host_name, @@ -155,22 +142,6 @@ class NFVIInfrastructureAPI(object): """ pass - @abc.abstractmethod - def notify_host_enabled(self, future, host_uuid, host_name, - host_personality, callback): - """ - Notify host enabled using the plugin - """ - pass - - @abc.abstractmethod - def notify_host_disabled(self, future, host_uuid, host_name, - host_personality, callback): - """ - Notify host disabled using the plugin - """ - pass - @abc.abstractmethod def notify_host_failed(self, future, host_uuid, host_name, host_personality, callback): diff --git a/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_network_api.py b/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_network_api.py index 29ade3b8..9827175b 100755 --- a/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_network_api.py +++ b/nfv/nfv-vim/nfv_vim/nfvi/api/v1/_nfvi_network_api.py @@ -114,6 +114,46 @@ class NFVINetworkAPI(object): """ pass + @abc.abstractmethod + def notify_host_disabled(self, future, host_uuid, host_name, + host_personality, callback): + """ + Notify network host disabled using the plugin + """ + pass + + @abc.abstractmethod + def enable_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Enable network services on a host using the plugin + """ + pass + + @abc.abstractmethod + def delete_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Delete network services on a host using the plugin + """ + pass + + @abc.abstractmethod + def create_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Create network services on a host using the plugin + """ + pass + + @abc.abstractmethod + def query_host_services(self, future, host_uuid, host_name, + host_personality, callback): + """ + Query network services on a host using the plugin + """ + pass + @abc.abstractmethod def initialize(self, config_file): """ diff --git a/nfv/nfv-vim/nfv_vim/objects/__init__.py b/nfv/nfv-vim/nfv_vim/objects/__init__.py index 09214a50..1a965ce3 100755 --- a/nfv/nfv-vim/nfv_vim/objects/__init__.py +++ b/nfv/nfv-vim/nfv_vim/objects/__init__.py @@ -8,6 +8,7 @@ from nfv_vim.objects._system import System # noqa: F401 from nfv_vim.objects._host import HOST_PERSONALITY # noqa: F401 from nfv_vim.objects._host import HOST_NAME # noqa: F401 from nfv_vim.objects._host import HOST_SERVICE_STATE # noqa: F401 +from nfv_vim.objects._host import HOST_SERVICES # noqa: F401 from nfv_vim.objects._host import Host # noqa: F401 from nfv_vim.objects._host_group import HOST_GROUP_POLICY # noqa: F401 from nfv_vim.objects._host_group import HostGroup # noqa: F401 diff --git a/nfv/nfv-vim/nfv_vim/objects/_host.py b/nfv/nfv-vim/nfv_vim/objects/_host.py index 36eab092..0eceb06b 100755 --- a/nfv/nfv-vim/nfv_vim/objects/_host.py +++ b/nfv/nfv-vim/nfv_vim/objects/_host.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 # import six +import os from nfv_common import debug from nfv_common import state_machine @@ -53,10 +54,22 @@ class HostServicesState(object): FAILED = Constant('failed') +@six.add_metaclass(Singleton) +class HostServices(object): + """ + Host-Services Constants + """ + GUEST = Constant('guest') + NETWORK = Constant('network') + COMPUTE = Constant('compute') + CONTAINER = Constant('container') + + # Host-Services Constant Instantiation HOST_SERVICE_STATE = HostServicesState() HOST_PERSONALITY = HostPersonality() HOST_NAME = HostNames() +HOST_SERVICES = HostServices() class Host(ObjectData): @@ -92,10 +105,24 @@ class Host(ObjectData): self._last_state_timestamp = timers.get_monotonic_timestamp_in_ms() self._fail_notification_required = False self._fsm_start_time = None - if self.is_enabled(): - self._host_service_state = HOST_SERVICE_STATE.ENABLED - else: - self._host_service_state = HOST_SERVICE_STATE.DISABLED + self._host_service_state = dict() + + if self.host_service_configured(HOST_SERVICES.COMPUTE): + self._host_service_state[HOST_SERVICES.COMPUTE] = \ + HOST_SERVICE_STATE.ENABLED if self.is_enabled() else \ + HOST_SERVICE_STATE.DISABLED + if self.host_service_configured(HOST_SERVICES.NETWORK): + self._host_service_state[HOST_SERVICES.NETWORK] = \ + HOST_SERVICE_STATE.ENABLED if self.is_enabled() else \ + HOST_SERVICE_STATE.DISABLED + if self.host_service_configured(HOST_SERVICES.GUEST): + self._host_service_state[HOST_SERVICES.GUEST] = \ + HOST_SERVICE_STATE.ENABLED if self.is_enabled() else \ + HOST_SERVICE_STATE.DISABLED + if self.host_service_configured(HOST_SERVICES.CONTAINER): + self._host_service_state[HOST_SERVICES.CONTAINER] = \ + HOST_SERVICE_STATE.ENABLED if self.is_enabled() else \ + HOST_SERVICE_STATE.DISABLED self._alarms = list() self._events = list() @@ -128,12 +155,70 @@ class Host(ObjectData): """ return self._fsm.current_state.name - @property - def host_service_state(self): + def host_service_configured(self, service): """ - Returns the current state of the host services + Returns whether a host service is configured or not """ - return self._host_service_state + kubernetes_config = True + if not os.path.isfile('/etc/kubernetes/admin.conf'): + kubernetes_config = False + + configured = True + + if kubernetes_config: + if service == HOST_SERVICES.COMPUTE: + configured = (not nfvi.nfvi_compute_plugin_disabled() and + self._nfvi_host.openstack_compute) + elif service == HOST_SERVICES.NETWORK: + configured = (not nfvi.nfvi_network_plugin_disabled() and + (self._nfvi_host.openstack_compute or + self._nfvi_host.openstack_control)) + elif service == HOST_SERVICES.GUEST: + configured = (not nfvi.nfvi_guest_plugin_disabled() and + self._nfvi_host.openstack_compute) + elif service != HOST_SERVICES.CONTAINER: + DLOG.error("unknown service %s" % service) + configured = False + else: + if service == HOST_SERVICES.CONTAINER: + configured = False + + DLOG.verbose("Host configure check for service %s, result %s" % + (service, configured)) + + return configured + + def host_service_state(self, service): + """ + Returns the state for a host service + """ + return self._host_service_state[service] + + def host_service_state_aggregate(self): + """ + Returns the overall state of the host services + """ + all_enabled = True + at_least_one_failed = False + for service, service_state in self._host_service_state.items(): + # Ignore state of kubernetes, plugin as + # there is no query function for that sevice. + if service == HOST_SERVICES.CONTAINER: + continue + all_enabled = all_enabled and \ + (service_state == HOST_SERVICE_STATE.ENABLED) + at_least_one_failed = at_least_one_failed or \ + (service_state == HOST_SERVICE_STATE.FAILED) + + DLOG.verbose("service_state: %s, all_enabled: %s" % + (service_state, all_enabled)) + + if all_enabled: + return HOST_SERVICE_STATE.ENABLED + elif at_least_one_failed: + return HOST_SERVICE_STATE.FAILED + else: + return HOST_SERVICE_STATE.DISABLED @property def host_services_locked(self): @@ -645,28 +730,54 @@ class Host(ObjectData): alarm.host_clear_alarm(self._alarms) self._fsm.handle_event(host_fsm.HOST_EVENT.DELETE) - def host_services_update(self, host_service_state, reason=None): + def host_services_update_all(self, host_service_state, reason=None): """ - Host services update + Host services update all """ - if host_service_state == self._host_service_state: - return + at_least_one_change = False + + for service, state in self._host_service_state.items(): + if state != host_service_state: + at_least_one_change = True + self._host_service_state[service] = host_service_state + + if at_least_one_change: + self.host_services_update(None, host_service_state, reason) + + def host_services_update(self, service, + host_service_state, reason=None): + """ + Host services update. None input service parameter indicates + that the _host_service_state has already been updated through + host_services_update_all. + """ + + if service is not None: + if host_service_state == self._host_service_state[service]: + return + + self._host_service_state[service] = host_service_state # Host services logs and alarms only apply to compute hosts if 'compute' in self.personality: - if HOST_SERVICE_STATE.ENABLED == host_service_state: + host_service_state_overall = \ + self.host_service_state_aggregate() + if (HOST_SERVICE_STATE.ENABLED == + host_service_state_overall): self._events = event_log.host_issue_log( self, event_log.EVENT_ID.HOST_SERVICES_ENABLED) alarm.host_clear_alarm(self._alarms) self._alarms[:] = list() - elif HOST_SERVICE_STATE.DISABLED == host_service_state: + elif (HOST_SERVICE_STATE.DISABLED == + host_service_state_overall): self._events = event_log.host_issue_log( self, event_log.EVENT_ID.HOST_SERVICES_DISABLED) alarm.host_clear_alarm(self._alarms) self._alarms[:] = list() - elif HOST_SERVICE_STATE.FAILED == host_service_state: + elif (HOST_SERVICE_STATE.FAILED == + host_service_state_overall): if reason is None: additional_text = '' else: @@ -679,8 +790,6 @@ class Host(ObjectData): self, alarm.ALARM_TYPE.HOST_SERVICES_FAILED, additional_text=additional_text) - self._host_service_state = host_service_state - def nfvi_host_upgrade_status(self, upgrade_inprogress, recover_instances): """ NFVI Host Upgrade diff --git a/nfv/nfv-vim/nfv_vim/strategy/_strategy.py b/nfv/nfv-vim/nfv_vim/strategy/_strategy.py index b8731305..caf899b8 100755 --- a/nfv/nfv-vim/nfv_vim/strategy/_strategy.py +++ b/nfv/nfv-vim/nfv_vim/strategy/_strategy.py @@ -19,6 +19,7 @@ from nfv_vim.objects import HOST_PERSONALITY from nfv_vim.objects import HOST_GROUP_POLICY from nfv_vim.objects import HOST_NAME from nfv_vim.objects import INSTANCE_GROUP_POLICY +from nfv_vim.objects import HOST_SERVICES from nfv_vim.nfvi.objects.v1 import UPGRADE_STATE @@ -777,8 +778,14 @@ class SwPatchStrategy(SwUpdateStrategy): # Disable host services before migrating to ensure # instances do not migrate to compute hosts in the # same set of hosts. - stage.add_step(strategy.DisableHostServicesStep( - host_list)) + if host_list[0].host_service_configured( + HOST_SERVICES.COMPUTE): + stage.add_step(strategy.DisableHostServicesStep( + host_list, HOST_SERVICES.COMPUTE)) + # TODO(ksmith) + # When support is added for orchestration on + # non-OpenStack worker nodes, support for disabling + # kubernetes services will have to be added. stage.add_step(strategy.MigrateInstancesStep( instance_list)) else: @@ -1375,7 +1382,15 @@ class SwUpgradeStrategy(SwUpdateStrategy): # Disable host services before migrating to ensure # instances do not migrate to compute hosts in the # same set of hosts. - stage.add_step(strategy.DisableHostServicesStep(host_list)) + if host_list[0].host_service_configured( + HOST_SERVICES.COMPUTE): + stage.add_step(strategy.DisableHostServicesStep( + host_list, HOST_SERVICES.COMPUTE)) + # TODO(ksmith) + # When support is added for orchestration on + # non-OpenStack worker nodes, support for disabling + # kubernetes services will have to be added. + stage.add_step(strategy.MigrateInstancesStep(instance_list)) stage.add_step(strategy.LockHostsStep(host_list)) stage.add_step(strategy.UpgradeHostsStep(host_list)) diff --git a/nfv/nfv-vim/nfv_vim/strategy/_strategy_steps.py b/nfv/nfv-vim/nfv_vim/strategy/_strategy_steps.py index b946aff5..3315496b 100755 --- a/nfv/nfv-vim/nfv_vim/strategy/_strategy_steps.py +++ b/nfv/nfv-vim/nfv_vim/strategy/_strategy_steps.py @@ -1793,12 +1793,14 @@ class DisableHostServicesStep(strategy.StrategyStep): """ Disable Host Services - Strategy Step """ - def __init__(self, hosts): + def __init__(self, hosts, service): super(DisableHostServicesStep, self).__init__( - STRATEGY_STEP_NAME.DISABLE_HOST_SERVICES, timeout_in_secs=180) + "%s" % STRATEGY_STEP_NAME.DISABLE_HOST_SERVICES, + timeout_in_secs=180) self._hosts = hosts self._host_names = list() self._host_uuids = list() + self._service = service for host in hosts: self._host_names.append(host.name) self._host_uuids.append(host.uuid) @@ -1807,7 +1809,7 @@ class DisableHostServicesStep(strategy.StrategyStep): """ Returns the abort step related to this step """ - return [EnableHostServicesStep(self._hosts)] + return [EnableHostServicesStep(self._hosts, self._service)] def _total_hosts_services_disabled(self): """ @@ -1820,7 +1822,8 @@ class DisableHostServicesStep(strategy.StrategyStep): if host is None: return -1 - if objects.HOST_SERVICE_STATE.DISABLED == host.host_service_state: + if (objects.HOST_SERVICE_STATE.DISABLED == + host.host_service_state(self._service)): total_hosts_services_disabled += 1 return total_hosts_services_disabled @@ -1831,10 +1834,11 @@ class DisableHostServicesStep(strategy.StrategyStep): """ from nfv_vim import directors - DLOG.info("Step (%s) apply for hosts %s." % (self._name, - self._host_names)) + DLOG.info("Step (%s) apply for hosts %s service %s." % + (self._name, self._host_names, self._service)) host_director = directors.get_host_director() - operation = host_director.disable_host_services(self._host_names) + operation = host_director.disable_host_services(self._host_names, + self._service) if operation.is_inprogress(): return strategy.STRATEGY_STEP_RESULT.WAIT, "" elif operation.is_failed(): @@ -1880,6 +1884,7 @@ class DisableHostServicesStep(strategy.StrategyStep): self._hosts = list() self._host_uuids = list() self._host_names = data['entity_names'] + self._service = data['entity_service'] host_table = tables.tables_get_host_table() for host_name in self._host_names: host = host_table.get(host_name, None) @@ -1896,6 +1901,7 @@ class DisableHostServicesStep(strategy.StrategyStep): data['entity_type'] = 'hosts' data['entity_names'] = self._host_names data['entity_uuids'] = self._host_uuids + data['entity_service'] = self._service return data @@ -1903,12 +1909,14 @@ class EnableHostServicesStep(strategy.StrategyStep): """ Enable Host Services - Strategy Step """ - def __init__(self, hosts): + def __init__(self, hosts, service): super(EnableHostServicesStep, self).__init__( - STRATEGY_STEP_NAME.ENABLE_HOST_SERVICES, timeout_in_secs=180) + "%s" % STRATEGY_STEP_NAME.ENABLE_HOST_SERVICES, + timeout_in_secs=180) self._hosts = hosts self._host_names = list() self._host_uuids = list() + self._service = service for host in hosts: self._host_names.append(host.name) self._host_uuids.append(host.uuid) @@ -1924,7 +1932,8 @@ class EnableHostServicesStep(strategy.StrategyStep): if host is None: return -1 - if objects.HOST_SERVICE_STATE.ENABLED == host.host_service_state: + if (objects.HOST_SERVICE_STATE.ENABLED == + host.host_service_state(self._service)): total_hosts_services_enabled += 1 return total_hosts_services_enabled @@ -1935,10 +1944,11 @@ class EnableHostServicesStep(strategy.StrategyStep): """ from nfv_vim import directors - DLOG.info("Step (%s) apply for hosts %s." % (self._name, - self._host_names)) + DLOG.info("Step (%s) apply for hosts %s service %s." % + (self._name, self._host_names, self._service)) host_director = directors.get_host_director() - operation = host_director.enable_host_services(self._host_names) + operation = host_director.enable_host_services(self._host_names, + self._service) if operation.is_inprogress(): return strategy.STRATEGY_STEP_RESULT.WAIT, "" elif operation.is_failed(): @@ -1984,6 +1994,7 @@ class EnableHostServicesStep(strategy.StrategyStep): self._hosts = list() self._host_uuids = list() self._host_names = data['entity_names'] + self._service = data['entity_service'] host_table = tables.tables_get_host_table() for host_name in self._host_names: host = host_table.get(host_name, None) @@ -2000,6 +2011,7 @@ class EnableHostServicesStep(strategy.StrategyStep): data['entity_type'] = 'hosts' data['entity_names'] = self._host_names data['entity_uuids'] = self._host_uuids + data['entity_service'] = self._service return data