From 5b1a1018f8df3758995b4462e9d29efb0012e49c Mon Sep 17 00:00:00 2001 From: Cole Walker Date: Fri, 14 Jan 2022 14:48:23 -0500 Subject: [PATCH] [PTP dual NIC config] Enable ptpinstance functionality This commit provides the API and CLI updates to enable ptpinstance functionality and runtime manifest application. A new CLI command is provided to apply the ptpinstance configuration: system ptp-instance-apply Tests: Pass: Build and install on hardware lab Pass: multi instance ptp can be configured and applied Regression: Pass: Single instance ptp is unaffected Story: 2009248 Task: 44292 Depends-on: https://review.opendev.org/c/starlingx/stx-puppet/+/824800 Signed-off-by: Cole Walker Change-Id: I095a000989af9c3c002b6bde5f899c0671860e66 --- .../cgts-client/cgtsclient/v1/ptp_instance.py | 3 ++ .../cgtsclient/v1/ptp_instance_shell.py | 8 +++++ .../sysinv/sysinv/api/controllers/v1/host.py | 7 ++-- .../sysinv/api/controllers/v1/ptp_instance.py | 14 ++++++++ .../sysinv/sysinv/sysinv/conductor/manager.py | 33 ++++++++++++------- .../sysinv/sysinv/sysinv/conductor/rpcapi.py | 9 ++--- .../sysinv/sysinv/sysinv/puppet/networking.py | 14 +++----- 7 files changed, 58 insertions(+), 30 deletions(-) diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/ptp_instance.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/ptp_instance.py index 413b89b27c..f62e635e77 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/ptp_instance.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/ptp_instance.py @@ -56,6 +56,9 @@ class PtpInstanceManager(base.Manager): def delete(self, ptp_instance_id): return self._delete(self._path(ptp_instance_id)) + def apply(self): + return self.api.json_request('POST', self._path() + "/apply") + def _find_ptp_instance(cc, key): if key.isdigit() or utils.is_uuid_like(key): diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/ptp_instance_shell.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/ptp_instance_shell.py index b9fc40e538..1df613440d 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/ptp_instance_shell.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/ptp_instance_shell.py @@ -184,3 +184,11 @@ def do_host_ptp_instance_remove(cc, args): ihost = ihost_utils._find_ihost(cc, args.hostnameorid) _host_ptp_instance_op(cc, op='remove', uuid=ihost.uuid, instance=args.nameoruuid) + + +def do_ptp_instance_apply(cc, args): + """Apply the PTP Instance config.""" + + cc.ptp_instance.apply() + + print('Applying the PTP Instance configuration') diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/host.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/host.py index 159cc057fc..d2d145d805 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/host.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/host.py @@ -6467,9 +6467,12 @@ class HostController(rest.RestController): if interface.ptp_role != constants.INTERFACE_PTP_ROLE_NONE: ptp_ifaces.append(interface) - if not ptp_ifaces: + ptp_instances = pecan.request.dbapi.ptp_instances_get_list(host_uuid) + if not (ptp_ifaces or ptp_instances): raise wsme.exc.ClientSideError( - _("Hosts with PTP clock synchronization must have at least one PTP interface configured")) + _("Hosts with PTP clock synchronization " + "must have at least one PTP " + "interface or instance configured")) # Check that interfaces have addresses assigned if PTP transport is UDP system_ptp = pecan.request.dbapi.ptp_get_one() diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/ptp_instance.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/ptp_instance.py index 1dcbeab8b7..eecf3122c1 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/ptp_instance.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/ptp_instance.py @@ -133,6 +133,10 @@ LOCK_NAME = 'PtpInstanceController' class PtpInstanceController(rest.RestController): """REST controller for PTP instance.""" + _custom_actions = { + 'apply': ['POST'] + } + ptp_parameters = ptp_parameter.PtpParameterController( parent="ptp_instance") "Expose PTP parameters as a sub-element of PTP instances" @@ -281,3 +285,13 @@ class PtpInstanceController(rest.RestController): LOG.debug("PtpInstanceController.delete: all clear for %s" % ptp_instance_uuid) pecan.request.dbapi.ptp_instance_destroy(ptp_instance_uuid) + + @cutils.synchronized(LOCK_NAME) + @wsme_pecan.wsexpose(None, status_code=204) + def apply(self): + """Apply the ptp instance configuration.""" + try: + pecan.request.rpcapi.update_ptp_instances_config(pecan.request.context) + except exception.HTTPNotFound: + msg = ("PTP Instance apply failed") + raise wsme.exc.ClientSideError(msg) diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py index 68bd1d4914..1331c0a0f2 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py @@ -7174,18 +7174,27 @@ class ConductorManager(service.PeriodicService): } self._config_apply_runtime_manifest(context, config_uuid, config_dict) - def update_ptp_instances_config(self, context, host_uuid, - ptp_instances_dict): - try: - host = self.dbapi.ihost_get(host_uuid) - if host: # TODO: put here to make variable used; remove it later - pass - except exception.ServerNotFound: - LOG.error("Cannot find host by id %s" % host_uuid) - return - # TODO: apply configuration of PTP instance to host (will probably go - # through PTP parameters instead to set the 'conf' files for services) - pass + def update_ptp_instances_config(self, context): + personalities = [constants.CONTROLLER, + constants.WORKER, + constants.STORAGE] + hosts = self.dbapi.ihost_get_list() + runtime_hosts = [] + for host in hosts: + if (host.clock_synchronization == constants.PTP and + host.administrative == constants.ADMIN_UNLOCKED and + host.operational == constants.OPERATIONAL_ENABLED): + runtime_hosts.append(host.uuid) + + if runtime_hosts: + config_dict = { + "personalities": personalities, + "classes": ['platform::ptpinstance::runtime'], + "host_uuids": runtime_hosts + } + config_uuid = self._config_update_hosts(context, personalities, + host_uuids=runtime_hosts) + self._config_apply_runtime_manifest(context, config_uuid, config_dict) def update_system_mode_config(self, context): """Update the system mode configuration""" diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py b/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py index 7db37d777e..96b1086b3d 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py @@ -808,18 +808,13 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy): """ return self.call(context, self.make_msg('update_ptp_config', do_apply=do_apply)) - def update_ptp_instances_config(self, context, host_uuid, - ptp_instances_dict): + def update_ptp_instances_config(self, context): """Synchronously, have the conductor update PTP instance(s). :param context: request context. - :param host_uuid: uuid or id of the host - :param ptp_instances_dict: a dictionary {name:service} of PTP instances """ return self.call(context, - self.make_msg('update_ptp_instances_config', - host_uuid=host_uuid, - ptp_instances_dict=ptp_instances_dict)) + self.make_msg('update_ptp_instances_config')) def update_system_mode_config(self, context): """Synchronously, have the conductor update the system mode diff --git a/sysinv/sysinv/sysinv/sysinv/puppet/networking.py b/sysinv/sysinv/sysinv/sysinv/puppet/networking.py index 4130d267fb..383b77d014 100644 --- a/sysinv/sysinv/sysinv/sysinv/puppet/networking.py +++ b/sysinv/sysinv/sysinv/sysinv/puppet/networking.py @@ -292,15 +292,11 @@ class NetworkingPuppet(base.BasePuppet): def _get_instance_ptp_config(self, host): - if host.clock_synchronization == constants.PTP: - ptp_enabled = True + if (host.clock_synchronization != constants.PTP): + ptpinstance_enabled = False + return {'platform::ptpinstance::enabled': ptpinstance_enabled} else: - ptp_enabled = False - - # Returning here because ptp instance functionality is not enabled at this time - # Subsequent code is inactive until this return statement is removed and ptp instance - # functionality is turned on - return {'platform::ptpinstance::enabled': ptp_enabled} + ptpinstance_enabled = True # Get the database entries for instances, interfaces and parameters ptp_instances = self.dbapi.ptp_instances_get_list(host=host.id) @@ -327,7 +323,7 @@ class NetworkingPuppet(base.BasePuppet): ptp_parameters_interface) return {'platform::ptpinstance::config': ptp_config, - 'platform::ptpinstance::enabled': ptp_enabled} + 'platform::ptpinstance::enabled': ptpinstance_enabled} def _get_ptp_interface_config(self): config = {}