Creating Namespaces

There are two ways to create namespaces in your scripts.
The the recommended method is to use the function create_namespace in the Test API.
The other option is to use the XML_API, with the function get_vlun_nvme_update_namespace.

create_namespace

create_namespace provides a wrapper around a call to XML_API.get_vlun_nvme_update_namespace in the XML API.

It does the following for your convenience:
– Checks that configuration parameters passed to the XML API are defined properly
– Parses the XML API response into a form that is easier to use
– Handles and reports any errors that occur during the creation of the new namespaces
create_namespace(dut, config, fail_type='error', skip_type='action')
dut : XML_API
The DUT the new namespace(s) will be associated with
ns_config : dict
A dictionary containing configuration parameters for the new namespace(s)
fail_type : int or str Optional
Specifies the action to be taken if the namespace creation fails:
0 or 'pass' : Log a PASS
1 or 'notify' : Log a NOTE
2 or 'warn' : Log a WARNING and increment the warnings counter
3 or 'error' : Log an ERROR and increment the errors counter
4 or 'test' : Log an ERROR and immediately fail the entire test
skip_type : int or str Optional
Specifies the skip behavior if namespace management not supported:
0 or 'none' : Do not skip. Proceed and attempt the creation
1 or 'action' : Do not attempt the creation. Return immediately
2 or 'test' : Immediately skip the remainder of the entire test
The return value of create_namespace is a dictionary containing the following elements:
status : int
0 if the requested number of new namespaces (creates 1 by default) was created successfully
1 if only some, or none, of the new namespaces were created successfully
nsids : list of int
A list containing the integer identifiers of all newly created namespaces (empty if none were successfully created)
reason : str
An explanation of the results
{
     'status': 0,
     'nsids' : [1, 2],
     'reason': "Successfully created 2 namespace(s) on controller 100"
}

Configuration Options

The ns_config dictionary may contain any combination of the following parameters, which are passed to get_vlun_nvme_update_namespace after they are validated:
create_num : int
The number of new namespaces to create
create_size : str
The size of the new namespaces. A number followed by b (blocks), kb, mb, gb, or tb.
0 (int) to use all remaining space. Ex '5gb'
create_priv : int, 0 or 1
Whether the new namespaces will be private
create_attach : int, 0 or 1
Whether the new namespaces will be attached
lbaf : int, 0-4
The format of the new namespace(s)
0 : Better - 512
1 : Degraded - 520 (512 + 8)
2 : Best - 4096
3 : Good - 4104 (4096 + 8)
4 : Degraded - 4160 (4096 + 64)
mset : int, 0 or 1
Metadata Setting
pi : int, 0-3
Protection Information Setting
0 or 000b : Protection information is not enabled
1 or 001b : Protection information is enabled, Type 1
2 or 010b : Protection information is enabled, Type 2
3 or 011b : Protection information is enabled, Type 3
pil : int, 0 or 1
Protection Information Location
csi : int, 0-2
Command Set Identifier
0: NVM
1: Key Value
2: Zoned Namespace
nvmsetid : int
NVM Set Identifier. Leave as 0 for controller to decide
anagrpid : int
ANA Group Identifier. Leave as 0 for controller to decide
If you include valid_command or nsid in your configuration they will be ignored.
Improperly defined parameters will be rejected, and default values will be used instead if possible.
A WARNING will be issued for each improperly defined parameter.

Warning

This will only guarantee that the API call is successful, not that the values are valid.

Here is an example configuration using improper parameters, and the results of their use:

ns_config = {'create_size': '100gb',
             'mset': 1,
             'wrong': 6,                # Doesn't exist
             'create_priv': 'yes',      # Requires integer
             'create_attach': 1}
Wed Jul 28 16:37:09 2021 WARNING: In create_namespace on target 100: removing unknown parameter 'wrong'
Wed Jul 28 16:37:09 2021 WARNING: In create_namespace on target 100: 'create_priv' must be type int. Defaulting to 0

Note

In addition to the previously mentioned features, create_namespace sets the default namespace of the passed DUT to be the first newly created namespace.

For example, if calling create_namespace on dut1 results in the creation of namespaces 5 and 6, subsequent operations using dut1 will default to using namespace 5.

You can override this at any time like so:

# "dut1" is the DUT for which you would like to change the default namespace
# new_namespace_id is the new default namespace identifier to be used

dut1.lun = new_namespace_id

Care should be taken to avoid assigning a namespace identifier that does not exist, or errors are likely to occur.

Basic Example

Here is a simple example in a dual-port test that will create a new private namespace 100GB in size and print the returned dictionary:

# .. Test settings ..

def main(test_config):
    @setup(test_config)
    def test(duts):

        dut1 = duts[0]
        dut2 = duts[1]

        config = {'create_size': '100gb',
                  'create_priv': 1}

        result = create_namespace(dut1, config)

        print(result)

Printed result:

{'status': 0, 'nsids': [1], 'reason': 'Successfully created 1 namespace(s) on target 100'}

As part of the call, reason will be logged:

Wed Jul 28 14:29:13 2021 DETAIL: Successfully created 1 namespace(s) on target 100

Partial Failure

Here is an attempt to create 50 new 1GB namespaces on a device that only supports 32 (none preexisting):

config_create_50 = {'create_size': '1gb',
                    'create_num': 50}

result = create_namespace(dut1, config_create_50)

print(result)

Output:

{'status': 1, 'nsids': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32], 'reason': 'Created 32 of 50 namespace(s) on target 100: NVMe command NamespaceManagement Create CSI=0x0 failed, NVMe Status=116h (NS_ID_UNAVAILABLE, SCT=1h, SC=16h) (1633 usec)'}

We can see that it created as many namespaces as it could before encountering the error NS_ID_UNAVAILABLE .

In the event of a partial failure, in which only some namespaces are successfully created, an ERROR will be issued unless an alternate fail_type has been specified:

Wed Jul 28 15:30:13 2021  ERROR: Created 32 of 50 namespace(s) on target 100: NVMe command NamespaceManagement Create CSI=0x0 failed, NVMe Status=116h (NS_ID_UNAVAILABLE, SCT=1h, SC=16h) (1633 usec)

Complete Failure

Here is an attempt to create 5 new 100MB namespaces using an invalid (but correctly formatted) parameter, setting lbaf to 400

bad_config = {'create_size': '100mb',
              'create_num': 5,
              'lbaf': 400}

result = create_namespace(dut1, bad_config)

print(result)

Output:

{'status': 1, 'nsids': [], 'reason': "Created 0 of 5 namspace(s) on target 100: Error: -lbaf value '400' is not valid"}

In the event of a complete failure, in which 0 new namespaces are successfully created, an ERROR will be issued unless an alternate fail_type has been specified:

.. code-block:: console

Wed Jul 28 15:30:13 2021 ERROR: Created 0 of 5 namespace(s) on target 100: Error: -lbaf value ‘400’ is not valid