nodes: 0, module; 1, function_definition; 2, function_name:get_free_crypto_domains; 3, parameters; 4, block; 5, identifier:self; 6, default_parameter; 7, expression_statement; 8, if_statement; 9, if_statement; 10, comment:# We determine the maximum number of crypto domains independently; 11, comment:# of the partitions, because (1) it is possible that no partition; 12, comment:# has a crypto configuration and (2) further down we want the inner; 13, comment:# loop to be on the crypto adapters because accessing them multiple; 14, comment:# times does not drive additional HMC operations.; 15, expression_statement; 16, comment:# maximum number of domains across all adapters; 17, for_statement; 18, expression_statement; 19, comment:# Crypto domains used in control-usage mode; 20, expression_statement; 21, for_statement; 22, expression_statement; 23, expression_statement; 24, return_statement; 25, identifier:crypto_adapters; 26, None; 27, comment:"""
          Return a list of crypto domains that are free for usage on a list of
          crypto adapters in this CPC.
  
          A crypto domain is considered free for usage if it is not assigned to
          any defined partition of this CPC in access mode 'control-usage' on any
          of the specified crypto adapters.
  
          For this test, all currently defined partitions of this CPC are
          checked, regardless of whether or not they are active. This ensures
          that a crypto domain that is found to be free for usage can be assigned
          to a partition for 'control-usage' access to the specified crypto
          adapters, without causing a crypto domain conflict when activating that
          partition.
  
          Note that a similar notion of free domains does not exist for access
          mode 'control', because a crypto domain on a crypto adapter can be
          in control access by multiple active partitions.
  
          This method requires the CPC to be in DPM mode.
  
          **Example:**
  
              .. code-block:: text
  
                             crypto domains
                 adapters     0   1   2   3
                            +---+---+---+---+
                   c1       |A,c|a,c|   | C |
                            +---+---+---+---+
                   c2       |b,c|B,c| B | C |
                            +---+---+---+---+
  
              In this example, the CPC has two crypto adapters c1 and c2. For
              simplicity of the example, we assume these crypto adapters support
              only 4 crypto domains.
  
              Partition A uses only adapter c1 and has domain 0 in
              'control-usage' access (indicated by an upper case letter 'A' in
              the corresponding cell) and has domain 1 in 'control' access
              (indicated by a lower case letter 'a' in the corresponding cell).
  
              Partition B uses only adapter c2 and has domain 0 in 'control'
              access and domains 1 and 2 in 'control-usage' access.
  
              Partition C uses both adapters, and has domains 0 and 1 in
              'control' access and domain 3 in 'control-usage' access.
  
              The domains free for usage in this example are shown in the
              following table, for each combination of crypto adapters to be
              investigated:
  
              ===============  ======================
              crypto_adapters  domains free for usage
              ===============  ======================
              c1               1, 2
              c2               0
              c1, c2           (empty list)
              ===============  ======================
  
          **Experimental:** This method has been added in v0.14.0 and is
          currently considered experimental. Its interface may change
          incompatibly. Once the interface remains stable, this experimental
          marker will be removed.
  
          Authorization requirements:
  
          * Object-access permission to this CPC.
          * Object-access permission to all of its Partitions.
          * Object-access permission to all of its crypto Adapters.
  
          Parameters:
  
            crypto_adapters (:term:`iterable` of :class:`~zhmcclient.Adapter`):
              The crypto :term:`Adapters <Adapter>` to be investigated.
  
              `None` means to investigate all crypto adapters of this CPC.
  
          Returns:
  
            A sorted list of domain index numbers (integers) of the crypto
            domains that are free for usage on the specified crypto adapters.
  
            Returns `None`, if ``crypto_adapters`` was an empty list or if
            ``crypto_adapters`` was `None` and the CPC has no crypto adapters.
  
          Raises:
  
            :exc:`~zhmcclient.HTTPError`
            :exc:`~zhmcclient.ParseError`
            :exc:`~zhmcclient.AuthError`
            :exc:`~zhmcclient.ConnectionError`
          """; 28, comparison_operator:crypto_adapters is None; 29, block; 30, not_operator; 31, comment:# No crypto adapters were specified or defaulted.; 32, block; 33, assignment; 34, identifier:ca; 35, identifier:crypto_adapters; 36, block; 37, assignment; 38, assignment; 39, identifier:partition; 40, identifier:partitions; 41, block; 42, assignment; 43, assignment; 44, call; 45, identifier:crypto_adapters; 46, None; 47, expression_statement; 48, identifier:crypto_adapters; 49, return_statement; 50, identifier:max_domains; 51, None; 52, if_statement; 53, identifier:used_domains; 54, call; 55, identifier:partitions; 56, call; 57, expression_statement; 58, if_statement; 59, identifier:all_domains; 60, call; 61, identifier:free_domains; 62, binary_operator:all_domains - used_domains; 63, identifier:sorted; 64, argument_list; 65, assignment; 66, None; 67, comparison_operator:max_domains is None; 68, block; 69, else_clause; 70, identifier:set; 71, argument_list; 72, attribute; 73, argument_list; 74, assignment; 75, identifier:crypto_config; 76, block; 77, identifier:set; 78, argument_list; 79, identifier:all_domains; 80, identifier:used_domains; 81, call; 82, identifier:crypto_adapters; 83, call; 84, identifier:max_domains; 85, None; 86, expression_statement; 87, block; 88, attribute; 89, identifier:list; 90, keyword_argument; 91, identifier:crypto_config; 92, call; 93, expression_statement; 94, expression_statement; 95, for_statement; 96, call; 97, identifier:list; 98, argument_list; 99, attribute; 100, argument_list; 101, assignment; 102, expression_statement; 103, identifier:self; 104, identifier:partitions; 105, identifier:full_properties; 106, True; 107, attribute; 108, argument_list; 109, assignment; 110, assignment; 111, identifier:ca; 112, identifier:crypto_adapters; 113, block; 114, identifier:range; 115, argument_list; 116, identifier:free_domains; 117, attribute; 118, identifier:findall; 119, keyword_argument; 120, identifier:max_domains; 121, attribute; 122, assignment; 123, identifier:partition; 124, identifier:get_property; 125, string; 126, identifier:adapter_uris; 127, subscript; 128, identifier:domain_configs; 129, subscript; 130, if_statement; 131, integer:0; 132, identifier:max_domains; 133, identifier:self; 134, identifier:adapters; 135, identifier:type; 136, string; 137, identifier:ca; 138, identifier:maximum_crypto_domains; 139, identifier:max_domains; 140, call; 141, string_content:crypto-configuration; 142, identifier:crypto_config; 143, string; 144, identifier:crypto_config; 145, string; 146, comparison_operator:ca.uri in adapter_uris; 147, block; 148, string_content:crypto; 149, identifier:min; 150, argument_list; 151, string_content:crypto-adapter-uris; 152, string_content:crypto-domain-configurations; 153, attribute; 154, identifier:adapter_uris; 155, expression_statement; 156, for_statement; 157, expression_statement; 158, attribute; 159, identifier:max_domains; 160, identifier:ca; 161, identifier:uri; 162, assignment; 163, identifier:dc; 164, identifier:domain_configs; 165, block; 166, call; 167, identifier:ca; 168, identifier:maximum_crypto_domains; 169, identifier:used_adapter_domains; 170, call; 171, if_statement; 172, attribute; 173, argument_list; 174, identifier:list; 175, argument_list; 176, comparison_operator:dc['access-mode'] == 'control-usage'; 177, block; 178, identifier:used_domains; 179, identifier:update; 180, identifier:used_adapter_domains; 181, subscript; 182, string; 183, expression_statement; 184, identifier:dc; 185, string; 186, string_content:control-usage; 187, call; 188, string_content:access-mode; 189, attribute; 190, argument_list; 191, identifier:used_adapter_domains; 192, identifier:append; 193, subscript; 194, identifier:dc; 195, string; 196, string_content:domain-index
code: def get_free_crypto_domains(self, crypto_adapters=None):
          """
          Return a list of crypto domains that are free for usage on a list of
          crypto adapters in this CPC.
  
          A crypto domain is considered free for usage if it is not assigned to
          any defined partition of this CPC in access mode 'control-usage' on any
          of the specified crypto adapters.
  
          For this test, all currently defined partitions of this CPC are
          checked, regardless of whether or not they are active. This ensures
          that a crypto domain that is found to be free for usage can be assigned
          to a partition for 'control-usage' access to the specified crypto
          adapters, without causing a crypto domain conflict when activating that
          partition.
  
          Note that a similar notion of free domains does not exist for access
          mode 'control', because a crypto domain on a crypto adapter can be
          in control access by multiple active partitions.
  
          This method requires the CPC to be in DPM mode.
  
          **Example:**
  
              .. code-block:: text
  
                             crypto domains
                 adapters     0   1   2   3
                            +---+---+---+---+
                   c1       |A,c|a,c|   | C |
                            +---+---+---+---+
                   c2       |b,c|B,c| B | C |
                            +---+---+---+---+
  
              In this example, the CPC has two crypto adapters c1 and c2. For
              simplicity of the example, we assume these crypto adapters support
              only 4 crypto domains.
  
              Partition A uses only adapter c1 and has domain 0 in
              'control-usage' access (indicated by an upper case letter 'A' in
              the corresponding cell) and has domain 1 in 'control' access
              (indicated by a lower case letter 'a' in the corresponding cell).
  
              Partition B uses only adapter c2 and has domain 0 in 'control'
              access and domains 1 and 2 in 'control-usage' access.
  
              Partition C uses both adapters, and has domains 0 and 1 in
              'control' access and domain 3 in 'control-usage' access.
  
              The domains free for usage in this example are shown in the
              following table, for each combination of crypto adapters to be
              investigated:
  
              ===============  ======================
              crypto_adapters  domains free for usage
              ===============  ======================
              c1               1, 2
              c2               0
              c1, c2           (empty list)
              ===============  ======================
  
          **Experimental:** This method has been added in v0.14.0 and is
          currently considered experimental. Its interface may change
          incompatibly. Once the interface remains stable, this experimental
          marker will be removed.
  
          Authorization requirements:
  
          * Object-access permission to this CPC.
          * Object-access permission to all of its Partitions.
          * Object-access permission to all of its crypto Adapters.
  
          Parameters:
  
            crypto_adapters (:term:`iterable` of :class:`~zhmcclient.Adapter`):
              The crypto :term:`Adapters <Adapter>` to be investigated.
  
              `None` means to investigate all crypto adapters of this CPC.
  
          Returns:
  
            A sorted list of domain index numbers (integers) of the crypto
            domains that are free for usage on the specified crypto adapters.
  
            Returns `None`, if ``crypto_adapters`` was an empty list or if
            ``crypto_adapters`` was `None` and the CPC has no crypto adapters.
  
          Raises:
  
            :exc:`~zhmcclient.HTTPError`
            :exc:`~zhmcclient.ParseError`
            :exc:`~zhmcclient.AuthError`
            :exc:`~zhmcclient.ConnectionError`
          """
          if crypto_adapters is None:
              crypto_adapters = self.adapters.findall(type='crypto')
  
          if not crypto_adapters:
              # No crypto adapters were specified or defaulted.
              return None
  
          # We determine the maximum number of crypto domains independently
          # of the partitions, because (1) it is possible that no partition
          # has a crypto configuration and (2) further down we want the inner
          # loop to be on the crypto adapters because accessing them multiple
          # times does not drive additional HMC operations.
          max_domains = None  # maximum number of domains across all adapters
          for ca in crypto_adapters:
              if max_domains is None:
                  max_domains = ca.maximum_crypto_domains
              else:
                  max_domains = min(ca.maximum_crypto_domains, max_domains)
  
          used_domains = set()  # Crypto domains used in control-usage mode
          partitions = self.partitions.list(full_properties=True)
          for partition in partitions:
              crypto_config = partition.get_property('crypto-configuration')
              if crypto_config:
                  adapter_uris = crypto_config['crypto-adapter-uris']
                  domain_configs = crypto_config['crypto-domain-configurations']
                  for ca in crypto_adapters:
                      if ca.uri in adapter_uris:
                          used_adapter_domains = list()
                          for dc in domain_configs:
                              if dc['access-mode'] == 'control-usage':
                                  used_adapter_domains.append(dc['domain-index'])
                          used_domains.update(used_adapter_domains)
  
          all_domains = set(range(0, max_domains))
          free_domains = all_domains - used_domains
          return sorted(list(free_domains))