From b6f7a850592cc3ba90b7a00874e3a629fffee26a Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Tue, 27 Nov 2018 14:23:05 -0500 Subject: [PATCH] Allow VIM to manage services independently Refactor the VIM to allow it to manage openstack and platform services independently. The disable/enable/create/delete/ notify/query_host_services methods in nfvi_infrastrcture_api.py are separated into the corresponding applicable plugin api to which the constituent parts belong. Multiple tasks are created (where applicable) to do the individual pieces of work corresponding to each plugin. Story: 2003910 Task: 27851 Change-Id: Ie86d293aa6a06dd3402fd75100fe7adf659af035 Signed-off-by: Kevin Smith --- .../nfvi_plugins/nfvi_compute_api.py | 508 ++++++++++ .../nfvi_plugins/nfvi_guest_api.py | 364 +++++++ .../nfvi_plugins/nfvi_infrastructure_api.py | 892 +----------------- .../nfvi_plugins/nfvi_network_api.py | 465 +++++++++ .../nfv_vim/directors/_host_director.py | 109 ++- .../nfv_vim/host_fsm/_host_state_enabled.py | 3 +- .../nfv_vim/host_fsm/_host_task_work.py | 307 ++++-- nfv/nfv-vim/nfv_vim/host_fsm/_host_tasks.py | 83 +- nfv/nfv-vim/nfv_vim/nfvi/__init__.py | 27 +- .../nfv_vim/nfvi/_nfvi_compute_module.py | 84 ++ .../nfv_vim/nfvi/_nfvi_guest_module.py | 60 ++ .../nfvi/_nfvi_infrastructure_module.py | 92 +- .../nfv_vim/nfvi/_nfvi_network_module.py | 60 ++ .../nfv_vim/nfvi/api/v1/_nfvi_compute_api.py | 56 ++ .../nfv_vim/nfvi/api/v1/_nfvi_guest_api.py | 40 + .../nfvi/api/v1/_nfvi_infrastructure_api.py | 49 +- .../nfv_vim/nfvi/api/v1/_nfvi_network_api.py | 40 + nfv/nfv-vim/nfv_vim/objects/__init__.py | 1 + nfv/nfv-vim/nfv_vim/objects/_host.py | 143 ++- nfv/nfv-vim/nfv_vim/strategy/_strategy.py | 21 +- .../nfv_vim/strategy/_strategy_steps.py | 38 +- 21 files changed, 2318 insertions(+), 1124 deletions(-) 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