From c473cf7a69c86bb0100893ea17b4274656ab0201 Mon Sep 17 00:00:00 2001 From: Prabhat Ranjan Date: Fri, 16 Dec 2016 15:06:51 +0530 Subject: [PATCH] implemented following function in driver.py 1.list_instances() 2.get_info() 3.spawn() Change-Id: Ifc67cebfcb2694ec082955a7180c0793ada20f21 Signed-off-by: Prabhat Ranjan --- nova_dpm/virt/dpm/driver.py | 51 ++++++++++--- nova_dpm/virt/dpm/utils.py | 14 ++++ nova_dpm/virt/dpm/vm.py | 144 ++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 9 deletions(-) create mode 100644 nova_dpm/virt/dpm/vm.py diff --git a/nova_dpm/virt/dpm/driver.py b/nova_dpm/virt/dpm/driver.py index bd11377..eeb385c 100644 --- a/nova_dpm/virt/dpm/driver.py +++ b/nova_dpm/virt/dpm/driver.py @@ -17,13 +17,17 @@ A connection to a z Systems through Dynamic Partition Manager( DPM) APIs. Supports DPM APIs for virtualization in z Systems """ + import nova_dpm.conf import requests.packages.urllib3 +from nova import context as context_object from nova import exception +from nova.objects import flavor as flavor_object from nova.virt import driver from nova_dpm.virt.dpm import host as Host from nova_dpm.virt.dpm import utils +from nova_dpm.virt.dpm import vm from oslo_log import log as logging from oslo_utils import importutils @@ -48,6 +52,7 @@ class DPMDriver(driver.ComputeDriver): self._host = None self._client = None + self._cpc = None # Retrieve zhmc ipaddress, username, password from the nova.conf zhmc = CONF.dpm.hmc @@ -89,15 +94,15 @@ class DPMDriver(driver.ComputeDriver): 'max_partitions': CONF.dpm.max_instances } - cpc = self._client.cpcs.find(**{"object-id": conf['cpc_uuid']}) + self._cpc = self._client.cpcs.find(**{"object-id": conf['cpc_uuid']}) LOG.debug("Matching hypervisor found %(cpcsubset_name)s for UUID " "%(uuid)s and CPC %(cpcname)s" % {'cpcsubset_name': conf['cpcsubset_name'], 'uuid': conf['cpc_uuid'], - 'cpcname': cpc.properties['name']}) + 'cpcname': self._cpc.properties['name']}) - utils.valide_host_conf(conf, cpc) - self._host = Host.Host(conf, cpc, self._client) + utils.valide_host_conf(conf, self._cpc) + self._host = Host.Host(conf, self._cpc, self._client) def get_available_resource(self, nodename): """Retrieve resource information. @@ -142,11 +147,6 @@ class DPMDriver(driver.ComputeDriver): # Refresh and check again. return nodename in self.get_available_nodes(refresh=True) - def get_num_instances(self): - LOG.debug("get_num_instances") - # TODO(preethipy): Will be updated with actual number of instances - return 0 - def attach_volume(self, context, connection_info, instance, mountpoint, disk_bus=None, device_type=None, encryption=None): @@ -203,3 +203,36 @@ class DPMDriver(driver.ComputeDriver): def _disconnect_volume(self, connection_info, disk_dev): vol_driver = self._get_volume_driver(connection_info) vol_driver.disconnect_volume(connection_info, disk_dev) + + def list_instances(self): + + partition_manager = zhmcclient.PartitionManager(self._cpc) + partition_lists = partition_manager.list(full_properties=False) + + part_list = [] + for partition in partition_lists: + part_list.append(partition.get_property('name')) + + return part_list + + def get_info(self, instance): + + info = vm.InstanceInfo(instance, self._cpc) + + return info + + def spawn(self, context, instance, image_meta, injected_files, + admin_password, network_info=None, block_device_info=None, + flavor=None): + + if not flavor: + context = context_object.get_admin_context(read_deleted='yes') + flavor = ( + flavor_object.Flavor.get_by_id(context, + instance.instance_type_id)) + LOG.debug("Flavor = %(flavor)s" % {'flavor': flavor}) + + inst = vm.Instance(instance, flavor, self._cpc) + inst.launch() + + # TODO(pranjank): implement start partition diff --git a/nova_dpm/virt/dpm/utils.py b/nova_dpm/virt/dpm/utils.py index 36aa8a8..f2ba647 100644 --- a/nova_dpm/virt/dpm/utils.py +++ b/nova_dpm/virt/dpm/utils.py @@ -51,3 +51,17 @@ def valide_host_conf(conf, cpc): 'cpcuuid': conf['cpc_uuid'], 'cpcname': cpc.properties['name']}) raise exception.ValidationError(errormsg) + + +class PartitionState(object): + + COMMUNICATION_NOT_ACTIVE = 'communications-not-active' + DEGRADED = 'degraded' + PAUSED = 'paused' + RESERVATION_ERROR = 'reservation-error' + RUNNING = 'active' + SHUTTING_DOWN = 'stopping' + STARTING = 'starting' + STOPPED = 'stopped' + TERMINATED = 'terminated"' + UNKNOWN = 'status-check' diff --git a/nova_dpm/virt/dpm/vm.py b/nova_dpm/virt/dpm/vm.py new file mode 100644 index 0000000..8950836 --- /dev/null +++ b/nova_dpm/virt/dpm/vm.py @@ -0,0 +1,144 @@ +# Copyright 2016 IBM Corp. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +""" +Partition will map nova parameter to PRSM parameter +""" + +from nova.compute import power_state +from nova_dpm.virt.dpm import utils +import zhmcclient + + +DPM_TO_NOVA_STATE = { + utils.PartitionState.RUNNING: power_state.RUNNING, + utils.PartitionState.STOPPED: power_state.SHUTDOWN, + utils.PartitionState.UNKNOWN: power_state.NOSTATE, + utils.PartitionState.PAUSED: power_state.PAUSED, + utils.PartitionState.STARTING: power_state.NOSTATE +} + + +def _translate_vm_state(dpm_state): + + if dpm_state is None: + return power_state.NOSTATE + + try: + nova_state = DPM_TO_NOVA_STATE[dpm_state.lower()] + except KeyError: + nova_state = power_state.NOSTATE + + return nova_state + + +class Instance(object): + def __init__(self, instance, flavor, cpc): + self.instance = instance + self.flavor = flavor + self.cpc = cpc + self.partition = None + + def properties(self): + properties = {} + properties['name'] = self.instance.hostname + properties['cp-processors'] = self.flavor.vcpus + properties['initial-memory'] = self.flavor.memory_mb + properties['maximum-memory'] = self.flavor.memory_mb + + return properties + + def create(self): + partition_manager = zhmcclient.PartitionManager( + self.cpc) + self.partition = partition_manager.create( + self.properties()) + + def launch(self): + self.create() + + def get_partition(self): + + if self.partition is None: + partition_manager = zhmcclient.PartitionManager( + self.cpc) + partition_lists = partition_manager.list( + full_properties=False) + for partition in partition_lists: + if partition.properties['name'] == self.instance.hostname: + self.partition = partition + + return self.partition + + +class InstanceInfo(object): + """Instance Information + + This object loads VM information like state, memory used etc + + """ + + def __init__(self, instance, cpc): + self.instance = instance + self.cpc = cpc + self.partition = None + partition_manager = zhmcclient.PartitionManager(self.cpc) + partition_lists = partition_manager.list(full_properties=False) + for partition in partition_lists: + if partition.properties['name'] == self.instance.hostname: + self.partition = partition + + @property + def state(self): + + status = None + if self.partition is not None: + status = self.partition.get_property('status') + + return _translate_vm_state(status) + + @property + def mem(self): + + mem = None + if self.partition is not None: + mem = self.partition.get_property('initial-memory') + + return mem + + @property + def max_mem(self): + + max_mem = None + if self.partition is not None: + max_mem = self.partition.get_property('maximum-memory') + + return max_mem + + @property + def num_cpu(self): + + num_cpu = None + if self.partition is not None: + num_cpu = self.partition.get_property('cp-processors') + + return num_cpu + + @property + def cpu_time(self): + + # TODO(pranjank): will implement + # As of now returning dummy value + return 100