Skip to content

Commit

Permalink
Fixed waiting for LPAR status in Lpar.activate()
Browse files Browse the repository at this point in the history
Details:

* Fixed the waiting for LPAR status in Lpar.activate(). Previously, the method
  was waiting for 'operating' or 'not-operating', so when an auto-load
  happened it already returned when status 'not-operating' was reached, but
  the load was still going on in parallel. Now, the method finds out whether
  the LPAR is expected to auto-load or not and waits for the corresponding
  status.

* Added a debug log entry when Lpar.wait_for_status() is called. This happens
  for example when Lpar.activate/deactivate/load() are called with
  wait_for_completion.

* Added definition of image profiles to unit test cases that perform
  activate or load.

Signed-off-by: Andreas Maier <maiera@de.ibm.com>
  • Loading branch information
andy-maier committed Oct 31, 2023
1 parent 5c733d2 commit 68f19d1
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 2 deletions.
11 changes: 11 additions & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ Released: not yet

* Docs: Corrected and improved the description of the Lpar.activate() method.

* Fixed the waiting for LPAR status in Lpar.activate(). Previously, the method
was waiting for 'operating' or 'not-operating', so when an auto-load
happened it already returned when status 'not-operating' was reached, but
the load was still going on in parallel. Now, the method finds out whether
the LPAR is expected to auto-load or not and waits for the corresponding
status.

* Added a debug log entry when Lpar.wait_for_status() is called. This happens
for example when Lpar.activate/deactivate/load() are called with
wait_for_completion.

**Enhancements:**

**Cleanup:**
Expand Down
58 changes: 58 additions & 0 deletions tests/unit/zhmcclient/test_lpar.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
LPAR2_OID = 'lpar2-oid'
LPAR2_NAME = 'lpar 2'

# Object IDs and names of our faked image activation profiles:
IMAGEPROFILE1_OID = 'imageprofile1-oid'
IMAGEPROFILE1_NAME = 'imageprofile 1'
IMAGEPROFILE2_OID = 'imageprofile2-oid'
IMAGEPROFILE2_NAME = 'imageprofile 2'

CPC_NAME = 'fake-cpc1-name'


Expand Down Expand Up @@ -100,6 +106,23 @@ def add_lpar1(self):
})
return faked_lpar

def add_imageprofile1(self):
"""Add image profile for lpar 1 (no auto-load)."""

faked_imageprofile = self.faked_cpc.image_activation_profiles.add({
'object-id': IMAGEPROFILE1_OID,
# object-uri will be automatically set
'parent': self.faked_cpc.uri,
'class': 'image-activation-profile',
'name': LPAR1_NAME,
'description': 'Image profile for LPAR #1 (Linux)',
'ipl-address': '00000',
'ipl-parameter': '',
'ipl-type': 'ipltype-standard',
'load-at-activation': False,
})
return faked_imageprofile

def add_lpar2(self):
"""Add lpar 2 (type ssc)."""

Expand All @@ -125,6 +148,23 @@ def add_lpar2(self):
})
return faked_lpar

def add_imageprofile2(self):
"""Add image profile for lpar 2 (auto-load due to SSC)."""

faked_imageprofile = self.faked_cpc.image_activation_profiles.add({
'object-id': IMAGEPROFILE2_OID,
# object-uri will be automatically set
'parent': self.faked_cpc.uri,
'class': 'image-activation-profile',
'name': LPAR2_NAME,
'description': 'Image profile for LPAR #2 (SSC)',
'ipl-address': '00000',
'ipl-parameter': '',
'ipl-type': 'ipltype-standard',
'load-at-activation': False,
})
return faked_imageprofile

def test_lparmanager_initial_attrs(self):
"""Test initial attributes of LparManager."""

