def facts(params, check_mode): """ Return facts about the crypto configuration of the partition. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] partition_name = params['partition_name'] faked_session = params.get('faked_session', None) # No default specified try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) partition = cpc.partitions.find(name=partition_name) # The default exception handling is sufficient for the above. # Determine all crypto adapters of any crypto type filter_args = { 'adapter-family': 'crypto', } all_adapters = cpc.adapters.list(filter_args=filter_args, full_properties=True) result = get_partition_config(partition, all_adapters) return False, result, None finally: session.logoff()
def facts(params, check_mode): """ Identify the target CPC and return facts about the target CPC and its child resources. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['name'] faked_session = params.get('faked_session', None) # No default specified try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) # The default exception handling is sufficient for the above. cpc.pull_full_properties() result = cpc.properties partitions = cpc.partitions.list() adapters = cpc.adapters.list() result['partitions'] = [p.properties for p in partitions] result['adapters'] = [a.properties for a in adapters] return False, result finally: session.logoff()
def ensure_absent(params, check_mode): """ Ensure that the storage volume does not exist. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] storage_group_name = params['storage_group_name'] storage_volume_name = params['name'] faked_session = params.get('faked_session', None) changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) console = client.consoles.console cpc = client.cpcs.find(name=cpc_name) storage_group = console.storage_groups.find(name=storage_group_name) # The default exception handling is sufficient for the above. 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(storage_group_name, cpc.name, sg_cpc.name)) try: storage_volume = storage_group.storage_volumes.find( name=storage_volume_name) except zhmcclient.NotFound: return changed, result except zhmcclient.NoUniqueMatch: # The name of storage volumes within their storage group is not # enforced to be unique. raise if not check_mode: storage_volume.delete() changed = True return changed, result finally: session.logoff()
def ensure_absent(params, check_mode): """ Ensure that the storage group does not exist. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] storage_group_name = params['name'] faked_session = params.get('faked_session', None) changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) console = client.consoles.console cpc = client.cpcs.find(name=cpc_name) # The default exception handling is sufficient for the above. try: storage_group = console.storage_groups.find( name=storage_group_name) except zhmcclient.NotFound: return changed, result 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(storage_group_name, cpc.name, sg_cpc.name)) if not check_mode: partitions = storage_group.list_attached_partitions() for part in partitions: # This will raise HTTPError(409) if the partition is in one of # the transitional states ('starting', 'stopping'). part.detach_storage_group(storage_group) storage_group.delete() changed = True return changed, result finally: session.logoff()
def facts(params, check_mode): """ Return partition facts. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] partition_name = params['name'] faked_session = params.get('faked_session', None) changed = False result = {} try: # The default exception handling is sufficient for this code session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) partition = cpc.partitions.find(name=partition_name) partition.pull_full_properties() # Get the child elements of the partition hbas_prop = list() if partition.hbas is not None: for hba in partition.hbas.list(full_properties=True): hbas_prop.append(hba.properties) partition.properties['hbas'] = hbas_prop nics_prop = list() for nic in partition.nics.list(full_properties=True): nics_prop.append(nic.properties) partition.properties['nics'] = nics_prop vf_prop = list() for vf in partition.virtual_functions.list(full_properties=True): vf_prop.append(vf.properties) partition.properties['virtual-functions'] = vf_prop result = partition.properties return changed, result finally: session.logoff()
def ensure_detached(params, check_mode): """ Ensure that the storage group is detached from the partition. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] storage_group_name = params['storage_group_name'] partition_name = params['partition_name'] faked_session = params.get('faked_session', None) changed = False attached = None try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) console = client.consoles.console cpc = client.cpcs.find(name=cpc_name) storage_group = console.storage_groups.find(name=storage_group_name) partition = cpc.partitions.find(name=partition_name) # The default exception handling is sufficient for the above. attached_partitions = storage_group.list_attached_partitions( name=partition_name) if attached_partitions: # The storage group is attached to the partition assert len(attached_partitions) == 1 assert attached_partitions[0].name == partition_name attached = True if not check_mode: partition.detach_storage_group(storage_group) attached = False changed = True else: # The storage group is already detached from the partition attached = False result = dict(attached=attached) return changed, result finally: session.logoff()
def ensure_set(params, check_mode): """ Identify the target CPC and ensure that the specified properties are set on the target CPC. Raises: ParameterError: An issue with the module parameters. Error: Other errors during processing. zhmcclient.Error: Any zhmcclient exception can happen. """ # Note: Defaults specified in argument_spec will be set in params dict host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['name'] faked_session = params.get('faked_session', None) # No default specified changed = False try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) # The default exception handling is sufficient for the above. cpc.pull_full_properties() result = cpc.properties update_props = process_properties(cpc, params) if update_props: if not check_mode: cpc.update_properties(update_props) # Some updates of CPC properties are not reflected in a new # retrieval of properties until after a few seconds (usually the # second retrieval). # Therefore, we construct the modified result based upon the input # changes, and not based upon newly retrieved properties. result.update(update_props) changed = True partitions = cpc.partitions.list() adapters = cpc.adapters.list() result['partitions'] = [p.properties for p in partitions] result['adapters'] = [a.properties for a in adapters] return changed, result finally: session.logoff()
def facts(params, check_mode): """ Return facts about a storage group and its storage volumes and virtual storage resources. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] storage_group_name = params['name'] expand = params['expand'] faked_session = params.get('faked_session', None) changed = False result = {} try: # The default exception handling is sufficient for this code session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) console = client.consoles.console cpc = client.cpcs.find(name=cpc_name) storage_group = console.storage_groups.find(name=storage_group_name) storage_group.pull_full_properties() 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(storage_group_name, cpc.name, sg_cpc.name)) add_artificial_properties(storage_group, expand) result = storage_group.properties return changed, result finally: session.logoff()
def ensure_absent(params, check_mode): """ Ensure that the virtual function does not exist. Raises: ParameterError: An issue with the module parameters. StatusError: An issue with the partition status. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] partition_name = params['partition_name'] vfunction_name = params['name'] faked_session = params.get('faked_session', None) changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) partition = cpc.partitions.find(name=partition_name) # The default exception handling is sufficient for the above. try: vfunction = partition.virtual_functions.find(name=vfunction_name) except zhmcclient.NotFound: return changed, result if not check_mode: vfunction.delete() changed = True return changed, result finally: session.logoff()
def ensure_absent(params, check_mode): """ Ensure that the specified Hipersockets adapter does not exist. Raises: ParameterError: An issue with the module parameters. Error: Other errors during processing. zhmcclient.Error: Any zhmcclient exception can happen. """ # Note: Defaults specified in argument_spec will be set in params dict host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] adapter_name = params['name'] faked_session = params.get('faked_session', None) # No default specified changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) # The default exception handling is sufficient for the above. try: adapter = cpc.adapters.find(name=adapter_name) except zhmcclient.NotFound: return changed, result if not check_mode: adapter.delete() changed = True return changed, result finally: session.logoff()
def facts(params, check_mode): """ Return facts about a user and its storage volumes and virtual storage resources. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) user_name = params['name'] expand = params['expand'] faked_session = params.get('faked_session', None) changed = False result = {} try: # The default exception handling is sufficient for this code session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) console = client.consoles.console user = console.users.find(name=user_name) user.pull_full_properties() add_artificial_properties(console, user, expand, check_mode) result = user.properties return changed, result finally: session.logoff()
def ensure_absent(params, check_mode): """ Ensure that the user does not exist. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) user_name = params['name'] faked_session = params.get('faked_session', None) changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) console = client.consoles.console # The default exception handling is sufficient for the above. try: user = console.users.find(name=user_name) except zhmcclient.NotFound: return changed, result if not check_mode: user.delete() changed = True return changed, result finally: session.logoff()
def ensure_set(params, check_mode): """ Identify the target adapter (that must exist) and ensure that the specified properties are set on the adapter. Raises: ParameterError: An issue with the module parameters. Error: Other errors during processing. zhmcclient.Error: Any zhmcclient exception can happen. """ # Note: Defaults specified in argument_spec will be set in params dict host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] adapter_name = params['name'] adapter_match = params['match'] faked_session = params.get('faked_session', None) # No default specified changed = False try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) adapter = identify_adapter(cpc, adapter_name, adapter_match) # The default exception handling is sufficient for the above. adapter.pull_full_properties() result = adapter.properties # It was identified by name or match properties, so it does exist. # Update its properties and change adapter and crypto type, if # needed. create_props, update_props, chg_adapter_type, chg_crypto_type = \ process_properties(adapter, params) if update_props: if not check_mode: adapter.update_properties(update_props) else: result.update(update_props) # from input values changed = True if chg_adapter_type: if not check_mode: adapter.change_adapter_type(chg_adapter_type) else: result['type'] = chg_adapter_type changed = True if chg_crypto_type: if not check_mode: adapter.change_crypto_type(chg_crypto_type) else: result['crypto-type'] = chg_crypto_type changed = True if changed and not check_mode: adapter.pull_full_properties() result = adapter.properties # from actual values ports = adapter.ports.list() result_ports = list() for port in ports: # TODO: Disabling the following line mitigates the recent issue # with HTTP error 404,4 when retrieving port properties. # port.pull_full_properties() result_ports.append(port.properties) result['ports'] = result_ports return changed, result finally: session.logoff()
def ensure_present(params, check_mode): """ Ensure that the specified Hipersockets adapter exists and has the specified properties set. Raises: ParameterError: An issue with the module parameters. Error: Other errors during processing. zhmcclient.Error: Any zhmcclient exception can happen. """ # Note: Defaults specified in argument_spec will be set in params dict host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] adapter_name = params['name'] faked_session = params.get('faked_session', None) # No default specified changed = False try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) # The default exception handling is sufficient for the above. try: adapter = cpc.adapters.find(name=adapter_name) except zhmcclient.NotFound: adapter = None if not adapter: # It does not exist. The only possible adapter type # that can be created is a Hipersockets adapter, but before # creating one we check the 'type' input property to verify that # the intention is really Hipersockets creation, and not just a # mispelled name. input_props = params.get('properties', None) if input_props is None: adapter_type = None else: adapter_type = input_props.get('type', None) if adapter_type is None: raise ParameterError( "Input property 'type' missing when creating " "Hipersockets adapter {!r} (must specify 'hipersockets')". format(adapter_name)) if adapter_type != 'hipersockets': raise ParameterError( "Input property 'type' specifies {!r} when creating " "Hipersockets adapter {!r} (must specify 'hipersockets').". format(adapter_type, adapter_name)) create_props, update_props = process_properties(adapter, params) # This is specific to Hipersockets: There are no update-only # properties, so any remaining such property is an input error invalid_update_props = {} for name in update_props: if name not in create_props: invalid_update_props[name] = update_props[name] if invalid_update_props: raise ParameterError( "Invalid input properties specified when creating " "Hipersockets adapter {!r}: {!r}".format( adapter_name, invalid_update_props)) # While the 'type' input property is required for verifying # the intention, it is not allowed as input for the # Create Hipersocket HMC operation. del create_props['type'] if not check_mode: adapter = cpc.adapters.create_hipersocket(create_props) adapter.pull_full_properties() result = adapter.properties # from actual values else: adapter = None result = dict() result.update(create_props) # from input values changed = True else: # It does exist. # Update its properties and change adapter and crypto type, if # needed. adapter.pull_full_properties() result = adapter.properties create_props, update_props, chg_adapter_type, chg_crypto_type = \ process_properties(adapter, params) if update_props: if not check_mode: adapter.update_properties(update_props) else: result.update(update_props) # from input values changed = True if chg_adapter_type: if not check_mode: adapter.change_adapter_type(chg_adapter_type) else: result['type'] = chg_adapter_type changed = True if chg_crypto_type: if not check_mode: adapter.change_crypto_type(chg_crypto_type) else: result['crypto-type'] = chg_crypto_type changed = True if changed and not check_mode: adapter.pull_full_properties() result = adapter.properties # from actual values if adapter: ports = adapter.ports.list() result_ports = list() for port in ports: port.pull_full_properties() result_ports.append(port.properties) result['ports'] = result_ports else: # For now, we return no ports when creating in check mode result['ports'] = dict() return changed, result finally: session.logoff()
def ensure_stopped(params, check_mode): """ Ensure that the partition exists, is stopped, and has the specified properties. Raises: ParameterError: An issue with the module parameters. StatusError: An issue with the partition status. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] partition_name = params['name'] faked_session = params.get('faked_session', None) changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) # The default exception handling is sufficient for the above. try: partition = cpc.partitions.find(name=partition_name) partition.pull_full_properties() except zhmcclient.NotFound: partition = None if not partition: # It does not exist. Create it and update it if there are # update-only properties. if not check_mode: create_props, update_props, stop, crypto_changes = \ process_properties(cpc, partition, params) partition = cpc.partitions.create(create_props) update2_props = {} for name in update_props: if name not in create_props: update2_props[name] = update_props[name] if update2_props: partition.update_properties(update2_props) if crypto_changes: change_crypto_config(partition, crypto_changes, check_mode) changed = True else: # It exists. Stop it and update its properties. create_props, update_props, stop, crypto_changes = \ process_properties(cpc, partition, params) changed |= stop_partition(partition, check_mode) if update_props: if not check_mode: partition.update_properties(update_props) changed = True if crypto_changes: changed |= change_crypto_config(partition, crypto_changes, check_mode) if partition and not check_mode: partition.pull_full_properties() status = partition.get_property('status') if status not in ('stopped'): raise StatusError( "Could not get partition {!r} into a stopped state, " "status is: {!r}".format(partition.name, status)) if partition: result = partition.properties return changed, result finally: session.logoff()
def ensure_active(params, check_mode): """ Ensure that the partition exists, is active or degraded, and has the specified properties. Raises: ParameterError: An issue with the module parameters. StatusError: An issue with the partition status. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] partition_name = params['name'] faked_session = params.get('faked_session', None) changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) # The default exception handling is sufficient for the above. try: partition = cpc.partitions.find(name=partition_name) partition.pull_full_properties() except zhmcclient.NotFound: partition = None if not partition: # It does not exist. Create it and update it if there are # update-only properties. if not check_mode: create_props, update_props, stop, crypto_changes = \ process_properties(cpc, partition, params) partition = cpc.partitions.create(create_props) update2_props = {} for name in update_props: if name not in create_props: update2_props[name] = update_props[name] if update2_props: partition.update_properties(update2_props) # We refresh the properties after the update, in case an # input property value gets changed (for example, the # partition does that with memory properties). partition.pull_full_properties() if crypto_changes: change_crypto_config(partition, crypto_changes, check_mode) else: # TODO: Show props in module result also in check mode. pass changed = True else: # It exists. Stop if needed due to property update requirements, # or wait for an updateable partition status, and update its # properties. create_props, update_props, stop, crypto_changes = \ process_properties(cpc, partition, params) if update_props: if not check_mode: if stop: stop_partition(partition, check_mode) else: wait_for_transition_completion(partition) partition.update_properties(update_props) # We refresh the properties after the update, in case an # input property value gets changed (for example, the # partition does that with memory properties). partition.pull_full_properties() else: # TODO: Show updated props in mod.result also in chk.mode pass changed = True if crypto_changes: changed |= change_crypto_config(partition, crypto_changes, check_mode) if partition: changed |= start_partition(partition, check_mode) if partition and not check_mode: partition.pull_full_properties() status = partition.get_property('status') if status not in ('active', 'degraded'): raise StatusError( "Could not get partition {!r} into an active state, " "status is: {!r}".format(partition.name, status)) if partition: result = partition.properties return changed, result finally: session.logoff()
def ensure_detached(params, check_mode): """ Ensure that the target partition has no adapters and no domains attached. Raises: ParameterError: An issue with the module parameters. Error: Other errors during processing. zhmcclient.Error: Any zhmcclient exception can happen. """ # Note: Defaults specified in argument_spec will be set in params dict host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] partition_name = params['partition_name'] faked_session = params.get('faked_session', None) # No default specified changed = False result = dict() result_changes = dict() try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) partition = cpc.partitions.find(name=partition_name) # The default exception handling is sufficient for the above. # Determine all crypto adapters of any crypto type filter_args = { 'adapter-family': 'crypto', } all_adapters = cpc.adapters.list(filter_args=filter_args, full_properties=True) cc = partition.get_property('crypto-configuration') # The 'crypto-configuration' property is None or: # { # 'crypto-adapter-uris': ['/api/...', ...], # 'crypto-domain-configurations': [ # {'domain-index': 15, 'access-mode': 'control-usage'}, # ... # ] # } if cc: attached_adapter_uris = cc['crypto-adapter-uris'] remove_adapters = [] remove_adapter_names = [] for a in all_adapters: if a.uri in attached_adapter_uris: remove_adapters.append(a) remove_adapter_names.append(a.name) remove_domains = [] for dc in cc['crypto-domain-configurations']: di = dc['domain-index'] remove_domains.append(di) LOGGER.debug( "Detaching adapters {!r} and domains {!r} from target " "partition {!r}".format(remove_adapter_names, remove_domains, partition.name)) if not check_mode: try: partition.decrease_crypto_config(remove_adapters, remove_domains) except zhmcclient.Error as exc: raise Error( "Detaching adapters {!r} and domains {!r} from " "target partition {!r} failed: {}".format( remove_adapter_names, remove_domains, partition.name, exc)) changed = True result_changes['removed-adapters'] = remove_adapter_names result_changes['removed-domains'] = remove_domains if not check_mode: # This is not optimal because it does not produce a result # in check mode, but because the actual config is determined, # instead of the artificially calculated one, it seems better # to return no config than the unchanged actual config. result.update(get_partition_config(partition, all_adapters)) return changed, result, result_changes finally: session.logoff()
def ensure_present(params, check_mode): """ Ensure that the virtual function exists and has the specified properties. Raises: ParameterError: An issue with the module parameters. StatusError: An issue with the partition status. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] partition_name = params['partition_name'] vfunction_name = params['name'] faked_session = params.get('faked_session', None) changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) # The default exception handling is sufficient for the above. try: partition = cpc.partitions.find(name=partition_name) except zhmcclient.NotFound: if check_mode: # Once the partition is created, the virtual function will # also need to be created. Therefore, we set changed. changed = True return changed, result raise try: vfunction = partition.virtual_functions.find(name=vfunction_name) vfunction.pull_full_properties() except zhmcclient.NotFound: vfunction = None if not vfunction: # It does not exist. Create it and update it if there are # update-only properties. if not check_mode: create_props, update_props, stop = process_properties( partition, vfunction, params) vfunction = partition.virtual_functions.create(create_props) update2_props = {} for name in update_props: if name not in create_props: update2_props[name] = update_props[name] if update2_props: vfunction.update_properties(update2_props) # We refresh the properties after the update, in case an # input property value gets changed (for example, the # partition does that with memory properties). vfunction.pull_full_properties() else: # TODO: Show props in module result also in check mode. pass changed = True else: # It exists. Stop the partition if needed due to the virtual # function property update requirements, or wait for an updateable # partition status, and update the virtual function properties. create_props, update_props, stop = process_properties( partition, vfunction, params) if update_props: if not check_mode: # Virtual function properties can all be updated while the # partition is active, therefore: assert not stop wait_for_transition_completion(partition) vfunction.update_properties(update_props) # We refresh the properties after the update, in case an # input property value gets changed (for example, the # partition does that with memory properties). vfunction.pull_full_properties() else: # TODO: Show updated props in mod.result also in chk.mode pass changed = True if vfunction: result = vfunction.properties return changed, result finally: session.logoff()
def ensure_present(params, check_mode): """ Ensure that the storage volume is defined and has the specified properties. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] storage_group_name = params['storage_group_name'] storage_volume_name = params['name'] faked_session = params.get('faked_session', None) changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) console = client.consoles.console cpc = client.cpcs.find(name=cpc_name) storage_group = console.storage_groups.find(name=storage_group_name) # The default exception handling is sufficient for the above. 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(storage_group_name, cpc.name, sg_cpc.name)) try: storage_volume = storage_group.storage_volumes.find( name=storage_volume_name) except zhmcclient.NotFound: storage_volume = None except zhmcclient.NoUniqueMatch: # The name of storage volumes within their storage group is not # enforced to be unique. raise if storage_volume is None: # It does not exist. Create it and update it if there are # update-only properties. if not check_mode: create_props, update_props = \ process_properties(cpc, storage_group, storage_volume, params) storage_volume = storage_group.storage_volumes.create( create_props) update2_props = {} for name in update_props: if name not in create_props: update2_props[name] = update_props[name] if update2_props: storage_volume.update_properties(update2_props) # We refresh the properties after the update, in case an # input property value gets changed. storage_volume.pull_full_properties() else: # TODO: Show props in module result also in check mode. pass changed = True else: # It exists. Update its properties. storage_volume.pull_full_properties() create_props, update_props = \ process_properties(cpc, storage_group, storage_volume, params) assert not create_props, \ "Unexpected create_props: %r" % create_props if update_props: if not check_mode: storage_volume.update_properties(update_props) # We refresh the properties after the update, in case an # input property value gets changed. storage_volume.pull_full_properties() else: # TODO: Show updated props in mod.result also in chk.mode storage_volume.pull_full_properties() changed = True if not check_mode: assert storage_volume if storage_volume: add_artificial_properties(storage_volume) result = storage_volume.properties return changed, result finally: session.logoff()
def ensure_present(params, check_mode): """ Ensure that the storage group exists and has the specified properties. Storage volumes are not subject of this function, they are handled by the zhmc_storage_volume.py module. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] storage_group_name = params['name'] expand = params['expand'] faked_session = params.get('faked_session', None) changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) console = client.consoles.console cpc = client.cpcs.find(name=cpc_name) # The default exception handling is sufficient for the above. try: storage_group = console.storage_groups.find( name=storage_group_name) except zhmcclient.NotFound: storage_group = None if storage_group is None: # It does not exist. Create it and update it if there are # update-only properties. if not check_mode: create_props, update_props = \ process_properties(cpc, storage_group, params) storage_group = console.storage_groups.create(create_props) update2_props = {} for name in update_props: if name not in create_props: update2_props[name] = update_props[name] if update2_props: storage_group.update_properties(update2_props) # We refresh the properties after the update, in case an # input property value gets changed. storage_group.pull_full_properties() else: # TODO: Show props in module result also in check mode. pass changed = True else: # It exists. Update its properties. storage_group.pull_full_properties() create_props, update_props = \ process_properties(cpc, storage_group, params) assert not create_props, \ "Unexpected create_props: %r" % create_props if update_props: if not check_mode: storage_group.update_properties(update_props) # We refresh the properties after the update, in case an # input property value gets changed. storage_group.pull_full_properties() else: # TODO: Show updated props in mod.result also in chk.mode pass changed = True if not check_mode: assert storage_group add_artificial_properties(storage_group, expand) result = storage_group.properties return changed, result finally: session.logoff()
def ensure_present(params, check_mode): """ Ensure that the user exists and has the specified properties. Storage volumes are not subject of this function, they are handled by the zhmc_storage_volume.py module. Raises: ParameterError: An issue with the module parameters. zhmcclient.Error: Any zhmcclient exception can happen. """ host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) user_name = params['name'] expand = params['expand'] faked_session = params.get('faked_session', None) changed = False result = {} try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) console = client.consoles.console # The default exception handling is sufficient for the above. try: user = console.users.find(name=user_name) except zhmcclient.NotFound: user = None if user is None: # It does not exist. Create it and update it if there are # update-only properties. create_props, update_props = process_properties( console, user, params) update2_props = {} for name in update_props: if name not in create_props: update2_props[name] = update_props[name] if not check_mode: user = console.users.create(create_props) if update2_props: user.update_properties(update2_props) # We refresh the properties after the update, in case an # input property value gets changed. user.pull_full_properties() else: # Create a User object locally user = create_check_mode_user(console, create_props, update2_props) changed = True else: # It exists. Update its properties. user.pull_full_properties() create_props, update_props = process_properties( console, user, params) assert not create_props, \ "Unexpected create_props: %r" % create_props if update_props: LOGGER.debug( "Existing user {!r} needs to get properties updated: {!r}". format(user_name, update_props)) if not check_mode: user.update_properties(update_props) # We refresh the properties after the update, in case an # input property value gets changed. user.pull_full_properties() else: # Update the local User object's properties user.properties.update(update_props) changed = True assert user add_artificial_properties(console, user, expand, check_mode) result = user.properties return changed, result finally: session.logoff()
def ensure_attached(params, check_mode): """ Ensure that the specified crypto adapters and crypto domains are attached to the target partition. Raises: ParameterError: An issue with the module parameters. Error: Other errors during processing. zhmcclient.Error: Any zhmcclient exception can happen. """ # Note: Defaults specified in argument_spec will be set in params dict host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] partition_name = params['partition_name'] adapter_count = params['adapter_count'] domain_range = params['domain_range'] access_mode = params['access_mode'] crypto_type = params['crypto_type'] faked_session = params.get('faked_session', None) # No default specified try: assert len(domain_range) == 2, \ "len(domain_range)={}".format(len(domain_range)) domain_range_lo = int(domain_range[0]) domain_range_hi = int(domain_range[1]) except (ValueError, AssertionError): raise ParameterError( "The 'domain_range' parameter must be a list containing two " "integer numbers, but is: {!r}".format(domain_range)) hmc_crypto_type = CRYPTO_TYPES_MOD2HMC[crypto_type] hmc_access_mode = ACCESS_MODES_MOD2HMC[access_mode] changed = False result = dict() result_changes = dict() try: session = get_session(faked_session, host, userid, password) client = zhmcclient.Client(session) cpc = client.cpcs.find(name=cpc_name) partition = cpc.partitions.find(name=partition_name) # The default exception handling is sufficient for the above. # Determine all crypto adapters of the specified crypto type. filter_args = { 'adapter-family': 'crypto', 'crypto-type': hmc_crypto_type, } all_adapters = cpc.adapters.list(filter_args=filter_args, full_properties=True) if not all_adapters: raise Error( "No crypto adapters of type {!r} found on CPC {!r} ".format( crypto_type, cpc_name)) # All crypto adapters in a CPC have the same number of domains # (otherwise the concept of attaching domains across all attached # adapters cannot work). Therefore, the max number of domains can be # gathered from any adapter. max_domains = all_adapters[0].maximum_crypto_domains # Parameter checking on domain range. # (can be done only now because it requires the max_domains). if domain_range_hi == -1: domain_range_hi = max_domains - 1 if domain_range_lo > domain_range_hi: raise ParameterError( "In the 'domain_range' parameter, the lower boundary (={}) " "of the range must be less than the higher boundary (={})". format(domain_range_lo, domain_range_hi)) # Parameter checking on adapter count. # (can be done only now because it requires the number of adapters). if adapter_count == -1: adapter_count = len(all_adapters) if adapter_count < 1: raise ParameterError( "The 'adapter_count' parameter must be at least 1, but is: {}". format(adapter_count)) if adapter_count > len(all_adapters): raise ParameterError( "The 'adapter_count' parameter must not exceed the number of " "{} crypto adapters of type {!r} in CPC {!r}, but is {}". format(len(all_adapters), crypto_type, cpc_name, adapter_count)) # # Get current crypto config of the target partition. # # Domains attached to the partition, as a dict with: # key: domain index # value: access mode attached_domains = dict() # Adapters attached to the partition, as a list of Adapter objects: attached_adapters = list() # Adapters not attached to the partition, as a list of Adapter objects: detached_adapters = list() _attached_adapter_uris = list() # URIs of attached adapters cc = partition.get_property('crypto-configuration') if cc: _attached_adapter_uris = cc['crypto-adapter-uris'] for dc in cc['crypto-domain-configurations']: di = int(dc['domain-index']) am = dc['access-mode'] LOGGER.debug("Crypto config of partition {!r}: " "Domain {} is attached in {!r} mode".format( partition.name, di, am)) attached_domains[di] = am for a in all_adapters: if a.uri in _attached_adapter_uris: LOGGER.debug("Crypto config of partition {!r}: " "Adapter {!r} is attached".format( partition.name, a.name)) attached_adapters.append(a) else: LOGGER.debug("Crypto config of partition {!r}: " "Adapter {!r} is not attached".format( partition.name, a.name)) detached_adapters.append(a) del _attached_adapter_uris # # Get the current crypto config of all partitions of the CPC. # # This is needed because finding out whether an adapter has the right # domains available by simply attaching it to the target partition # and reacting to the returned status does not work for stopped # partitions. # # All partition of the CPC, as a dict: # key: partition URI # value: Partition object all_partitions = cpc.partitions.list() all_partitions = dict( zip([p.uri for p in all_partitions], all_partitions)) # Crypto config of all partitions of the CPC, as a dict with: # key: adapter URI # value: dict: # key: domain index (for attached domains) # value: list of tuple(access mode, partition URI) all_crypto_config = dict() for p_uri in all_partitions: p = all_partitions[p_uri] cc = p.get_property('crypto-configuration') # The 'crypto-configuration' property is None or: # { # 'crypto-adapter-uris': ['/api/...', ...], # 'crypto-domain-configurations': [ # {'domain-index': 15, 'access-mode': 'control-usage'}, # ... # ] # } if cc: _adapter_uris = cc['crypto-adapter-uris'] for dc in cc['crypto-domain-configurations']: di = int(dc['domain-index']) am = dc['access-mode'] for a_uri in _adapter_uris: if a_uri not in all_crypto_config: all_crypto_config[a_uri] = dict() domains_dict = all_crypto_config[a_uri] # mutable if di not in domains_dict: domains_dict[di] = list() domains_dict[di].append((am, p.uri)) # # Determine the domains to be attached to the target partition # desired_domains = list(range(domain_range_lo, domain_range_hi + 1)) add_domains = list() # List of domain index numbers to be attached for di in desired_domains: if di not in attached_domains: # This domain is not attached to the target partition add_domains.append(di) elif attached_domains[di] != hmc_access_mode: # This domain is attached to the target partition but not in # the desired access mode. The access mode could be extended # from control to control+usage, but that is not implemented # by this code here. raise Error( "Domain {} is currently attached in {!r} mode to target " "partition {!r}, but requested was {!r} mode".format( di, ACCESS_MODES_HMC2MOD[attached_domains[di]], partition.name, access_mode)) else: # This domain is attached to the target partition in the # desired access mode pass # Create the domain config structure for the domains to be attached add_domain_config = list() for di in add_domains: add_domain_config.append({ 'domain-index': di, 'access-mode': hmc_access_mode }) # Check that the domains to be attached to the partition are available # on the currently attached adapters for a in attached_adapters: domains_dict = all_crypto_config[a.uri] for di in add_domains: if di in domains_dict: for am, p_uri in domains_dict[di]: if am != 'control' and hmc_access_mode != 'control': # Multiple attachments conflict only when both are # in usage mode p = all_partitions[p_uri] raise Error( "Domain {} cannot be attached in {!r} mode to " "target partition {!r} because it is already " "attached in {!r} mode to partition {!r}". format(di, access_mode, partition.name, ACCESS_MODES_HMC2MOD[am], p.name)) # Make sure the desired number of adapters is attached to the partition # and the desired domains are attached. # The HMC enforces the following for non-empty crypto configurations of # a partition: # - In the resulting config, the partition needs to have at least one # adapter attached. # - In the resulting config, the partition needs to have at least one # domain attached in usage mode. # As a result, on an empty crypto config, the first adapter and the # first domain(s) need to be attached at the same time. result_changes['added-adapters'] = [] result_changes['added-domains'] = [] missing_count = max(0, adapter_count - len(attached_adapters)) assert missing_count <= len(detached_adapters), \ "missing_count={}, len(detached_adapters)={}".\ format(missing_count, len(detached_adapters)) if missing_count == 0 and add_domain_config: # Adapters already sufficient, but domains to be attached LOGGER.debug( "Adapters sufficient - attaching domains {!r} in {!r} mode to " "target partition {!r}".format(add_domains, access_mode, partition.name)) if not check_mode: try: partition.increase_crypto_config([], add_domain_config) except zhmcclient.Error as exc: raise Error( "Attaching domains {!r} in {!r} mode to target " "partition {!r} failed: {}".format( add_domains, access_mode, partition.name, exc)) changed = True result_changes['added-domains'].extend(add_domains) elif missing_count > 0: # Adapters need to be attached for adapter in detached_adapters: if missing_count == 0: break # Check that the adapter has all needed domains available conflicting_domains = dict() if adapter.uri in all_crypto_config: domains_dict = all_crypto_config[adapter.uri] for di in desired_domains: if di in domains_dict: # The domain is already attached to some # partition(s) in some access mode for am, p_uri in domains_dict[di]: if am == 'control': # An attachment in control mode does not # prevent additional attachments continue if p_uri == partition.uri and \ am == hmc_access_mode: # This is our target partition, and the # domain is already attached in the desired # mode. continue p = all_partitions[p_uri] conflicting_domains[di] = (am, p.name) if conflicting_domains: LOGGER.debug( "Skipping adapter {!r} because the following of its " "domains are already attached to other partitions: " "{!r}".format(adapter.name, conflicting_domains)) continue LOGGER.debug( "Attaching adapter {!r} and domains {!r} in {!r} mode to " "target partition {!r}".format(adapter.name, add_domains, access_mode, partition.name)) if not check_mode: try: partition.increase_crypto_config([adapter], add_domain_config) except zhmcclient.Error as exc: raise Error( "Attaching adapter {!r} and domains {!r} in {!r} " "mode to target partition {!r} failed: {}".format( adapter.name, add_domains, access_mode, partition.name, exc)) changed = True result_changes['added-adapters'].append(adapter.name) result_changes['added-domains'].extend(add_domains) # Don't try to add again for next adapter: add_domain_config = [] add_domains = [] missing_count -= 1 if missing_count > 0: # Because adapters may be skipped, it is possible that there # are not enough adapters raise Error( "Did not find enough crypto adapters with attachable " "domains - missing adapters: {}; Requested domains: {}, " "Access mode: {}".format(missing_count, desired_domains, access_mode)) if not check_mode: # This is not optimal because it does not produce a result # in check mode, but because the actual config is determined, # instead of the artificially calculated one, it seems better # to return no config than the unchanged actual config. result.update(get_partition_config(partition, all_adapters)) return changed, result, result_changes finally: session.logoff()