def process_properties(cpc, params): """ Process the properties specified in the 'properties' module parameter, and return a dictionary (update_props) that contains the properties that can be updated. The input property values are compared with the existing resource property values and the returned set of properties is the minimal set of properties that need to be changed. - Underscores in the property names are translated into hyphens. - The presence of properties that cannot be updated is surfaced by raising ParameterError. Parameters: cpc (zhmcclient.Cpc): CPC to be updated. params (dict): Module input parameters. Returns: update_props: dict of properties for zhmcclient.Cpc.update_properties() Raises: ParameterError: An issue with the module parameters. """ input_props = params.get('properties', None) if input_props is None: input_props = {} update_props = {} for prop_name in input_props: try: allowed, create, update, update_active, eq_func, type_cast = \ ZHMC_CPC_PROPERTIES[prop_name] except KeyError: allowed = False if not allowed: raise ParameterError( "CPC property {!r} specified in the 'properties' module " "parameter cannot be updated.".format(prop_name)) # Process a normal (= non-artificial) property _create_props, _update_props, _stop = process_normal_property( prop_name, ZHMC_CPC_PROPERTIES, input_props, cpc) update_props.update(_update_props) assert not _create_props assert _stop is False return update_props
def process_properties(partition, vfunction, params): """ Process the properties specified in the 'properties' module parameter, and return two dictionaries (create_props, update_props) that contain the properties that can be created, and the properties that can be updated, respectively. If the resource exists, the input property values are compared with the existing resource property values and the returned set of properties is the minimal set of properties that need to be changed. - Underscores in the property names are translated into hyphens. - The presence of read-only properties, invalid properties (i.e. not defined in the data model for partitions), and properties that are not allowed because of restrictions or because they are auto-created from an artificial property is surfaced by raising ParameterError. - The properties resulting from handling artificial properties are added to the returned dictionaries. Parameters: partition (zhmcclient.Partition): Partition containing the virtual function. Must exist. vfunction (zhmcclient.VirtualFunction): Virtual function to be updated with the full set of current properties, or `None` if it did not previously exist. params (dict): Module input parameters. Returns: tuple of (create_props, update_props, stop), where: * create_props: dict of properties for zhmcclient.VirtualFunctionManager.create() * update_props: dict of properties for zhmcclient.VirtualFunction.update_properties() * stop (bool): Indicates whether some update properties require the partition containg the virtual function to be stopped when doing the update. Raises: ParameterError: An issue with the module parameters. """ create_props = {} update_props = {} stop = False # handle 'name' property vfunction_name = to_unicode(params['name']) create_props['name'] = vfunction_name # We looked up the virtual function by name, so we will never have to # update its name # Names of the artificial properties adapter_name_art_name = 'adapter_name' # handle the other properties input_props = params.get('properties', {}) if input_props is None: input_props = {} for prop_name in input_props: if prop_name not in ZHMC_VFUNCTION_PROPERTIES: raise ParameterError( "Property {!r} is not defined in the data model for " "virtual functions.".format(prop_name)) allowed, create, update, update_while_active, eq_func, type_cast = \ ZHMC_VFUNCTION_PROPERTIES[prop_name] if not allowed: raise ParameterError( "Property {!r} is not allowed in the 'properties' module " "parameter.".format(prop_name)) if prop_name == adapter_name_art_name: # Artificial properties will be processed together after this loop continue # Process a normal (= non-artificial) property _create_props, _update_props, _stop = process_normal_property( prop_name, ZHMC_VFUNCTION_PROPERTIES, input_props, vfunction) create_props.update(_create_props) update_props.update(_update_props) if _stop: stop = True # Process artificial properties if adapter_name_art_name in input_props: adapter_name = to_unicode(input_props[adapter_name_art_name]) try: adapter = partition.manager.cpc.adapters.find(name=adapter_name) except zhmcclient.NotFound: raise ParameterError( "Artificial property {!r} does not specify the name of an " "existing adapter: {!r}".format(adapter_name_art_name, adapter_name)) # Here we perform the same logic as in the property loop, just now # simplified by the knowledge about the property flags (create, update, # etc.). hmc_prop_name = 'adapter-uri' input_prop_value = adapter.uri if vfunction: if vfunction.properties.get(hmc_prop_name) != input_prop_value: update_props[hmc_prop_name] = input_prop_value else: update_props[hmc_prop_name] = input_prop_value create_props[hmc_prop_name] = input_prop_value return create_props, update_props, stop
def process_properties(cpc, partition, params): """ Process the properties specified in the 'properties' module parameter, and return two dictionaries (create_props, update_props) that contain the properties that can be created, and the properties that can be updated, respectively. If the resource exists, the input property values are compared with the existing resource property values and the returned set of properties is the minimal set of properties that need to be changed. - Underscores in the property names are translated into hyphens. - The presence of read-only properties, invalid properties (i.e. not defined in the data model for partitions), and properties that are not allowed because of restrictions or because they are auto-created from an artificial property is surfaced by raising ParameterError. - The properties resulting from handling artificial properties are added to the returned dictionaries. Parameters: cpc (zhmcclient.Cpc): CPC with the partition to be updated, and with the adapters to be used for the partition. partition (zhmcclient.Partition): Partition to be updated with the full set of current properties, or `None` if it did not previously exist. params (dict): Module input parameters. Returns: tuple of (create_props, update_props, stop, crypto_changes), where: * create_props: dict of properties for zhmcclient.PartitionManager.create() * update_props: dict of properties for zhmcclient.Partition.update_properties() * stop (bool): Indicates whether some update properties require the partition to be stopped when doing the update. * crypto_changes (tuple): Changes to the crypto configuration if any (or `None` if no changes were specified), as a tuple of: * remove_adapters: List of Adapter objects to be removed * remove_domain_indexes: List of domain indexes to be removed * add_adapters: List of Adapter objects to be added * add_domain_configs: List of domain configs to be added (dict of 'domain-index', 'access-mode') * change_domain_configs: List of domain configs for changing the access mode of existing domain indexes. Raises: ParameterError: An issue with the module parameters. """ create_props = {} update_props = {} stop = False crypto_changes = None # handle 'name' property part_name = to_unicode(params['name']) create_props['name'] = part_name # We looked up the partition by name, so we will never have to update # the partition name # handle the other properties input_props = params.get('properties', {}) if input_props is None: input_props = {} for prop_name in input_props: if prop_name not in ZHMC_PARTITION_PROPERTIES: raise ParameterError( "Property {!r} is not defined in the data model for " "partitions.".format(prop_name)) allowed, create, update, update_while_active, eq_func, type_cast = \ ZHMC_PARTITION_PROPERTIES[prop_name] if not allowed: raise ParameterError( "Property {!r} is not allowed in the 'properties' module " "parameter.".format(prop_name)) if prop_name == 'boot_storage_hba_name': # Process this artificial property if not partition: raise ParameterError( "Artificial property {!r} can only be specified when the " "partition previously exists.".format(prop_name)) if partition.hbas is None: raise ParameterError( "Artificial property {!r} can only be specified when the " "'dpm-storage-management' feature is disabled.". format(prop_name)) hba_name = input_props[prop_name] if type_cast: hba_name = type_cast(hba_name) try: hba = partition.hbas.find(name=hba_name) except zhmcclient.NotFound: raise ParameterError( "Artificial property {!r} does not name an existing HBA: " "{!r}".format(prop_name, hba_name)) hmc_prop_name = 'boot-storage-device' if partition.properties.get(hmc_prop_name) != hba.uri: update_props[hmc_prop_name] = hba.uri assert update_while_active elif prop_name == 'boot_network_nic_name': # Process this artificial property if not partition: raise ParameterError( "Artificial property {!r} can only be specified when the " "partition previously exists.".format(prop_name)) nic_name = input_props[prop_name] if type_cast: nic_name = type_cast(nic_name) try: nic = partition.nics.find(name=nic_name) except zhmcclient.NotFound: raise ParameterError( "Artificial property {!r} does not name an existing NIC: " "{!r}".format(prop_name, nic_name)) hmc_prop_name = 'boot-network-device' if partition.properties.get(hmc_prop_name) != nic.uri: update_props[hmc_prop_name] = nic.uri assert update_while_active elif prop_name == 'crypto_configuration': # Process this artificial property crypto_config = input_props[prop_name] if not isinstance(crypto_config, dict): raise ParameterError( "Artificial property {!r} is not a dictionary: {!r}.". format(prop_name, crypto_config)) if partition: hmc_prop_name = 'crypto-configuration' current_crypto_config = partition.properties.get(hmc_prop_name) else: current_crypto_config = None # Determine adapter changes try: adapter_field_name = 'crypto_adapter_names' adapter_names = crypto_config[adapter_field_name] except KeyError: raise ParameterError( "Artificial property {!r} does not have required field " "{!r}.".format(prop_name, adapter_field_name)) adapter_uris = set() adapter_dict = {} # adapters by uri if adapter_names is None: # Default: Use all crypto adapters of the CPC adapters = cpc.adapters.findall(type='crypto') for adapter in adapters: adapter_dict[adapter.uri] = adapter adapter_uris.add(adapter.uri) else: for adapter_name in adapter_names: try: adapter = cpc.adapters.find(name=adapter_name, type='crypto') except zhmcclient.NotFound: raise ParameterError( "Artificial property {!r} does not specify the " "name of an existing crypto adapter in its {!r} " "field: {!r}". format(prop_name, adapter_field_name, adapter_name)) adapter_dict[adapter.uri] = adapter adapter_uris.add(adapter.uri) if current_crypto_config: current_adapter_uris = set( current_crypto_config['crypto-adapter-uris']) else: current_adapter_uris = set() if adapter_uris != current_adapter_uris: add_adapter_uris = adapter_uris - current_adapter_uris # Result: List of adapters to be added: add_adapters = [adapter_dict[uri] for uri in add_adapter_uris] remove_adapter_uris = current_adapter_uris - adapter_uris for uri in remove_adapter_uris: adapter = cpc.adapters.find(**{'object-uri': uri}) # We assume the current crypto config lists only valid URIs adapter_dict[adapter.uri] = adapter # Result: List of adapters to be removed: remove_adapters = \ [adapter_dict[uri] for uri in remove_adapter_uris] else: # Result: List of adapters to be added: add_adapters = [] # Result: List of adapters to be removed: remove_adapters = [] # Determine domain config changes. try: config_field_name = 'crypto_domain_configurations' domain_configs = crypto_config[config_field_name] except KeyError: raise ParameterError( "Artificial property {!r} does not have required field " "{!r}.".format(prop_name, config_field_name)) di_field_name = 'domain_index' am_field_name = 'access_mode' domain_indexes = set() for dc in domain_configs: try: # Convert to integer in case the domain index is provided # as a string: domain_index = int(dc[di_field_name]) except KeyError: raise ParameterError( "Artificial property {!r} does not have required " "sub-field {!r} in one of its {!r} fields.". format(prop_name, di_field_name, config_field_name)) domain_indexes.add(domain_index) current_access_mode_dict = {} # dict: acc.mode by dom.index if current_crypto_config: current_domain_configs = \ current_crypto_config['crypto-domain-configurations'] di_prop_name = 'domain-index' am_prop_name = 'access-mode' for dc in current_domain_configs: # Here the domain index is always an integer because it is # returned from the HMC that way, so no type cast needed. current_access_mode_dict[dc[di_prop_name]] = \ dc[am_prop_name] current_domain_indexes = \ set([di for di in current_access_mode_dict]) # Result: List of domain indexes to be removed: remove_domain_indexes = \ list(current_domain_indexes - domain_indexes) # Building result: List of domain configs to be added: add_domain_configs = [] # Building result: List of domain configs to be changed: change_domain_configs = [] for dc in domain_configs: # Convert to integer in case the domain index is provided # as a string: domain_index = int(dc[di_field_name]) try: access_mode = dc[am_field_name] except KeyError: raise ParameterError( "Artificial property {!r} does not have required " "sub-field {!r} in one of its {!r} fields.". format(prop_name, am_field_name, config_field_name)) hmc_domain_config = { 'domain-index': domain_index, 'access-mode': access_mode, } if domain_index not in current_access_mode_dict: # Domain is not included yet add_domain_configs.append(hmc_domain_config) elif access_mode != current_access_mode_dict[domain_index]: # Domain is included but access mode needs to be changed change_domain_configs.append(hmc_domain_config) crypto_changes = (remove_adapters, remove_domain_indexes, add_adapters, add_domain_configs, change_domain_configs) else: # Process a normal (= non-artificial) property if prop_name == 'ssc_ipv4_gateway': # Undo conversion from None to empty string in Ansible if input_props[prop_name] == '': input_props[prop_name] = None _create_props, _update_props, _stop = process_normal_property( prop_name, ZHMC_PARTITION_PROPERTIES, input_props, partition) create_props.update(_create_props) update_props.update(_update_props) if _stop: stop = True return create_props, update_props, stop, crypto_changes
def process_properties(console, user, params): """ Process the properties specified in the 'properties' module parameter, and return two dictionaries (create_props, update_props) that contain the properties that can be created, and the properties that can be updated, respectively. If the resource exists, the input property values are compared with the existing resource property values and the returned set of properties is the minimal set of properties that need to be changed. - Underscores in the property names are translated into hyphens. - The presence of read-only properties, invalid properties (i.e. not defined in the data model for users), and properties that are not allowed because of restrictions or because they are auto-created from an artificial property is surfaced by raising ParameterError. Parameters: user (zhmcclient.User): User object to be updated with the full set of current properties, or `None` if it did not previously exist. params (dict): Module input parameters. Returns: tuple of (create_props, update_props), where: * create_props: dict of properties for zhmcclient.UserManager.create() * update_props: dict of properties for zhmcclient.User.update_properties() Raises: ParameterError: An issue with the module parameters. """ create_props = {} update_props = {} # handle 'name' property user_name = to_unicode(params['name']) if user is None: # User does not exist yet. create_props['name'] = user_name else: # User does already exist. # We looked up the user by name, so we will never have to # update the user name. pass # handle the other properties input_props = params.get('properties', None) if input_props is None: input_props = {} # Check required input properties for prop_name in ('type', 'authentication_type'): if prop_name not in input_props: raise ParameterError( "Property {!r} is required but is missing in the module " "input parameters.".format(prop_name)) auth_type = input_props['authentication_type'] if auth_type == 'local': for prop_name in ('password_rule_name', 'password'): if prop_name not in input_props: raise ParameterError( "Property {!r} is required for " "authentication_type='local' but is missing in the " "module input parameters.".format(prop_name)) if auth_type == 'ldap': for prop_name in ('ldap_server_definition_name', ): if prop_name not in input_props: raise ParameterError( "Property {!r} is required for " "authentication_type='ldap' but is missing in the " "module input parameters.".format(prop_name)) for prop_name in input_props: if prop_name not in ZHMC_USER_PROPERTIES: raise ParameterError( "Property {!r} is not defined in the data model for " "users.".format(prop_name)) allowed, create, update, update_while_active, eq_func, type_cast = \ ZHMC_USER_PROPERTIES[prop_name] if not allowed: raise ParameterError( "Property {!r} is not allowed in the 'properties' module " "parameter.".format(prop_name)) # Process artificial properties allowed in input parameters if prop_name == 'user_pattern_name': user_pattern_name = input_props[prop_name] if user_pattern_name: user_pattern = console.user_patterns.find_by_name( user_pattern_name) user_pattern_uri = user_pattern.uri else: user_pattern_uri = None if user is None: create_props['user-pattern-uri'] = user_pattern_uri elif user.prop('user-pattern-uri') != user_pattern_uri: update_props['user-pattern-uri'] = user_pattern_uri continue if prop_name == 'password_rule_name': password_rule_name = input_props[prop_name] if password_rule_name: password_rule = console.password_rules.find_by_name( password_rule_name) password_rule_uri = password_rule.uri else: password_rule_uri = None if user is None: create_props['password-rule-uri'] = password_rule_uri elif user.prop('password-rule-uri') != password_rule_uri: update_props['password-rule-uri'] = password_rule_uri continue if prop_name == 'ldap_server_definition_name': ldap_srv_def_name = input_props[prop_name] if ldap_srv_def_name: ldap_srv_def = console.ldap_server_definitions.find_by_name( ldap_srv_def_name) ldap_srv_def_uri = ldap_srv_def.uri else: ldap_srv_def_uri = None if user is None: create_props['ldap-server-definition-uri'] = ldap_srv_def_uri elif user.prop('ldap-server-definition-uri') != ldap_srv_def_uri: update_props['ldap-server-definition-uri'] = ldap_srv_def_uri continue if prop_name == 'default_group_name': default_group_name = input_props[prop_name] # TODO: Add support for Group objects to zhmcclient # default_group = console.groups.find_by_name(default_group_name) default_group_uri = 'fake-uri-{}'.format(default_group_name) if user is None: create_props['default-group-uri'] = default_group_uri elif user.prop('default-group-uri') != default_group_uri: update_props['default-group-uri'] = default_group_uri continue # Process a normal (= non-artificial) property _create_props, _update_props, _stop = process_normal_property( prop_name, ZHMC_USER_PROPERTIES, input_props, user) create_props.update(_create_props) update_props.update(_update_props) assert _stop is False return create_props, update_props
def process_properties(partition, hba, params): """ Process the properties specified in the 'properties' module parameter, and return two dictionaries (create_props, update_props) that contain the properties that can be created, and the properties that can be updated, respectively. If the resource exists, the input property values are compared with the existing resource property values and the returned set of properties is the minimal set of properties that need to be changed. - Underscores in the property names are translated into hyphens. - The presence of read-only properties, invalid properties (i.e. not defined in the data model for partitions), and properties that are not allowed because of restrictions or because they are auto-created from an artificial property is surfaced by raising ParameterError. - The properties resulting from handling artificial properties are added to the returned dictionaries. Parameters: partition (zhmcclient.Partition): Partition containing the HBA. Must exist. hba (zhmcclient.Hba): HBA to be updated with the full set of current properties, or `None` if it did not previously exist. params (dict): Module input parameters. Returns: tuple of (create_props, update_props, stop), where: * create_props: dict of properties for zhmcclient.HbaManager.create() * update_props: dict of properties for zhmcclient.Hba.update_properties() * stop (bool): Indicates whether some update properties require the partition containg the HBA to be stopped when doing the update. Raises: ParameterError: An issue with the module parameters. """ create_props = {} update_props = {} stop = False # handle 'name' property hba_name = to_unicode(params['name']) create_props['name'] = hba_name # We looked up the HBA by name, so we will never have to update its name # Names of the artificial properties adapter_name_art_name = 'adapter_name' adapter_port_art_name = 'adapter_port' # handle the other properties input_props = params.get('properties', {}) if input_props is None: input_props = {} for prop_name in input_props: if prop_name not in ZHMC_HBA_PROPERTIES: raise ParameterError( "Property {!r} is not defined in the data model for " "HBAs.".format(prop_name)) allowed, create, update, update_while_active, eq_func, type_cast = \ ZHMC_HBA_PROPERTIES[prop_name] if not allowed: raise ParameterError( "Property {!r} is not allowed in the 'properties' module " "parameter.".format(prop_name)) if prop_name in (adapter_name_art_name, adapter_port_art_name): # Artificial properties will be processed together after this loop continue # Process a normal (= non-artificial) property _create_props, _update_props, _stop = process_normal_property( prop_name, ZHMC_HBA_PROPERTIES, input_props, hba) create_props.update(_create_props) update_props.update(_update_props) if _stop: stop = True # Process artificial properties if (adapter_name_art_name in input_props) != \ (adapter_port_art_name in input_props): raise ParameterError( "Artificial properties {!r} and {!r} must either both be " "specified or both be omitted.".format(adapter_name_art_name, adapter_port_art_name)) if adapter_name_art_name in input_props and \ adapter_port_art_name in input_props: adapter_name = to_unicode(input_props[adapter_name_art_name]) adapter_port_index = int(input_props[adapter_port_art_name]) try: adapter = partition.manager.cpc.adapters.find(name=adapter_name) except zhmcclient.NotFound: raise ParameterError( "Artificial property {!r} does not specify the name of an " "existing adapter: {!r}".format(adapter_name_art_name, adapter_name)) try: port = adapter.ports.find(index=adapter_port_index) except zhmcclient.NotFound: raise ParameterError( "Artificial property {!r} does not specify the index of an " "existing port on adapter {!r}: {!r}".format( adapter_port_art_name, adapter_name, adapter_port_index)) hmc_prop_name = 'adapter-port-uri' if hba: existing_port_uri = hba.get_property(hmc_prop_name) if port.uri != existing_port_uri: raise ParameterError( "Artificial properties {!r} and {!r} cannot be used to " "change the adapter port of an existing HBA".format( adapter_name_art_name, adapter_port_art_name)) create_props[hmc_prop_name] = port.uri return create_props, update_props, stop
def process_properties(partition, nic, params): """ Process the properties specified in the 'properties' module parameter, and return two dictionaries (create_props, update_props) that contain the properties that can be created, and the properties that can be updated, respectively. If the resource exists, the input property values are compared with the existing resource property values and the returned set of properties is the minimal set of properties that need to be changed. - Underscores in the property names are translated into hyphens. - The presence of read-only properties, invalid properties (i.e. not defined in the data model for partitions), and properties that are not allowed because of restrictions or because they are auto-created from an artificial property is surfaced by raising ParameterError. - The properties resulting from handling artificial properties are added to the returned dictionaries. Parameters: partition (zhmcclient.Partition): Partition containing the NIC. Must exist. nic (zhmcclient.Nic): NIC to be updated with the full set of current properties, or `None` if it did not previously exist. params (dict): Module input parameters. Returns: tuple of (create_props, update_props, stop), where: * create_props: dict of properties for zhmcclient.NicManager.create() * update_props: dict of properties for zhmcclient.Nic.update_properties() * stop (bool): Indicates whether some update properties require the partition containg the NIC to be stopped when doing the update. Raises: ParameterError: An issue with the module parameters. """ create_props = {} update_props = {} stop = False # handle 'name' property nic_name = to_unicode(params['name']) create_props['name'] = nic_name # We looked up the NIC by name, so we will never have to update its name # Names of the artificial properties adapter_name_art_name = 'adapter_name' adapter_port_art_name = 'adapter_port' # handle the other properties input_props = params.get('properties', {}) if input_props is None: input_props = {} for prop_name in input_props: if prop_name not in ZHMC_NIC_PROPERTIES: raise ParameterError( "Property {!r} is not defined in the data model for " "NICs.".format(prop_name)) allowed, create, update, update_while_active, eq_func, type_cast = \ ZHMC_NIC_PROPERTIES[prop_name] if not allowed: raise ParameterError( "Property {!r} is not allowed in the 'properties' module " "parameter.".format(prop_name)) if prop_name in (adapter_name_art_name, adapter_port_art_name): # Artificial properties will be processed together after this loop continue # Process a normal (= non-artificial) property _create_props, _update_props, _stop = process_normal_property( prop_name, ZHMC_NIC_PROPERTIES, input_props, nic) create_props.update(_create_props) update_props.update(_update_props) if _stop: stop = True # Process artificial properties if (adapter_name_art_name in input_props) != \ (adapter_port_art_name in input_props): raise ParameterError( "Artificial properties {!r} and {!r} must either both be " "specified or both be omitted.".format(adapter_name_art_name, adapter_port_art_name)) if adapter_name_art_name in input_props and \ adapter_port_art_name in input_props: adapter_name = to_unicode(input_props[adapter_name_art_name]) adapter_port_index = int(input_props[adapter_port_art_name]) try: adapter = partition.manager.cpc.adapters.find(name=adapter_name) except zhmcclient.NotFound: raise ParameterError( "Artificial property {!r} does not specify the name of an " "existing adapter: {!r}".format(adapter_name_art_name, adapter_name)) try: port = adapter.ports.find(index=adapter_port_index) except zhmcclient.NotFound: raise ParameterError( "Artificial property {!r} does not specify the index of an " "existing port on adapter {!r}: {!r}".format( adapter_port_art_name, adapter_name, adapter_port_index)) # The rest of it depends on the network adapter family: adapter_family = adapter.get_property('adapter-family') if adapter_family == 'roce': # Here we perform the same logic as in the property loop, just now # simplified by the knowledge about the property flags (create, # update, etc.). hmc_prop_name = 'network-adapter-port-uri' input_prop_value = port.uri if nic: if nic.properties.get(hmc_prop_name) != input_prop_value: update_props[hmc_prop_name] = input_prop_value else: update_props[hmc_prop_name] = input_prop_value create_props[hmc_prop_name] = input_prop_value elif adapter_family in ('osa', 'hipersockets'): vswitches = partition.manager.cpc.virtual_switches.findall( **{'backing-adapter-uri': adapter.uri}) # Adapters of this family always have a vswitch (one for each # port), so we assert that we can find one or more: assert vswitches found_vswitch = None for vswitch in vswitches: if vswitch.get_property('port') == adapter_port_index: found_vswitch = vswitch break # Because we already checked for the existence of the specified # port index, we can now assert that we found the vswitch for that # port: assert found_vswitch # Here we perform the same logic as in the property loop, just now # simplified by the knowledge about the property flags (create, # update, etc.). hmc_prop_name = 'virtual-switch-uri' input_prop_value = found_vswitch.uri if nic: if nic.properties.get(hmc_prop_name) != input_prop_value: update_props[hmc_prop_name] = input_prop_value else: update_props[hmc_prop_name] = input_prop_value create_props[hmc_prop_name] = input_prop_value else: raise ParameterError( "Artificial property {!r} specifies the name of a non-network " "adapter of family {!r}: {!r}".format(adapter_name_art_name, adapter_family, adapter_name)) return create_props, update_props, stop
def process_properties(cpc, storage_group, params): """ Process the properties specified in the 'properties' module parameter, and return two dictionaries (create_props, update_props) that contain the properties that can be created, and the properties that can be updated, respectively. If the resource exists, the input property values are compared with the existing resource property values and the returned set of properties is the minimal set of properties that need to be changed. - Underscores in the property names are translated into hyphens. - The presence of read-only properties, invalid properties (i.e. not defined in the data model for storage groups), and properties that are not allowed because of restrictions or because they are auto-created from an artificial property is surfaced by raising ParameterError. - The properties resulting from handling artificial properties are added to the returned dictionaries. Parameters: cpc (zhmcclient.Cpc): CPC with the partition to be updated, and with the adapters to be used for the partition. storage_group (zhmcclient.StorageGroup): Storage group object to be updated with the full set of current properties, or `None` if it did not previously exist. params (dict): Module input parameters. Returns: tuple of (create_props, update_props), where: * create_props: dict of properties for zhmcclient.StorageGroupManager.create() * update_props: dict of properties for zhmcclient.StorageGroup.update_properties() Raises: ParameterError: An issue with the module parameters. """ create_props = {} update_props = {} # handle 'name' and 'cpc-uri' properties. sg_name = to_unicode(params['name']) if storage_group is None: # SG does not exist yet. create_props['name'] = sg_name create_props['cpc-uri'] = cpc.uri else: # SG does already exist. # We looked up the storage group by name, so we will never have to # update the storage group name. # Updates to the associated CPC are not possible. sg_cpc = storage_group.cpc if sg_cpc.uri != cpc.uri: raise ParameterError( "Storage group {!r} is not associated with the specified " "CPC %r, but with CPC %r.".format(sg_name, cpc.name, sg_cpc.name)) # handle the other properties input_props = params.get('properties', None) if input_props is None: input_props = {} for prop_name in input_props: if prop_name not in ZHMC_STORAGE_GROUP_PROPERTIES: raise ParameterError( "Property {!r} is not defined in the data model for " "storage groups.".format(prop_name)) allowed, create, update, update_while_active, eq_func, type_cast = \ ZHMC_STORAGE_GROUP_PROPERTIES[prop_name] if not allowed: raise ParameterError( "Property {!r} is not allowed in the 'properties' module " "parameter.".format(prop_name)) # Process a normal (= non-artificial) property _create_props, _update_props, _stop = process_normal_property( prop_name, ZHMC_STORAGE_GROUP_PROPERTIES, input_props, storage_group) create_props.update(_create_props) update_props.update(_update_props) assert _stop is False return create_props, update_props
def process_properties(adapter, params): """ Process the properties specified in the 'properties' module parameter, and return a dictionary (update_props) that contains the properties that can be updated. The input property values are compared with the existing resource property values and the returned set of properties is the minimal set of properties that need to be changed. - Underscores in the property names are translated into hyphens. - The presence of properties that cannot be updated is surfaced by raising ParameterError. Parameters: adapter (zhmcclient.Adapter): Existing adapter to be updated, or `None` if the adapter does not exist. params (dict): Module input parameters. Returns: tuple of (create_props, update_props), where: * create_props: dict of properties from params that may be specified in zhmcclient.AdapterManager.create_hipersocket() (may overlap with update_props). * update_props: dict of properties from params that may be specified in zhmcclient.Adapter.update_properties() (may overlap with create_props). * change_adapter_type: String with new adapter type (i.e. input for Change Adapter Type operation), or None if no change needed. * change_crypto_type: String with new crypto type (i.e. input for Change Crypto Type operation), or None if no change needed. Raises: ParameterError: An issue with the module parameters. """ # Prepare return values create_props = {} update_props = {} change_adapter_type = None # New adapter type, if needed change_crypto_type = None # New crypto type, if needed # handle the 'name' module parameter adapter_name = to_unicode(params['name']) if adapter and adapter.properties.get('name', None) == adapter_name: pass # adapter exists and has the desired name else: create_props['name'] = adapter_name update_props['name'] = adapter_name # handle the other input properties input_props = params.get('properties', None) if input_props is None: input_props = {} for prop_name in input_props: try: allowed, create, update, update_active, eq_func, type_cast = \ ZHMC_ADAPTER_PROPERTIES[prop_name] except KeyError: allowed = False if not allowed: raise ParameterError( "Invalid adapter property {!r} specified in the 'properties' " "module parameter.".format(prop_name)) if prop_name == 'type': # Determine need to change the adapter type _current_adapter_type = adapter.properties.get('type', None) _input_adapter_type = input_props[prop_name] if _input_adapter_type != _current_adapter_type: change_adapter_type = _input_adapter_type elif prop_name == 'crypto_type': # Determine need to change the crypto type _current_crypto_type = adapter.properties.get('crypto-type', None) _input_crypto_type = CRYPTO_TYPES_MOD2HMC[input_props[prop_name]] if _input_crypto_type != _current_crypto_type: change_crypto_type = _input_crypto_type else: # Process a normal (= non-artificial) property _create_props, _update_props, _stop = process_normal_property( prop_name, ZHMC_ADAPTER_PROPERTIES, input_props, adapter) create_props.update(_create_props) update_props.update(_update_props) assert _stop is False return create_props, update_props, change_adapter_type, change_crypto_type