Expand Down Expand Up @@ -382,6 +422,9 @@ def test_lpar_activate(
faked_lpar.properties['status'] = initial_status
faked_lpar.properties['next-activation-profile-name'] = initial_profile

# Add a faked image profile
self.add_imageprofile1()

lpar_mgr = self.cpc.lpars
lpar = lpar_mgr.find(name=faked_lpar.name)

Expand Down Expand Up @@ -620,6 +663,9 @@ def test_lpar_load(
faked_lpar.properties['last-used-load-parameter'] = initial_loadparm
faked_lpar.properties['memory'] = initial_memory

# Add a faked image profile
self.add_imageprofile1()

lpar_mgr = self.cpc.lpars
lpar = lpar_mgr.find(name=faked_lpar.name)

Expand Down Expand Up @@ -838,6 +884,9 @@ def test_lpar_scsi_load(
faked_lpar = self.add_lpar1()
faked_lpar.properties['status'] = initial_status

# Add a faked image profile
self.add_imageprofile1()

lpar_mgr = self.cpc.lpars
lpar = lpar_mgr.find(name=faked_lpar.name)

Expand Down Expand Up @@ -1026,6 +1075,9 @@ def test_lpar_scsi_dump(
faked_lpar = self.add_lpar1()
faked_lpar.properties['status'] = initial_status

# Add a faked image profile
self.add_imageprofile1()

lpar_mgr = self.cpc.lpars
lpar = lpar_mgr.find(name=faked_lpar.name)

Expand Down Expand Up @@ -1179,6 +1231,9 @@ def test_lpar_nvme_load(
faked_lpar = self.add_lpar1()
faked_lpar.properties['status'] = initial_status

# Add a faked image profile
self.add_imageprofile1()

lpar_mgr = self.cpc.lpars
lpar = lpar_mgr.find(name=faked_lpar.name)

Expand Down Expand Up @@ -1330,6 +1385,9 @@ def test_lpar_nvme_dump(
faked_lpar = self.add_lpar1()
faked_lpar.properties['status'] = initial_status

# Add a faked image profile
self.add_imageprofile1()

lpar_mgr = self.cpc.lpars
lpar = lpar_mgr.find(name=faked_lpar.name)

Expand Down
24 changes: 22 additions & 2 deletions zhmcclient/_lpar.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@
from ._manager import BaseManager
from ._resource import BaseResource
from ._exceptions import StatusTimeout
from ._logging import logged_api_call
from ._constants import HMC_LOGGER_NAME
from ._logging import get_logger, logged_api_call
from ._utils import RC_LOGICAL_PARTITION

__all__ = ['LparManager', 'Lpar']

HMC_LOGGER = get_logger(HMC_LOGGER_NAME)


class LparManager(BaseManager):
"""
Expand Down Expand Up @@ -349,7 +352,21 @@ def activate(self, wait_for_completion=True,
wait_for_completion=wait_for_completion,
operation_timeout=operation_timeout)
if wait_for_completion:
statuses = ["not-operating", "operating"]
# If an automatic load is performed, the LPAR status will first go
# to 'not-operating' and then later to 'operating'. So we cannot
# just wait for any of those two, but need to have an understanding
# whether we expect auto-load.
image_profile_mgr = self.manager.parent.image_activation_profiles
image_profile = image_profile_mgr.find(name=self.name)
auto_load = image_profile.get_property('load-at-activation')
activation_mode = self.get_property('activation-mode')
load_profile_specified = activation_profile_name is not None and \
activation_profile_name != self.name
is_ssc = activation_mode in ('ssc', 'zaware')
if auto_load or load_profile_specified or is_ssc:
statuses = ["operating"]
else:
statuses = ["not-operating"]
if allow_status_exceptions:
statuses.append("exceptions")
self.wait_for_status(statuses, status_timeout)
Expand Down Expand Up @@ -1885,6 +1902,9 @@ def wait_for_status(self, status, status_timeout=None):
statuses = status
else:
statuses = [status]
HMC_LOGGER.debug("Waiting for LPAR %r to have status: %s "
"(timeout: %s sec)",
self.name, status, status_timeout)
while True:

# Fastest way to get actual status value:
Expand Down

0 comments on commit 68f19d1

Please sign in to comment.