diff --git a/puppet-manifests/src/modules/openstack/manifests/cinder.pp b/puppet-manifests/src/modules/openstack/manifests/cinder.pp index 6935eb33db..83315a9942 100644 --- a/puppet-manifests/src/modules/openstack/manifests/cinder.pp +++ b/puppet-manifests/src/modules/openstack/manifests/cinder.pp @@ -245,7 +245,7 @@ class openstack::cinder::backup class openstack::cinder::backends::san inherits ::openstack::cinder::params { include ::openstack::cinder::emc_vnx - include ::openstack::cinder::hpe3par + include ::openstack::cinder::backends::hpe3par include ::openstack::cinder::hpelefthand } @@ -520,23 +520,29 @@ class openstack::cinder::emc_vnx( } -class openstack::cinder::hpe3par( - $feature_enabled, - $config_params -) inherits ::openstack::cinder::params { - create_resources('cinder_config', hiera_hash('openstack::cinder::hpe3par::config_params', {})) +define openstack::cinder::backend::hpe3par +{ + $hiera_params = "openstack::cinder::${name}::config_params" + $feature_enabled = "openstack::cinder::${name}::feature_enabled" - # As HP SANs are addon PS supported options, make sure we have explicit - # logging showing this is being included when the feature is enabled. + create_resources('cinder_config', hiera_hash($hiera_params, {})) + if $feature_enabled { - exec {'Including hpe3par configuration': + exec {"Including $name configuration": path => [ '/usr/bin', '/usr/sbin', '/bin', '/sbin' ], - command => 'echo Including hpe3par configuration', + command => "echo Including $name configuration", } } } +class openstack::cinder::backends::hpe3par ( + $sections = [] +) inherits ::openstack::cinder::params { + ::openstack::cinder::backend::hpe3par {$sections:} +} + + class openstack::cinder::hpelefthand( $feature_enabled, $config_params diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/service_parameter.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/service_parameter.py index c5b3a7f8f5..38c925d56e 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/service_parameter.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/service_parameter.py @@ -134,6 +134,21 @@ class ServiceParameterController(rest.RestController): def __init__(self, parent=None, **kwargs): self._parent = parent + # Add additional hpe3par backends + for i in range(2, constants.SERVICE_PARAM_MAX_HPE3PAR + 1): + section = "{0}{1}".format(constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, i) + service_parameter.SERVICE_PARAMETER_SCHEMA[constants.SERVICE_TYPE_CINDER][section] = { + service_parameter.SERVICE_PARAM_MANDATORY: + service_parameter.CINDER_HPE3PAR_PARAMETER_MANDATORY, + service_parameter.SERVICE_PARAM_PROTECTED: + service_parameter.CINDER_HPE3PAR_PARAMETER_PROTECTED, + service_parameter.SERVICE_PARAM_OPTIONAL: + service_parameter.CINDER_HPE3PAR_PARAMETER_OPTIONAL, + service_parameter.SERVICE_PARAM_VALIDATOR: + service_parameter.CINDER_HPE3PAR_PARAMETER_VALIDATOR, + service_parameter.SERVICE_PARAM_RESOURCE: + service_parameter.CINDER_HPE3PAR_PARAMETER_RESOURCE, + } def _get_service_parameter_collection(self, marker=None, limit=None, sort_key=None, sort_dir=None, @@ -952,8 +967,12 @@ class ServiceParameterController(rest.RestController): self._service_parameter_apply_semantic_check_cinder_emc_vnx() self._emc_vnx_ip_addresses_reservation() - self._service_parameter_apply_semantic_check_cinder_hpe3par() - self._hpe3par_reserve_ip_addresses() + self._service_parameter_apply_semantic_check_cinder_hpe3par(constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR) + self._hpe3par_reserve_ip_addresses(constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR) + for i in range(2, constants.SERVICE_PARAM_MAX_HPE3PAR + 1): + section = "{0}{1}".format(constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, i) + self._service_parameter_apply_semantic_check_cinder_hpe3par(section) + self._hpe3par_reserve_ip_addresses(section) self._service_parameter_apply_semantic_check_cinder_hpelefthand() self._hpelefthand_reserve_ip_addresses() @@ -986,7 +1005,7 @@ class ServiceParameterController(rest.RestController): LOG.exception(e) @staticmethod - def _hpe3par_reserve_ip_addresses(): + def _hpe3par_reserve_ip_addresses(section): """ We need to keep the address information between service_parameter @@ -997,11 +1016,11 @@ class ServiceParameterController(rest.RestController): Service Parameter | Address DB Entry Name --------------------------------------------------------------- - hpe3par_api_url | hpe3par-api-ip + hpe3par_api_url |
-api-ip --------------------------------------------------------------- - hpe3par_iscsi_ips | hpe3par-iscsi-ip + hpe3par_iscsi_ips |
-iscsi-ip --------------------------------------------------------------- - san_ip | hpe3par-san-ip + san_ip |
-san-ip --------------------------------------------------------------- """ @@ -1011,7 +1030,7 @@ class ServiceParameterController(rest.RestController): # feature is enabled. # - name = "hpe3par-api-ip" + name = section + "-api-ip" try: addr = pecan.request.dbapi.address_get_by_name(name) LOG.debug("Removing address %s" % name) @@ -1021,7 +1040,7 @@ class ServiceParameterController(rest.RestController): i = 0 while True: - name = "hpe3par-iscsi-ip" + str(i) + name = section + "-iscsi-ip" + str(i) try: addr = pecan.request.dbapi.address_get_by_name(name) LOG.debug("Removing address %s" % name) @@ -1030,7 +1049,7 @@ class ServiceParameterController(rest.RestController): except exception.AddressNotFoundByName: break - name = "hpe3par-san-ip" + name = section + "-san-ip" try: addr = pecan.request.dbapi.address_get_by_name(name) LOG.debug("Removing address %s" % name) @@ -1040,7 +1059,7 @@ class ServiceParameterController(rest.RestController): enabled = pecan.request.dbapi.service_parameter_get_one( service=constants.SERVICE_TYPE_CINDER, - section=constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, + section=section, name="enabled") if enabled.value.lower() == 'false': @@ -1051,7 +1070,7 @@ class ServiceParameterController(rest.RestController): # api_url = pecan.request.dbapi.service_parameter_get_one( service=constants.SERVICE_TYPE_CINDER, - section=constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, + section=section, name="hpe3par_api_url") url = urlparse.urlparse(api_url.value) @@ -1063,7 +1082,7 @@ class ServiceParameterController(rest.RestController): # if pool is not None: try: - name = "hpe3par-api-ip" + name = section + "-api-ip" address = {'address': str(ip), 'prefix': pool['prefix'], 'family': pool['family'], @@ -1099,7 +1118,7 @@ class ServiceParameterController(rest.RestController): # if pool is not None: try: - name = "hpe3par-iscsi-ip" + str(i) + name = section + "-iscsi-ip" + str(i) address = {'address': str(ip), 'prefix': pool['prefix'], 'family': pool['family'], @@ -1122,7 +1141,7 @@ class ServiceParameterController(rest.RestController): try: san_ip = pecan.request.dbapi.service_parameter_get_one( service=constants.SERVICE_TYPE_CINDER, - section=constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, + section=section, name="san_ip") except exception.NotFound: return @@ -1135,7 +1154,7 @@ class ServiceParameterController(rest.RestController): # if pool is not None: try: - name = "hpe3par-san-ip" + name = section + "-san-ip" address = {'address': str(ip), 'prefix': pool['prefix'], 'family': pool['family'], @@ -1219,12 +1238,12 @@ class ServiceParameterController(rest.RestController): raise wsme.exc.ClientSideError(msg) @staticmethod - def _service_parameter_apply_semantic_check_cinder_hpe3par(): + def _service_parameter_apply_semantic_check_cinder_hpe3par(section): """Semantic checks for the Cinder Service Type """ feature_enabled = pecan.request.dbapi.service_parameter_get_one( service=constants.SERVICE_TYPE_CINDER, - section=constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, - name=constants.SERVICE_PARAM_CINDER_HPE3PAR_ENABLED) + section=section, + name=constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED) if feature_enabled.value.lower() == 'true': # Client library installed? If not fail. @@ -1237,21 +1256,21 @@ class ServiceParameterController(rest.RestController): try: pecan.request.dbapi.service_parameter_get_one( service=constants.SERVICE_TYPE_CINDER, - section=constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, + section=section, name=name) except exception.NotFound: msg = _("Unable to apply service parameters. " "Missing service parameter '%s' for service '%s' " "in section '%s'." % (name, constants.SERVICE_TYPE_CINDER, - constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR)) + section)) raise wsme.exc.ClientSideError(msg) else: if not pecan.request.rpcapi.validate_hpe3par_removal( - pecan.request.context): + pecan.request.context, section): msg = _("Unable to apply service parameters. Can not disable " "%s while in use. Remove any HPE3PAR volumes." - % constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR) + % section) raise wsme.exc.ClientSideError(msg) @staticmethod @@ -1260,7 +1279,7 @@ class ServiceParameterController(rest.RestController): feature_enabled = pecan.request.dbapi.service_parameter_get_one( service=constants.SERVICE_TYPE_CINDER, section=constants.SERVICE_PARAM_SECTION_CINDER_HPELEFTHAND, - name=constants.SERVICE_PARAM_CINDER_HPELEFTHAND_ENABLED) + name=constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED) if feature_enabled.value.lower() == 'true': # Client library installed? If not fail. diff --git a/sysinv/sysinv/sysinv/sysinv/common/constants.py b/sysinv/sysinv/sysinv/sysinv/common/constants.py index 60a91a0f7a..9dc7dec77a 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/constants.py +++ b/sysinv/sysinv/sysinv/sysinv/common/constants.py @@ -815,12 +815,11 @@ SERVICE_PARAM_SECTION_CINDER_EMC_VNX = 'emc_vnx' SERVICE_PARAM_CINDER_EMC_VNX_ENABLED = 'enabled' SERVICE_PARAM_SECTION_CINDER_EMC_VNX_STATE = 'emc_vnx.state' +SERVICE_PARAM_MAX_HPE3PAR = 12 SERVICE_PARAM_SECTION_CINDER_HPE3PAR = 'hpe3par' -SERVICE_PARAM_CINDER_HPE3PAR_ENABLED = 'enabled' SERVICE_PARAM_SECTION_CINDER_HPE3PAR_STATE = 'hpe3par.state' SERVICE_PARAM_SECTION_CINDER_HPELEFTHAND = 'hpelefthand' -SERVICE_PARAM_CINDER_HPELEFTHAND_ENABLED = 'enabled' SERVICE_PARAM_SECTION_CINDER_HPELEFTHAND_STATE = 'hpelefthand.state' SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS = 'status' diff --git a/sysinv/sysinv/sysinv/sysinv/common/service_parameter.py b/sysinv/sysinv/sysinv/sysinv/common/service_parameter.py index 153a5da3f4..dd54face3a 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/service_parameter.py +++ b/sysinv/sysinv/sysinv/sysinv/common/service_parameter.py @@ -1219,7 +1219,7 @@ HPE_DATA_NETWORKS = [ # CINDER_HPE3PAR_PARAMETER_MANDATORY = [ - constants.SERVICE_PARAM_CINDER_HPE3PAR_ENABLED, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED, ] CINDER_HPE3PAR_PARAMETER_PROTECTED = [ @@ -1251,7 +1251,7 @@ CINDER_HPE3PAR_PARAMETER_OPTIONAL = ( CINDER_HPE3PAR_PARAMETER_VALIDATOR = { # Mandatory parameters - constants.SERVICE_PARAM_CINDER_HPE3PAR_ENABLED: _validate_boolean, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED: _validate_boolean, # Required parameters 'hpe3par_api_url': _validate_hpe_api_url, 'hpe3par_username': _validate_not_empty, @@ -1270,7 +1270,7 @@ CINDER_HPE3PAR_PARAMETER_VALIDATOR = { CINDER_HPE3PAR_PARAMETER_RESOURCE = { # Mandatory parameters - constants.SERVICE_PARAM_CINDER_HPE3PAR_ENABLED: None, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED: None, # Required parameters 'hpe3par_api_url': None, 'hpe3par_username': None, @@ -1292,7 +1292,7 @@ CINDER_HPE3PAR_PARAMETER_RESOURCE = { # CINDER_HPELEFTHAND_PARAMETER_MANDATORY = [ - constants.SERVICE_PARAM_CINDER_HPELEFTHAND_ENABLED, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED, ] CINDER_HPELEFTHAND_PARAMETER_PROTECTED = [] @@ -1321,7 +1321,7 @@ CINDER_HPELEFTHAND_PARAMETER_OPTIONAL = ( CINDER_HPELEFTHAND_PARAMETER_VALIDATOR = { # Mandatory parameters - constants.SERVICE_PARAM_CINDER_HPELEFTHAND_ENABLED: _validate_boolean, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED: _validate_boolean, # Required parameters 'hpelefthand_api_url': _validate_hpe_api_url, 'hpelefthand_username': _validate_not_empty, @@ -1335,7 +1335,7 @@ CINDER_HPELEFTHAND_PARAMETER_VALIDATOR = { CINDER_HPELEFTHAND_PARAMETER_RESOURCE = { # Mandatory parameters - constants.SERVICE_PARAM_CINDER_HPELEFTHAND_ENABLED: None, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED: None, # Required parameters 'hpelefthand_api_url': None, 'hpelefthand_username': None, diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py index a9af97deef..c6d2e23747 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py @@ -428,12 +428,12 @@ class ConductorManager(service.PeriodicService): }, {'service': constants.SERVICE_TYPE_CINDER, 'section': constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, - 'name': constants.SERVICE_PARAM_CINDER_HPE3PAR_ENABLED, + 'name': constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED, 'value': False }, {'service': constants.SERVICE_TYPE_CINDER, 'section': constants.SERVICE_PARAM_SECTION_CINDER_HPELEFTHAND, - 'name': constants.SERVICE_PARAM_CINDER_HPELEFTHAND_ENABLED, + 'name': constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED, 'value': False }, {'service': constants.SERVICE_TYPE_CINDER, @@ -510,6 +510,16 @@ class ConductorManager(service.PeriodicService): 'value': constants.SERVICE_PARAM_SWIFT_FS_SIZE_MB_DEFAULT}, ] + for i in range(2, constants.SERVICE_PARAM_MAX_HPE3PAR + 1): + section = "{0}{1}".format(constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, i) + DEFAULT_PARAMETERS.extend([ + {'service': constants.SERVICE_TYPE_CINDER, + 'section': section, + 'name': constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED, + 'value': False + }] + ) + def _create_default_service_parameter(self): """ Populate the default service parameters""" for p in ConductorManager.DEFAULT_PARAMETERS: @@ -4740,18 +4750,32 @@ class ConductorManager(service.PeriodicService): of cinder services. """ - # Only run audit of either one of the backends is enabled + # Only run audit if any one of the backends is enabled + hpe3par_enabled = False try: param = self.dbapi.service_parameter_get_one(constants.SERVICE_TYPE_CINDER, - constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, 'enabled') + constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED) hpe3par_enabled = param.value.lower() == 'true' except exception.NotFound: - hpe3par_enabled = False - + pass + if not hpe3par_enabled: + for i in range(2, constants.SERVICE_PARAM_MAX_HPE3PAR + 1): + section = "{0}{1}".format(constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR, i) + try: + param = self.dbapi.service_parameter_get_one(constants.SERVICE_TYPE_CINDER, + section, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED) + hpe3par_enabled = param.value.lower() == 'true' + except exception.NotFound: + pass + if hpe3par_enabled: + break try: param = self.dbapi.service_parameter_get_one(constants.SERVICE_TYPE_CINDER, - constants.SERVICE_PARAM_SECTION_CINDER_HPELEFTHAND, 'enabled') + constants.SERVICE_PARAM_SECTION_CINDER_HPELEFTHAND, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED) hpelefthand_enabled = param.value.lower() == 'true' except exception.NotFound: hpelefthand_enabled = False @@ -6991,12 +7015,28 @@ class ConductorManager(service.PeriodicService): status_param = self._hpe_get_state(name) status = status_param.value - enabled_param = self.dbapi.service_parameter_get_one( - constants.SERVICE_TYPE_CINDER, name, - constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED - ) - enabled = (enabled_param.value.lower() == 'true') - + enabled = False + try: + enabled_param = self.dbapi.service_parameter_get_one( + constants.SERVICE_TYPE_CINDER, name, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED + ) + enabled = (enabled_param.value.lower() == 'true') + except exception.NotFound: + pass + if not enabled and name == constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR: + for i in range(2, constants.SERVICE_PARAM_MAX_HPE3PAR + 1): + section = "{0}{1}".format(name, i) + try: + enabled_param = self.dbapi.service_parameter_get_one( + constants.SERVICE_TYPE_CINDER, section, + constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED + ) + enabled = (enabled_param.value.lower() == 'true') + except exception.NotFound: + pass + if enabled: + break if enabled and status == constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_DISABLED: do_update = True new_state = constants.SERVICE_PARAM_CINDER_SAN_CHANGE_STATUS_ENABLED @@ -9230,7 +9270,7 @@ class ConductorManager(service.PeriodicService): return not emc_volume_found - def validate_hpe3par_removal(self, context): + def validate_hpe3par_removal(self, context, backend): """ Check that it is safe to remove the HPE3PAR SAN Ensure there are no volumes using the HPE3PAR endpoint @@ -9239,7 +9279,7 @@ class ConductorManager(service.PeriodicService): for volume in self._openstack.get_cinder_volumes(): end_point = getattr(volume, 'os-vol-host-attr:host', '') - if end_point and '@hpe3par' in end_point: + if end_point and '@' + backend + '#' in end_point: volume_found = True break diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py b/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py index 1376b60126..00c3ab44f8 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py @@ -1368,11 +1368,13 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy): """ return self.call(context, self.make_msg('validate_emc_removal')) - def validate_hpe3par_removal(self, context): + def validate_hpe3par_removal(self, context, backend): """ Check that it is safe to remove the HPE 3PAR storage array """ - return self.call(context, self.make_msg('validate_hpe3par_removal')) + return self.call(context, + self.make_msg('validate_hpe3par_removal', + backend=backend)) def validate_hpelefthand_removal(self, context): """ diff --git a/sysinv/sysinv/sysinv/sysinv/puppet/cinder.py b/sysinv/sysinv/sysinv/sysinv/puppet/cinder.py index 261f38fabe..519a2c966a 100644 --- a/sysinv/sysinv/sysinv/sysinv/puppet/cinder.py +++ b/sysinv/sysinv/sysinv/sysinv/puppet/cinder.py @@ -250,7 +250,7 @@ def sp_hpe3par_post_process(config, section, section_map, if provided_params.get('enabled', 'false').lower() == 'true': # Hardcoded params must exist in cinder.conf. - provided_params['volume_backend_name'] = SP_CINDER_HPE3PAR + provided_params['volume_backend_name'] = section provided_params['volume_driver'] = ( 'cinder.volume.drivers.hpe.hpe_3par_iscsi.HPE3PARISCSIDriver') @@ -345,6 +345,18 @@ class CinderPuppet(openstack.OpenstackBasePuppet): SERVICE_PATH_V3 = 'v3/%(tenant_id)s' PROXY_SERVICE_PORT = '28776' + def __init__(self, *args, **kwargs): + super(CinderPuppet, self).__init__(*args, **kwargs) + # Update the section mapping for multiple HPE3PAR backends + for i in range(2, constants.SERVICE_PARAM_MAX_HPE3PAR + 1): + section = "{0}{1}".format(SP_CINDER_HPE3PAR, i) + prefix = "{0}{1}".format(SP_CINDER_HPE3PAR_PREFIX, i) + SP_CINDER_SECTION_MAPPING[section] = { + SP_CONF_NAME_KEY: prefix, + SP_PARAM_PROCESS_KEY: sp_common_param_process, + SP_POST_PROCESS_KEY: sp_hpe3par_post_process, + } + def get_static_config(self): dbuser = self._get_database_username(self.SERVICE_NAME) @@ -760,6 +772,11 @@ class CinderPuppet(openstack.OpenstackBasePuppet): config, section, sp_section_map, is_service_enabled, enabled_backends) + # Build the list of possible HPE3PAR backends + possible_hpe3pars = filter( + lambda s: constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR in s, + SP_CINDER_SECTION_MAPPING.keys()) + config.update({'openstack::cinder::backends::hpe3par::sections': possible_hpe3pars}) return config def is_service_enabled(self):