Skip to content

Commit

Permalink
Added support for operations for managing temporary processor capacity
Browse files Browse the repository at this point in the history
Details:

* Added `Cpc.add_temporary_capacity()` and `Cpc.remove_temporary_capacity()`.

* Added mock support for these operations by adding the URI handler classes
  CpcAddTempCapacityHandler and CpcRemoveTempCapacityHandler and the
  corresponding URIs.

Signed-off-by: Andreas Maier <[email protected]>
  • Loading branch information
andy-maier committed Nov 22, 2020
1 parent 94e247f commit 545fbf9
Show file tree
Hide file tree
Showing 4 changed files with 477 additions and 0 deletions.
3 changes: 3 additions & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ Released: not yet
* Migrated from Travis and Appveyor to GitHub Actions. This required several
changes in package dependencies for development.

* Added support for operations for managing temporary processor capacity:
`Cpc.add_temporary_capacity()` and `Cpc.remove_temporary_capacity()`.

**Cleanup:**

**Known issues:**
Expand Down
153 changes: 153 additions & 0 deletions tests/unit/zhmcclient/test_cpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,27 @@
CPC4_NAME = 'cpc 4' # z14-ZR1 in DPM mode
CPC4_OID = 'cpc4-oid'

# Additional CPC properties for temporary capacity tests
CPC1_CAPACITY_PROPS = {
'is-on-off-cod-installed': True,
'is-on-off-cod-enabled': True,
'is-on-off-cod-activated': False,
'on-off-cod-activation-date': None,
'software-model-permanent': '700',
'software-model-permanent-plus-billable': '700',
'software-model-permanent-plus-temporary': None,
# 'msu-permanent': TBD,
# 'msu-permanen-plus-billable': TBD,
# 'msu-permanent-plus-temporary': TBD,
'processor-count-general-purpose': 7,
'processor-count-service-assist': 6,
'processor-count-aap': 5,
'processor-count-ifl': 4,
'processor-count-icf': 3,
'processor-count-iip': 2,
'processor-count-cbp2': 1,
}

HTTPError_404_1 = HTTPError({'http-status': 404, 'reason': 1})
HTTPError_409_5 = HTTPError({'http-status': 409, 'reason': 5})
HTTPError_409_4 = HTTPError({'http-status': 409, 'reason': 4})
Expand Down Expand Up @@ -318,6 +339,16 @@
]


def updated(dict1, dict2):
"""
Return a copy of dict1 that is updated with dict2. This allows specifying
testcase structures more easily.
"""
dictres = dict1.copy()
dictres.update(dict2)
return dictres


class TestCpc(object):
"""All tests for the Cpc and CpcManager classes."""

