#!/usr/bin/env python # coding: utf-8 # # Tutorial 3: Python objects representing HMC resources # This tutorial explains how the zhmcclient package maps the HMC operations and the resources exposed by the HMC to Python objects, and how to navigate between these objects. This tutorial mostly uses the CPC and its partitions as example resources, but the same principles apply to nearly all types of resources exposed by the HMC. # In order to keep the code in these tutorials simple, the creation of the `Session` and `Client` objects has been moved into a function `make_client()` in a utility module `tututils`. # # The following code section creates a logged-on client for the specified HMC. When invoked for the first time in a notebook, `make_client()` asks for userid and password and saves that in the module. On subsequent invocations (within the same notebook), it uses the saved userid and password. # In[ ]: import tututils zhmc = '9.152.150.65' # edit this to your HMC's IP address or host name user = 'ensadmin' # edit this to the userid on that HMC client = tututils.make_client(zhmc, user) # In the zhmcclient package, all resources exposed by the HMC are encapsulated as Python objects. The following code section lists the CPCs managed by the HMC and examines the first [`Cpc`](https://python-zhmcclient.readthedocs.io/en/latest/resources.html#zhmcclient.Cpc) object in the list: # In[ ]: from pprint import pprint cpcs = client.cpcs.list() cpc = cpcs[0] print(type(cpc)) print("Public symbols:") pprint([s for s in sorted(dir(cpc)) if not s.startswith('_')]) print("Resource properties:") pprint(cpc.properties) # The public symbols are (Python) properties or methods and are described in the zhmcclient documentation (see [`Cpc`](https://python-zhmcclient.readthedocs.io/en/latest/resources.html#zhmcclient.Cpc)). # # This `Cpc` object has only three resource properties: `name`, `object-uri`, and `status`. The zhmcclient package provides these resource properties as a dictionary in the [`properties`](https://python-zhmcclient.readthedocs.io/en/latest/appendix.html#zhmcclient.BaseResource.properties) instance variable of the `Cpc` object. The names of these resource properties are unchanged from what the [HMC API](https://python-zhmcclient.readthedocs.io/en/latest/appendix.html#term-hmc-api) book defines. The zhmcclient documentation refers to the HMC API book for a list and description of the resource properties. # # The [`list()`](https://python-zhmcclient.readthedocs.io/en/latest/resources.html#zhmcclient.CpcManager.list) method only returned these three resource properties, but a CPC resource has many more properties. In the HMC API, list operations generally return only a small set of the most important properties, mostly for identification and status of the resource. # # The following code retrieves the full set of resource properties for that CPC and prints them: # In[ ]: cpc.pull_full_properties() print("Properties:") pprint(cpc.properties) # Because of this behavior, a Python object representing a resource may not always have all properties of the resource present. The [`get_property()`](https://python-zhmcclient.readthedocs.io/en/latest/appendix.html#zhmcclient.BaseResource.get_property) method allows accessing a specific named property, and retrieves it from the HMC if not currently present in the Python object. # # The following code section again lists the CPCs, creating a `Cpc` object with only three resource properties. The `get_property()` method is then used to access a property that is not among the initial three properties. This causes all resource properties to be retrieved from the HMC and stored in the `Cpc` object. The requested one is returned from the method: # In[ ]: cpcs = client.cpcs.list() cpc = cpcs[0] print("Cpc object returned by list() has {} properties".format(len(cpc.properties))) print("Accessing a property that is not yet present ...") machine_type = cpc.get_property('machine-type') print("CPC machine type: {}".format(machine_type)) print("After retrieving machine-type, the Cpc object has {} properties".format(len(cpc.properties))) # The `Cpc` object knows that it now has the full set of resource properties, so it uses them without further communication with the HMC: # In[ ]: print("CPC machine model: {}".format(cpc.get_property('machine-model'))) # Accessing invalid resource properties (i.e. properties not described in the HMC API book for the resource) causes a `KeyError` exception to be raised: # In[ ]: try: print("CPC foo: {}".format(cpc.get_property('foo'))) except Exception as exc: print("{}: {}".format(exc.__class__.__name__, exc)) # The [`prop()`](https://python-zhmcclient.readthedocs.io/en/latest/appendix.html#zhmcclient.BaseResource.prop) method returns a resource property value and allows specifying a default value in case the property is invalid: # In[ ]: print("CPC foo: {}".format(cpc.prop('foo', 'invalid'))) # The resources in the HMC are organized as a tree. The zhmcclient package reflects that in the organization of the Python objects representing these resources. The top-level object is [`Client`](https://python-zhmcclient.readthedocs.io/en/latest/general.html#zhmcclient.Client) which represents the HMC. It allows navigating to the CPCs managed by the HMC via its [`cpcs`](https://python-zhmcclient.readthedocs.io/en/latest/general.html#zhmcclient.Client.cpcs) property. # # Each Python object representing a resource allows navigating down to its child resources, and each child resource allows navigating up to its parent resource. For example, a [`Cpc`](https://python-zhmcclient.readthedocs.io/en/latest/resources.html#zhmcclient.Cpc) object represents a CPC, and its [`lpars`](https://python-zhmcclient.readthedocs.io/en/latest/resources.html#zhmcclient.Cpc.lpars) instance variable allows navigating to the LPARs of the CPC, represented by [`Lpar`](https://python-zhmcclient.readthedocs.io/en/latest/resources.html#zhmcclient.Lpar) objects. An `Lpar` object allows navigating up to its parent `Cpc` object via the generic [`manager.parent`](https://python-zhmcclient.readthedocs.io/en/latest/appendix.html#zhmcclient.BaseManager.parent) instance variable, and also via the specific [`manager.cpc`](https://python-zhmcclient.readthedocs.io/en/latest/resources.html#zhmcclient.LparManager.cpc) instance variable that is named according to the type of parent. # # The following code navigates from a `Cpc` object to its partitions (`Lpar` or `Partition` dependent on the CPC mode) and navigates back up from the first partition to its parent resource, which is the same `Cpc` Python object we started from: # In[ ]: # We use the cpc object from above print("CPC: name={}, Python object id={}".format(cpc.prop('name'), id(cpc))) if cpc.dpm_enabled: parts = cpc.partitions.list() else: parts = cpc.lpars.list() part = parts[0] kind = part.__class__.__name__ print("Found {} partitions ({} child resources)".format(len(parts), kind)) print("First {}: name={}, Python object id={}".format(kind, part.prop('name'), id(part))) p_cpc = part.manager.cpc print("Parent CPC: name={}, Python object id={}".format(p_cpc.prop('name'), id(p_cpc))) print("Same Cpc Python objects: {}".format(cpc is p_cpc)) # The [`find()`](https://python-zhmcclient.readthedocs.io/en/latest/appendix.html#zhmcclient.BaseManager.find) method retrieves a resource by specifying the value of one (or more) of its properties. # # The following code finds the CPC we already know, based upon its name: # In[ ]: cpc_name = cpc.prop('name') # could also have been specified as input print("Finding CPC by name={} ...".format(cpc_name)) cpc2 = client.cpcs.find(name=cpc_name) print("Found CPC: name={}, Python object id={}".format(cpc2.prop('name'), id(cpc2))) print("Same Cpc Python objects: {}".format(cpc is cpc2)) # Note that the found `Cpc` Python object is not the same as the original `Cpc` Python object. These two Python objects represent the same CPC resource, but their state may be different (e.g. different resource properties present, properties obtained at different points in time, etc.). # # You generally cannot rely that the zhmcclient API always returns the same Python object for a specific HMC resource. The zhmcclient package tries to minimize the use of different objects (as we saw in the case of navigating back to the parent resource), but sometimes it cannot be avoided to return multiple Python objects for the same resource. The zhmcclient is a very thin client that abstracts the HMC API into a Python API without adding things like a shared resource cache.