Expand Down Expand Up @@ -1310,3 +1341,125 @@ def test_cpc_get_energy_mgmt_props(
# Verify consistency of returned energy properties with CPC props
assert p in cpc.properties
assert cpc.properties[p] == exp_value

@pytest.mark.parametrize(
"cpc_name, cpc_props, input_kwargs, exp_cpc_props", [
(
CPC1_NAME,
CPC1_CAPACITY_PROPS,
dict(
record_id='caprec1',
),
CPC1_CAPACITY_PROPS,
),
(
CPC1_NAME,
CPC1_CAPACITY_PROPS,
dict(
record_id='caprec1',
software_model='710',
),
updated(
CPC1_CAPACITY_PROPS, {
'software-model-permanent-plus-temporary': '710',
'processor-count-general-purpose': 10,
}
),
),
(
CPC1_NAME,
CPC1_CAPACITY_PROPS,
dict(
record_id='caprec1',
processor_info=dict(ifl=1),
),
updated(
CPC1_CAPACITY_PROPS, {
'processor-count-ifl': 5,
}
),
),
]
)
def test_cpc_add_temporary_capacity(
self, cpc_name, cpc_props, input_kwargs, exp_cpc_props):
"""Test Cpc.add_temporary_capacity()."""

# Add a faked CPC
faked_cpc = self.add_cpc(cpc_name)
faked_cpc.properties.update(cpc_props)

cpc_mgr = self.client.cpcs
cpc = cpc_mgr.find(name=cpc_name)

# Execute the code to be tested
cpc.add_temporary_capacity(**input_kwargs)

cpc.pull_full_properties()

for pname, pvalue in exp_cpc_props.items():
assert pname in cpc.properties
assert cpc.properties[pname] == pvalue

@pytest.mark.parametrize(
"cpc_name, cpc_props, input_kwargs, exp_cpc_props", [
(
CPC1_NAME,
CPC1_CAPACITY_PROPS,
dict(
record_id='caprec1',
),
CPC1_CAPACITY_PROPS,
),
(
CPC1_NAME,
updated(
CPC1_CAPACITY_PROPS, {
'software-model-permanent-plus-temporary': '710',
'processor-count-general-purpose': 10,
}
),
dict(
record_id='caprec1',
software_model='705',
),
updated(
CPC1_CAPACITY_PROPS, {
'processor-count-general-purpose': 5,
}
),
),
(
CPC1_NAME,
CPC1_CAPACITY_PROPS,
dict(
record_id='caprec1',
processor_info=dict(ifl=1),
),
updated(
CPC1_CAPACITY_PROPS, {
'processor-count-ifl': 3,
}
),
),
]
)
def test_cpc_remove_temporary_capacity(
self, cpc_name, cpc_props, input_kwargs, exp_cpc_props):
"""Test Cpc.remove_temporary_capacity()."""

# Add a faked CPC
faked_cpc = self.add_cpc(cpc_name)
faked_cpc.properties.update(cpc_props)

cpc_mgr = self.client.cpcs
cpc = cpc_mgr.find(name=cpc_name)

# Execute the code to be tested
cpc.remove_temporary_capacity(**input_kwargs)

cpc.pull_full_properties()

for pname, pvalue in exp_cpc_props.items():
assert pname in cpc.properties
assert cpc.properties[pname] == pvalue
179 changes: 179 additions & 0 deletions zhmcclient/_cpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1360,3 +1360,182 @@ def validate_lun_path(self, host_wwpn, host_port, wwpn, lun):
self.manager.session.post(
self.uri + '/operations/validate-lun-path',
body=body)

@logged_api_call
def add_temporary_capacity(
self, record_id, software_model=None, processor_info=None,
test=False, force=False):
"""
Add temporary processors to the CPC or increase temporary model
capacity of the CPC.
This method performs the "Add Temporary Capacity" HMC operation.
If the request would exceed the processor capacity that is installed on
the CPC or the limits of the capacity record, the operation will fail,
unless the `force` parameter is `True`.
Parameters:
record_id (:term:`string`):
The ID of the capacity record to be used for any updates of the
processor capacity.
software_model (:term:`string`):
The name of the software model to be activated for the CPC.
This must be one of the software models defined within the
specified capacity record. The software model implies the number
of general purpose processors that will be active once the
operation succeeds.
If `None`, the software model and the number of general purpose
processors of the CPC will remain unchanged.
processor_info (dict):
The number of specialty processors to be added to the CPC.
If `None`, the number of specialty processors of the CPC will
remain unchanged.
Each item in the dictionary identifies the number of one type of
specialty processor. The key of the item must be a string
specifying the type of specialty processor ('aap', 'cbp', 'icf',
'ifl', 'iip', 'sap'), and the value of the item must be an integer
specifying the number of processors of that type to be added.
If an item for a type of specialty processor is not provided, or
if the value of the item is `None`, the number of specialty
processors of that type will remain unchanged.
test (bool):
Indicates whether test (`True`) or real (`False`) resources should
be activated. Test resources are automatically deactivated after
24h.
force (bool):
`True` indicates that the operation should proceed if not enough
processors are available. `True` is permitted only for CBU, CPE
and loaner capacity records.
Authorization requirements:
* Object-access permission to the CPC.
* Task permission to the "Perform Model Conversion" task.
Raises:
:exc:`~zhmcclient.HTTPError`
:exc:`~zhmcclient.ParseError`
:exc:`~zhmcclient.AuthError`
:exc:`~zhmcclient.ConnectionError`
"""

body = {
'record-id': record_id,
'force': force,
'test': test,
}
if software_model:
body['software-model'] = software_model
if processor_info:
pi = []
for ptype, pvalue in processor_info.items():
pi_item = {
'processor-type': ptype,
}
if pvalue is not None:
pi_item['num-processor-steps'] = pvalue
pi.append(pi_item)
body['processor-info'] = pi

self.manager.session.post(
self.uri + '/operations/add-temp-capacity',
body=body)

@logged_api_call
def remove_temporary_capacity(
self, record_id, software_model=None, processor_info=None):
"""
Remove temporary processors from the CPC or decrease temporary model
capacity of the CPC.
This method performs the "Remove Temporary Capacity" HMC operation.
You can only remove activated resources for the specific offering.
You cannot remove dedicated engines or the last processor of a processor
type. If you remove resources back to the base configuration, the
capacity record activation is completed. That is, if you remove the
last temporary processor, your capacity record is deactivated. For a
CBU and On/Off CoD record, to add resources again, you must use another
:meth:`add_temporary_capacity` operation. For an On/Off CoD test or
CPE record, once the record is deactivated, it is no longer available
for use. You can then delete the record.
After removal of the resources, the capacity record remains as an
installed record. If you want a record deleted, you must manually
delete the record on the "Installed Records" page in the HMC GUI.
Parameters:
record_id (:term:`string`):
The ID of the capacity record to be used for any updates of the
processor capacity.
software_model (:term:`string`):
The name of the software model to be activated for the CPC.
This must be one of the software models defined within the
specified capacity record. The software model implies the number
of general purpose processors that will be active once the
operation succeeds.
If `None`, the software model and the number of general purpose
processors of the CPC will remain unchanged.
processor_info (dict):
The number of specialty processors to be removed from the CPC.
If `None`, the number of specialty processors of the CPC will
remain unchanged.
Each item in the dictionary identifies the number of one type of
specialty processor. The key of the item must be a string
specifying the type of specialty processor ('aap', 'cbp', 'icf',
'ifl', 'iip', 'sap'), and the value of the item must be an integer
specifying the number of processors of that type to be removed.
If an item for a type of specialty processor is not provided, or
if the value of the item is `None`, the number of specialty
processors of that type will remain unchanged.
Authorization requirements:
* Object-access permission to the CPC.
* Task permission to the "Perform Model Conversion" task.
Raises:
:exc:`~zhmcclient.HTTPError`
:exc:`~zhmcclient.ParseError`
:exc:`~zhmcclient.AuthError`
:exc:`~zhmcclient.ConnectionError`
"""

body = {
'record-id': record_id,
}
if software_model:
body['software-model'] = software_model
if processor_info:
pi = []
for ptype, pvalue in processor_info.items():
pi_item = {
'processor-type': ptype,
}
if pvalue is not None:
pi_item['num-processor-steps'] = pvalue
pi.append(pi_item)
body['processor-info'] = pi

self.manager.session.post(
self.uri + '/operations/remove-temp-capacity',
body=body)
Loading

0 comments on commit 545fbf9

Please sign in to comment.