1474 lines
53 KiB
Python
1474 lines
53 KiB
Python
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
|
# Copyright (c) 2012 VMware, Inc.
|
|
# Copyright (c) 2011 Citrix Systems, Inc.
|
|
# Copyright 2011 OpenStack Foundation
|
|
#
|
|
# 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.
|
|
|
|
"""
|
|
A fake VMware VI API implementation.
|
|
"""
|
|
|
|
import collections
|
|
import pprint
|
|
|
|
from nova import exception
|
|
from nova.openstack.common.gettextutils import _
|
|
from nova.openstack.common import jsonutils
|
|
from nova.openstack.common import log as logging
|
|
from nova.openstack.common import units
|
|
from nova.openstack.common import uuidutils
|
|
from nova.virt.vmwareapi import error_util
|
|
|
|
_CLASSES = ['Datacenter', 'Datastore', 'ResourcePool', 'VirtualMachine',
|
|
'Network', 'HostSystem', 'HostNetworkSystem', 'Task', 'session',
|
|
'files', 'ClusterComputeResource', 'HostStorageSystem']
|
|
|
|
_FAKE_FILE_SIZE = 1024
|
|
|
|
_db_content = {}
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def log_db_contents(msg=None):
|
|
"""Log DB Contents."""
|
|
LOG.debug(_("%(text)s: _db_content => %(content)s"),
|
|
{'text': msg or "", 'content': pprint.pformat(_db_content)})
|
|
|
|
|
|
def reset(vc=False):
|
|
"""Resets the db contents."""
|
|
cleanup()
|
|
create_network()
|
|
create_host_network_system()
|
|
create_host_storage_system()
|
|
ds_ref1 = create_datastore('ds1', 1024, 500)
|
|
create_host(ds_ref=ds_ref1)
|
|
if vc:
|
|
ds_ref2 = create_datastore('ds2', 1024, 500)
|
|
create_host(ds_ref=ds_ref2)
|
|
create_datacenter('dc1', ds_ref1)
|
|
if vc:
|
|
create_datacenter('dc2', ds_ref2)
|
|
create_res_pool()
|
|
if vc:
|
|
create_cluster('test_cluster', ds_ref1)
|
|
create_cluster('test_cluster2', ds_ref2)
|
|
|
|
|
|
def cleanup():
|
|
"""Clear the db contents."""
|
|
for c in _CLASSES:
|
|
# We fake the datastore by keeping the file references as a list of
|
|
# names in the db
|
|
if c == 'files':
|
|
_db_content[c] = []
|
|
else:
|
|
_db_content[c] = {}
|
|
|
|
|
|
def _create_object(table, table_obj):
|
|
"""Create an object in the db."""
|
|
_db_content[table][table_obj.obj] = table_obj
|
|
|
|
|
|
def _get_object(obj_ref):
|
|
"""Get object for the give reference."""
|
|
return _db_content[obj_ref.type][obj_ref]
|
|
|
|
|
|
def _get_objects(obj_type):
|
|
"""Get objects of the type."""
|
|
lst_objs = FakeRetrieveResult()
|
|
for key in _db_content[obj_type]:
|
|
lst_objs.add_object(_db_content[obj_type][key])
|
|
return lst_objs
|
|
|
|
|
|
def _convert_to_array_of_mor(mors):
|
|
"""Wraps the given array into a DataObject."""
|
|
array_of_mors = DataObject()
|
|
array_of_mors.ManagedObjectReference = mors
|
|
return array_of_mors
|
|
|
|
|
|
def _convert_to_array_of_opt_val(optvals):
|
|
"""Wraps the given array into a DataObject."""
|
|
array_of_optv = DataObject()
|
|
array_of_optv.OptionValue = optvals
|
|
return array_of_optv
|
|
|
|
|
|
class FakeRetrieveResult(object):
|
|
"""Object to retrieve a ObjectContent list."""
|
|
|
|
def __init__(self, token=None):
|
|
self.objects = []
|
|
if token is not None:
|
|
self.token = token
|
|
|
|
def add_object(self, object):
|
|
self.objects.append(object)
|
|
|
|
|
|
class MissingProperty(object):
|
|
"""Missing object in ObjectContent's missing set."""
|
|
def __init__(self, path='fake-path', message='fake_message',
|
|
method_fault=None):
|
|
self.path = path
|
|
self.fault = DataObject()
|
|
self.fault.localizedMessage = message
|
|
self.fault.fault = method_fault
|
|
|
|
|
|
def _get_object_refs(obj_type):
|
|
"""Get object References of the type."""
|
|
lst_objs = []
|
|
for key in _db_content[obj_type]:
|
|
lst_objs.append(key)
|
|
return lst_objs
|
|
|
|
|
|
def _update_object(table, table_obj):
|
|
"""Update objects of the type."""
|
|
_db_content[table][table_obj.obj] = table_obj
|
|
|
|
|
|
class Prop(object):
|
|
"""Property Object base class."""
|
|
|
|
def __init__(self, name=None, val=None):
|
|
self.name = name
|
|
self.val = val
|
|
|
|
|
|
class ManagedObjectReference(object):
|
|
"""A managed object reference is a remote identifier."""
|
|
|
|
def __init__(self, name="ManagedObject", value=None):
|
|
super(ManagedObjectReference, self)
|
|
# Managed Object Reference value attributes
|
|
# typically have values like vm-123 or
|
|
# host-232 and not UUID.
|
|
self.value = value
|
|
# Managed Object Reference type
|
|
# attributes hold the name of the type
|
|
# of the vCenter object the value
|
|
# attribute is the identifier for
|
|
self.type = name
|
|
self._type = name
|
|
|
|
|
|
class ObjectContent(object):
|
|
"""ObjectContent array holds dynamic properties."""
|
|
|
|
# This class is a *fake* of a class sent back to us by
|
|
# SOAP. It has its own names. These names are decided
|
|
# for us by the API we are *faking* here.
|
|
def __init__(self, obj_ref, prop_list=None, missing_list=None):
|
|
self.obj = obj_ref
|
|
|
|
if not isinstance(prop_list, collections.Iterable):
|
|
prop_list = []
|
|
|
|
if not isinstance(missing_list, collections.Iterable):
|
|
missing_list = []
|
|
|
|
# propSet is the name your Python code will need to
|
|
# use since this is the name that the API will use
|
|
if prop_list:
|
|
self.propSet = prop_list
|
|
|
|
# missingSet is the name your python code will
|
|
# need to use since this is the name that the
|
|
# API we are talking to will use.
|
|
if missing_list:
|
|
self.missingSet = missing_list
|
|
|
|
|
|
class ManagedObject(object):
|
|
"""Managed Object base class."""
|
|
_counter = 0
|
|
|
|
def __init__(self, mo_id_prefix="obj"):
|
|
"""Sets the obj property which acts as a reference to the object."""
|
|
object.__setattr__(self, 'mo_id', self._generate_moid(mo_id_prefix))
|
|
object.__setattr__(self, 'propSet', [])
|
|
object.__setattr__(self, 'obj',
|
|
ManagedObjectReference(self.__class__.__name__,
|
|
self.mo_id))
|
|
|
|
def set(self, attr, val):
|
|
"""Sets an attribute value. Not using the __setattr__ directly for we
|
|
want to set attributes of the type 'a.b.c' and using this function
|
|
class we set the same.
|
|
"""
|
|
self.__setattr__(attr, val)
|
|
|
|
def get(self, attr):
|
|
"""Gets an attribute. Used as an intermediary to get nested
|
|
property like 'a.b.c' value.
|
|
"""
|
|
return self.__getattr__(attr)
|
|
|
|
def __setattr__(self, attr, val):
|
|
# TODO(hartsocks): this is adds unnecessary complexity to the class
|
|
for prop in self.propSet:
|
|
if prop.name == attr:
|
|
prop.val = val
|
|
return
|
|
elem = Prop()
|
|
elem.name = attr
|
|
elem.val = val
|
|
self.propSet.append(elem)
|
|
|
|
def __getattr__(self, attr):
|
|
# TODO(hartsocks): remove this
|
|
# in a real ManagedObject you have to iterate the propSet
|
|
# in a real ManagedObject, the propSet is a *set* not a list
|
|
for elem in self.propSet:
|
|
if elem.name == attr:
|
|
return elem.val
|
|
msg = _("Property %(attr)s not set for the managed object %(name)s")
|
|
raise exception.NovaException(msg % {'attr': attr,
|
|
'name': self.__class__.__name__})
|
|
|
|
def _generate_moid(self, prefix):
|
|
"""Generates a new Managed Object ID."""
|
|
self.__class__._counter += 1
|
|
return prefix + "-" + str(self.__class__._counter)
|
|
|
|
def __repr__(self):
|
|
return jsonutils.dumps(dict([(elem.name, elem.val)
|
|
for elem in self.propSet]))
|
|
|
|
|
|
class DataObject(object):
|
|
"""Data object base class."""
|
|
|
|
def __init__(self, obj_name=None):
|
|
self.obj_name = obj_name
|
|
|
|
def __repr__(self):
|
|
return str(self.__dict__)
|
|
|
|
|
|
class HostInternetScsiHba(DataObject):
|
|
"""iSCSI Host Bus Adapter"""
|
|
|
|
def __init__(self):
|
|
super(HostInternetScsiHba, self).__init__()
|
|
self.device = 'vmhba33'
|
|
self.key = 'key-vmhba33'
|
|
|
|
|
|
class FileAlreadyExists(DataObject):
|
|
"""File already exists class."""
|
|
|
|
def __init__(self):
|
|
super(FileAlreadyExists, self).__init__()
|
|
self.__name__ = error_util.FILE_ALREADY_EXISTS
|
|
|
|
|
|
class FileNotFound(DataObject):
|
|
"""File not found class."""
|
|
|
|
def __init__(self):
|
|
super(FileNotFound, self).__init__()
|
|
self.__name__ = error_util.FILE_NOT_FOUND
|
|
|
|
|
|
class FileFault(DataObject):
|
|
"""File fault."""
|
|
|
|
def __init__(self):
|
|
super(FileFault, self).__init__()
|
|
self.__name__ = error_util.FILE_FAULT
|
|
|
|
|
|
class CannotDeleteFile(DataObject):
|
|
"""Cannot delete file."""
|
|
|
|
def __init__(self):
|
|
super(CannotDeleteFile, self).__init__()
|
|
self.__name__ = error_util.CANNOT_DELETE_FILE
|
|
|
|
|
|
class FileLocked(DataObject):
|
|
"""File locked."""
|
|
|
|
def __init__(self):
|
|
super(FileLocked, self).__init__()
|
|
self.__name__ = error_util.FILE_LOCKED
|
|
|
|
|
|
class VirtualDisk(DataObject):
|
|
"""Virtual Disk class."""
|
|
|
|
def __init__(self, controllerKey=0, unitNumber=0):
|
|
super(VirtualDisk, self).__init__()
|
|
self.key = 0
|
|
self.controllerKey = controllerKey
|
|
self.unitNumber = unitNumber
|
|
|
|
|
|
class VirtualDiskFlatVer2BackingInfo(DataObject):
|
|
"""VirtualDiskFlatVer2BackingInfo class."""
|
|
|
|
def __init__(self):
|
|
super(VirtualDiskFlatVer2BackingInfo, self).__init__()
|
|
self.thinProvisioned = False
|
|
self.eagerlyScrub = False
|
|
|
|
|
|
class VirtualDiskRawDiskMappingVer1BackingInfo(DataObject):
|
|
"""VirtualDiskRawDiskMappingVer1BackingInfo class."""
|
|
|
|
def __init__(self):
|
|
super(VirtualDiskRawDiskMappingVer1BackingInfo, self).__init__()
|
|
self.lunUuid = ""
|
|
|
|
|
|
class VirtualIDEController(DataObject):
|
|
|
|
def __init__(self, key=0):
|
|
self.key = key
|
|
|
|
|
|
class VirtualLsiLogicController(DataObject):
|
|
"""VirtualLsiLogicController class."""
|
|
def __init__(self, key=0, scsiCtlrUnitNumber=0):
|
|
self.key = key
|
|
self.scsiCtlrUnitNumber = scsiCtlrUnitNumber
|
|
|
|
|
|
class VirtualLsiLogicSASController(DataObject):
|
|
"""VirtualLsiLogicSASController class."""
|
|
pass
|
|
|
|
|
|
class VirtualPCNet32(DataObject):
|
|
"""VirtualPCNet32 class."""
|
|
|
|
def __init__(self):
|
|
super(VirtualPCNet32, self).__init__()
|
|
self.key = 4000
|
|
|
|
|
|
class OptionValue(DataObject):
|
|
"""OptionValue class."""
|
|
|
|
def __init__(self, key=None, value=None):
|
|
super(OptionValue, self).__init__()
|
|
self.key = key
|
|
self.value = value
|
|
|
|
|
|
class VirtualMachine(ManagedObject):
|
|
"""Virtual Machine class."""
|
|
|
|
def __init__(self, **kwargs):
|
|
super(VirtualMachine, self).__init__("vm")
|
|
self.set("name", kwargs.get("name", 'test-vm'))
|
|
self.set("runtime.connectionState",
|
|
kwargs.get("conn_state", "connected"))
|
|
self.set("summary.config.guestId", kwargs.get("guest", "otherGuest"))
|
|
ds_do = kwargs.get("ds", None)
|
|
self.set("datastore", _convert_to_array_of_mor(ds_do))
|
|
self.set("summary.guest.toolsStatus", kwargs.get("toolsstatus",
|
|
"toolsOk"))
|
|
self.set("summary.guest.toolsRunningStatus", kwargs.get(
|
|
"toolsrunningstate", "guestToolsRunning"))
|
|
self.set("runtime.powerState", kwargs.get("powerstate", "poweredOn"))
|
|
self.set("config.files.vmPathName", kwargs.get("vmPathName"))
|
|
self.set("summary.config.numCpu", kwargs.get("numCpu", 1))
|
|
self.set("summary.config.memorySizeMB", kwargs.get("mem", 1))
|
|
self.set("summary.config.instanceUuid", kwargs.get("instanceUuid"))
|
|
self.set("config.hardware.device", kwargs.get("virtual_device", None))
|
|
exconfig_do = kwargs.get("extra_config", None)
|
|
self.set("config.extraConfig",
|
|
_convert_to_array_of_opt_val(exconfig_do))
|
|
if exconfig_do:
|
|
for optval in exconfig_do:
|
|
self.set('config.extraConfig["%s"]' % optval.key, optval)
|
|
self.set('runtime.host', kwargs.get("runtime_host", None))
|
|
self.device = kwargs.get("virtual_device")
|
|
# Sample of diagnostics data is below.
|
|
config = [
|
|
('template', False),
|
|
('vmPathName', 'fake_path'),
|
|
('memorySizeMB', 512),
|
|
('cpuReservation', 0),
|
|
('memoryReservation', 0),
|
|
('numCpu', 1),
|
|
('numEthernetCards', 1),
|
|
('numVirtualDisks', 1)]
|
|
self.set("summary.config", config)
|
|
|
|
quickStats = [
|
|
('overallCpuUsage', 0),
|
|
('overallCpuDemand', 0),
|
|
('guestMemoryUsage', 0),
|
|
('hostMemoryUsage', 141),
|
|
('balloonedMemory', 0),
|
|
('consumedOverheadMemory', 20)]
|
|
self.set("summary.quickStats", quickStats)
|
|
|
|
key1 = {'key': 'cpuid.AES'}
|
|
key2 = {'key': 'cpuid.AVX'}
|
|
runtime = [
|
|
('connectionState', 'connected'),
|
|
('powerState', 'poweredOn'),
|
|
('toolsInstallerMounted', False),
|
|
('suspendInterval', 0),
|
|
('memoryOverhead', 21417984),
|
|
('maxCpuUsage', 2000),
|
|
('featureRequirement', [key1, key2])]
|
|
self.set("summary.runtime", runtime)
|
|
|
|
def reconfig(self, factory, val):
|
|
"""Called to reconfigure the VM. Actually customizes the property
|
|
setting of the Virtual Machine object.
|
|
"""
|
|
|
|
if hasattr(val, 'name') and val.name:
|
|
self.set("name", val.name)
|
|
|
|
if hasattr(val, 'extraConfig'):
|
|
extraConfigs = _merge_extraconfig(
|
|
self.get("config.extraConfig").OptionValue,
|
|
val.extraConfig)
|
|
self.get("config.extraConfig").OptionValue = extraConfigs
|
|
|
|
if hasattr(val, 'instanceUuid') and val.instanceUuid is not None:
|
|
if val.instanceUuid == "":
|
|
val.instanceUuid = uuidutils.generate_uuid()
|
|
self.set("summary.config.instanceUuid", val.instanceUuid)
|
|
|
|
try:
|
|
if not hasattr(val, 'deviceChange'):
|
|
return
|
|
|
|
if len(val.deviceChange) < 2:
|
|
return
|
|
|
|
# Case of Reconfig of VM to attach disk
|
|
controller_key = val.deviceChange[0].device.controllerKey
|
|
filename = val.deviceChange[0].device.backing.fileName
|
|
|
|
disk = VirtualDisk()
|
|
disk.controllerKey = controller_key
|
|
|
|
disk_backing = VirtualDiskFlatVer2BackingInfo()
|
|
disk_backing.fileName = filename
|
|
disk_backing.key = -101
|
|
disk.backing = disk_backing
|
|
|
|
controller = VirtualLsiLogicController()
|
|
controller.key = controller_key
|
|
|
|
self.set("config.hardware.device", [disk, controller,
|
|
self.device[0]])
|
|
except AttributeError:
|
|
pass
|
|
|
|
|
|
class Network(ManagedObject):
|
|
"""Network class."""
|
|
|
|
def __init__(self):
|
|
super(Network, self).__init__("network")
|
|
self.set("summary.name", "vmnet0")
|
|
|
|
|
|
class ResourcePool(ManagedObject):
|
|
"""Resource Pool class."""
|
|
|
|
def __init__(self, name="test_ResPool", value="resgroup-test"):
|
|
super(ResourcePool, self).__init__("rp")
|
|
self.set("name", name)
|
|
summary = DataObject()
|
|
runtime = DataObject()
|
|
config = DataObject()
|
|
memory = DataObject()
|
|
cpu = DataObject()
|
|
|
|
memoryAllocation = DataObject()
|
|
cpuAllocation = DataObject()
|
|
vm_list = DataObject()
|
|
|
|
memory.maxUsage = 1000 * units.Mi
|
|
memory.overallUsage = 500 * units.Mi
|
|
cpu.maxUsage = 10000
|
|
cpu.overallUsage = 1000
|
|
runtime.cpu = cpu
|
|
runtime.memory = memory
|
|
summary.runtime = runtime
|
|
cpuAllocation.limit = 10000
|
|
memoryAllocation.limit = 1024
|
|
memoryAllocation.reservation = 1024
|
|
config.memoryAllocation = memoryAllocation
|
|
config.cpuAllocation = cpuAllocation
|
|
vm_list.ManagedObjectReference = []
|
|
self.set("summary", summary)
|
|
self.set("summary.runtime.memory", memory)
|
|
self.set("config", config)
|
|
self.set("vm", vm_list)
|
|
parent = ManagedObjectReference(value=value,
|
|
name=name)
|
|
owner = ManagedObjectReference(value=value,
|
|
name=name)
|
|
self.set("parent", parent)
|
|
self.set("owner", owner)
|
|
|
|
|
|
class DatastoreHostMount(DataObject):
|
|
def __init__(self, value='host-100'):
|
|
super(DatastoreHostMount, self).__init__()
|
|
host_ref = (_db_content["HostSystem"]
|
|
[_db_content["HostSystem"].keys()[0]].obj)
|
|
host_system = DataObject()
|
|
host_system.ManagedObjectReference = [host_ref]
|
|
host_system.value = value
|
|
self.key = host_system
|
|
|
|
|
|
class ClusterComputeResource(ManagedObject):
|
|
"""Cluster class."""
|
|
|
|
def __init__(self, name="test_cluster"):
|
|
super(ClusterComputeResource, self).__init__("domain")
|
|
self.set("name", name)
|
|
self.set("host", None)
|
|
self.set("datastore", None)
|
|
self.set("resourcePool", None)
|
|
|
|
summary = DataObject()
|
|
summary.numHosts = 0
|
|
summary.numCpuCores = 0
|
|
summary.numCpuThreads = 0
|
|
summary.numEffectiveHosts = 0
|
|
summary.totalMemory = 0
|
|
summary.effectiveMemory = 0
|
|
summary.effectiveCpu = 10000
|
|
self.set("summary", summary)
|
|
|
|
def _add_root_resource_pool(self, r_pool):
|
|
if r_pool:
|
|
self.set("resourcePool", r_pool)
|
|
|
|
def _add_host(self, host_sys):
|
|
if host_sys:
|
|
hosts = self.get("host")
|
|
if hosts is None:
|
|
hosts = DataObject()
|
|
hosts.ManagedObjectReference = []
|
|
self.set("host", hosts)
|
|
hosts.ManagedObjectReference.append(host_sys)
|
|
# Update summary every time a new host is added
|
|
self._update_summary()
|
|
|
|
def _add_datastore(self, datastore):
|
|
if datastore:
|
|
datastores = self.get("datastore")
|
|
if datastores is None:
|
|
datastores = DataObject()
|
|
datastores.ManagedObjectReference = []
|
|
self.set("datastore", datastores)
|
|
datastores.ManagedObjectReference.append(datastore)
|
|
|
|
# Method to update summary of a cluster upon host addition
|
|
def _update_summary(self):
|
|
summary = self.get("summary")
|
|
summary.numHosts = 0
|
|
summary.numCpuCores = 0
|
|
summary.numCpuThreads = 0
|
|
summary.numEffectiveHosts = 0
|
|
summary.totalMemory = 0
|
|
summary.effectiveMemory = 0
|
|
|
|
hosts = self.get("host")
|
|
# Compute the aggregate stats
|
|
summary.numHosts = len(hosts.ManagedObjectReference)
|
|
for host_ref in hosts.ManagedObjectReference:
|
|
host_sys = _get_object(host_ref)
|
|
connected = host_sys.get("connected")
|
|
host_summary = host_sys.get("summary")
|
|
summary.numCpuCores += host_summary.hardware.numCpuCores
|
|
summary.numCpuThreads += host_summary.hardware.numCpuThreads
|
|
summary.totalMemory += host_summary.hardware.memorySize
|
|
free_memory = (host_summary.hardware.memorySize / units.Mi
|
|
- host_summary.quickStats.overallMemoryUsage)
|
|
summary.effectiveMemory += free_memory if connected else 0
|
|
summary.numEffectiveHosts += 1 if connected else 0
|
|
self.set("summary", summary)
|
|
|
|
|
|
class Datastore(ManagedObject):
|
|
"""Datastore class."""
|
|
|
|
def __init__(self, name="fake-ds", capacity=1024, free=500):
|
|
super(Datastore, self).__init__("ds")
|
|
self.set("summary.type", "VMFS")
|
|
self.set("summary.name", name)
|
|
self.set("summary.capacity", capacity * units.Gi)
|
|
self.set("summary.freeSpace", free * units.Gi)
|
|
self.set("summary.accessible", True)
|
|
self.set("browser", "")
|
|
|
|
|
|
class HostNetworkSystem(ManagedObject):
|
|
"""HostNetworkSystem class."""
|
|
|
|
def __init__(self, name="networkSystem"):
|
|
super(HostNetworkSystem, self).__init__("ns")
|
|
self.set("name", name)
|
|
|
|
pnic_do = DataObject()
|
|
pnic_do.device = "vmnic0"
|
|
|
|
net_info_pnic = DataObject()
|
|
net_info_pnic.PhysicalNic = [pnic_do]
|
|
|
|
self.set("networkInfo.pnic", net_info_pnic)
|
|
|
|
|
|
class HostStorageSystem(ManagedObject):
|
|
"""HostStorageSystem class."""
|
|
|
|
def __init__(self):
|
|
super(HostStorageSystem, self).__init__("storageSystem")
|
|
|
|
|
|
class HostSystem(ManagedObject):
|
|
"""Host System class."""
|
|
|
|
def __init__(self, name="ha-host", connected=True, ds_ref=None):
|
|
super(HostSystem, self).__init__("host")
|
|
self.set("name", name)
|
|
if _db_content.get("HostNetworkSystem", None) is None:
|
|
create_host_network_system()
|
|
if not _get_object_refs('HostStorageSystem'):
|
|
create_host_storage_system()
|
|
host_net_key = _db_content["HostNetworkSystem"].keys()[0]
|
|
host_net_sys = _db_content["HostNetworkSystem"][host_net_key].obj
|
|
self.set("configManager.networkSystem", host_net_sys)
|
|
host_storage_sys_key = _get_object_refs('HostStorageSystem')[0]
|
|
self.set("configManager.storageSystem", host_storage_sys_key)
|
|
|
|
if not ds_ref:
|
|
ds_ref = create_datastore('local-host-%s' % name, 500, 500)
|
|
datastores = DataObject()
|
|
datastores.ManagedObjectReference = [ds_ref]
|
|
self.set("datastore", datastores)
|
|
|
|
summary = DataObject()
|
|
hardware = DataObject()
|
|
hardware.numCpuCores = 8
|
|
hardware.numCpuPkgs = 2
|
|
hardware.numCpuThreads = 16
|
|
hardware.vendor = "Intel"
|
|
hardware.cpuModel = "Intel(R) Xeon(R)"
|
|
hardware.uuid = "host-uuid"
|
|
hardware.memorySize = units.Gi
|
|
summary.hardware = hardware
|
|
|
|
runtime = DataObject()
|
|
if connected:
|
|
runtime.connectionState = "connected"
|
|
else:
|
|
runtime.connectionState = "disconnected"
|
|
summary.runtime = runtime
|
|
|
|
quickstats = DataObject()
|
|
quickstats.overallMemoryUsage = 500
|
|
summary.quickStats = quickstats
|
|
|
|
product = DataObject()
|
|
product.name = "VMware ESXi"
|
|
product.version = "5.0.0"
|
|
config = DataObject()
|
|
config.product = product
|
|
summary.config = config
|
|
|
|
pnic_do = DataObject()
|
|
pnic_do.device = "vmnic0"
|
|
net_info_pnic = DataObject()
|
|
net_info_pnic.PhysicalNic = [pnic_do]
|
|
|
|
self.set("summary", summary)
|
|
self.set("capability.maxHostSupportedVcpus", 600)
|
|
self.set("summary.runtime.inMaintenanceMode", False)
|
|
self.set("summary.hardware", hardware)
|
|
self.set("summary.runtime", runtime)
|
|
self.set("config.network.pnic", net_info_pnic)
|
|
self.set("connected", connected)
|
|
|
|
if _db_content.get("Network", None) is None:
|
|
create_network()
|
|
net_ref = _db_content["Network"][_db_content["Network"].keys()[0]].obj
|
|
network_do = DataObject()
|
|
network_do.ManagedObjectReference = [net_ref]
|
|
self.set("network", network_do)
|
|
|
|
vswitch_do = DataObject()
|
|
vswitch_do.pnic = ["vmnic0"]
|
|
vswitch_do.name = "vSwitch0"
|
|
vswitch_do.portgroup = ["PortGroup-vmnet0"]
|
|
|
|
net_swicth = DataObject()
|
|
net_swicth.HostVirtualSwitch = [vswitch_do]
|
|
self.set("config.network.vswitch", net_swicth)
|
|
|
|
host_pg_do = DataObject()
|
|
host_pg_do.key = "PortGroup-vmnet0"
|
|
|
|
pg_spec = DataObject()
|
|
pg_spec.vlanId = 0
|
|
pg_spec.name = "vmnet0"
|
|
|
|
host_pg_do.spec = pg_spec
|
|
|
|
host_pg = DataObject()
|
|
host_pg.HostPortGroup = [host_pg_do]
|
|
self.set("config.network.portgroup", host_pg)
|
|
|
|
config = DataObject()
|
|
storageDevice = DataObject()
|
|
|
|
iscsi_hba = HostInternetScsiHba()
|
|
iscsi_hba.iScsiName = "iscsi-name"
|
|
host_bus_adapter_array = DataObject()
|
|
host_bus_adapter_array.HostHostBusAdapter = [iscsi_hba]
|
|
storageDevice.hostBusAdapter = host_bus_adapter_array
|
|
config.storageDevice = storageDevice
|
|
self.set("config.storageDevice.hostBusAdapter", host_bus_adapter_array)
|
|
|
|
# Set the same on the storage system managed object
|
|
host_storage_sys = _get_object(host_storage_sys_key)
|
|
host_storage_sys.set('storageDeviceInfo.hostBusAdapter',
|
|
host_bus_adapter_array)
|
|
|
|
def _add_iscsi_target(self, data):
|
|
default_lun = DataObject()
|
|
default_lun.scsiLun = 'key-vim.host.ScsiDisk-010'
|
|
default_lun.key = 'key-vim.host.ScsiDisk-010'
|
|
default_lun.deviceName = 'fake-device'
|
|
default_lun.uuid = 'fake-uuid'
|
|
scsi_lun_array = DataObject()
|
|
scsi_lun_array.ScsiLun = [default_lun]
|
|
self.set("config.storageDevice.scsiLun", scsi_lun_array)
|
|
|
|
transport = DataObject()
|
|
transport.address = [data['target_portal']]
|
|
transport.iScsiName = data['target_iqn']
|
|
default_target = DataObject()
|
|
default_target.lun = [default_lun]
|
|
default_target.transport = transport
|
|
|
|
iscsi_adapter = DataObject()
|
|
iscsi_adapter.adapter = 'key-vmhba33'
|
|
iscsi_adapter.transport = transport
|
|
iscsi_adapter.target = [default_target]
|
|
iscsi_topology = DataObject()
|
|
iscsi_topology.adapter = [iscsi_adapter]
|
|
self.set("config.storageDevice.scsiTopology", iscsi_topology)
|
|
|
|
def _add_port_group(self, spec):
|
|
"""Adds a port group to the host system object in the db."""
|
|
pg_name = spec.name
|
|
vswitch_name = spec.vswitchName
|
|
vlanid = spec.vlanId
|
|
|
|
vswitch_do = DataObject()
|
|
vswitch_do.pnic = ["vmnic0"]
|
|
vswitch_do.name = vswitch_name
|
|
vswitch_do.portgroup = ["PortGroup-%s" % pg_name]
|
|
|
|
vswitches = self.get("config.network.vswitch").HostVirtualSwitch
|
|
vswitches.append(vswitch_do)
|
|
|
|
host_pg_do = DataObject()
|
|
host_pg_do.key = "PortGroup-%s" % pg_name
|
|
|
|
pg_spec = DataObject()
|
|
pg_spec.vlanId = vlanid
|
|
pg_spec.name = pg_name
|
|
|
|
host_pg_do.spec = pg_spec
|
|
host_pgrps = self.get("config.network.portgroup").HostPortGroup
|
|
host_pgrps.append(host_pg_do)
|
|
|
|
|
|
class Datacenter(ManagedObject):
|
|
"""Datacenter class."""
|
|
|
|
def __init__(self, name="ha-datacenter", ds_ref=None):
|
|
super(Datacenter, self).__init__("dc")
|
|
self.set("name", name)
|
|
self.set("vmFolder", "vm_folder_ref")
|
|
if _db_content.get("Network", None) is None:
|
|
create_network()
|
|
net_ref = _db_content["Network"][_db_content["Network"].keys()[0]].obj
|
|
network_do = DataObject()
|
|
network_do.ManagedObjectReference = [net_ref]
|
|
self.set("network", network_do)
|
|
if ds_ref:
|
|
datastore = DataObject()
|
|
datastore.ManagedObjectReference = [ds_ref]
|
|
else:
|
|
datastore = None
|
|
self.set("datastore", datastore)
|
|
|
|
|
|
class Task(ManagedObject):
|
|
"""Task class."""
|
|
|
|
def __init__(self, task_name, state="running", result=None,
|
|
error_fault=None):
|
|
super(Task, self).__init__("Task")
|
|
info = DataObject()
|
|
info.name = task_name
|
|
info.state = state
|
|
if state == 'error':
|
|
error = DataObject()
|
|
error.localizedMessage = "Error message"
|
|
if not error_fault:
|
|
error.fault = DataObject()
|
|
else:
|
|
error.fault = error_fault
|
|
info.error = error
|
|
info.result = result
|
|
self.set("info", info)
|
|
|
|
|
|
def create_host_network_system():
|
|
host_net_system = HostNetworkSystem()
|
|
_create_object("HostNetworkSystem", host_net_system)
|
|
|
|
|
|
def create_host_storage_system():
|
|
host_storage_system = HostStorageSystem()
|
|
_create_object("HostStorageSystem", host_storage_system)
|
|
|
|
|
|
def create_host(ds_ref=None):
|
|
host_system = HostSystem(ds_ref=ds_ref)
|
|
_create_object('HostSystem', host_system)
|
|
|
|
|
|
def create_datacenter(name, ds_ref=None):
|
|
data_center = Datacenter(name, ds_ref)
|
|
_create_object('Datacenter', data_center)
|
|
|
|
|
|
def create_datastore(name, capacity, free):
|
|
data_store = Datastore(name, capacity, free)
|
|
_create_object('Datastore', data_store)
|
|
return data_store.obj
|
|
|
|
|
|
def create_res_pool():
|
|
res_pool = ResourcePool()
|
|
_create_object('ResourcePool', res_pool)
|
|
return res_pool.obj
|
|
|
|
|
|
def create_network():
|
|
network = Network()
|
|
_create_object('Network', network)
|
|
|
|
|
|
def create_cluster(name, ds_ref):
|
|
cluster = ClusterComputeResource(name=name)
|
|
cluster._add_host(_get_object_refs("HostSystem")[0])
|
|
cluster._add_host(_get_object_refs("HostSystem")[1])
|
|
cluster._add_datastore(ds_ref)
|
|
cluster._add_root_resource_pool(create_res_pool())
|
|
_create_object('ClusterComputeResource', cluster)
|
|
|
|
|
|
def create_task(task_name, state="running", result=None, error_fault=None):
|
|
task = Task(task_name, state, result, error_fault)
|
|
_create_object("Task", task)
|
|
return task
|
|
|
|
|
|
def _add_file(file_path):
|
|
"""Adds a file reference to the db."""
|
|
_db_content["files"].append(file_path)
|
|
|
|
|
|
def _remove_file(file_path):
|
|
"""Removes a file reference from the db."""
|
|
if _db_content.get("files") is None:
|
|
raise exception.NoFilesFound()
|
|
# Check if the remove is for a single file object or for a folder
|
|
if file_path.find(".vmdk") != -1:
|
|
if file_path not in _db_content.get("files"):
|
|
raise exception.FileNotFound(file_path=file_path)
|
|
_db_content.get("files").remove(file_path)
|
|
else:
|
|
# Removes the files in the folder and the folder too from the db
|
|
to_delete = set()
|
|
for file in _db_content.get("files"):
|
|
if file.find(file_path) != -1:
|
|
to_delete.add(file)
|
|
for file in to_delete:
|
|
_db_content.get("files").remove(file)
|
|
|
|
|
|
def fake_plug_vifs(*args, **kwargs):
|
|
"""Fakes plugging vifs."""
|
|
pass
|
|
|
|
|
|
def fake_get_network(*args, **kwargs):
|
|
"""Fake get network."""
|
|
return {'type': 'fake'}
|
|
|
|
|
|
def get_file(file_path):
|
|
"""Check if file exists in the db."""
|
|
if _db_content.get("files") is None:
|
|
raise exception.NoFilesFound()
|
|
return file_path in _db_content.get("files")
|
|
|
|
|
|
def fake_upload_image(context, image, instance, **kwargs):
|
|
"""Fakes the upload of an image."""
|
|
pass
|
|
|
|
|
|
def fake_get_vmdk_size_and_properties(context, image_id, instance):
|
|
"""Fakes the file size and properties fetch for the image file."""
|
|
props = {"vmware_ostype": "otherGuest",
|
|
"vmware_adaptertype": "lsiLogic"}
|
|
return _FAKE_FILE_SIZE, props
|
|
|
|
|
|
def _get_vm_mdo(vm_ref):
|
|
"""Gets the Virtual Machine with the ref from the db."""
|
|
if _db_content.get("VirtualMachine", None) is None:
|
|
raise exception.NotFound(_("There is no VM registered"))
|
|
if vm_ref not in _db_content.get("VirtualMachine"):
|
|
raise exception.NotFound(_("Virtual Machine with ref %s is not "
|
|
"there") % vm_ref)
|
|
return _db_content.get("VirtualMachine")[vm_ref]
|
|
|
|
|
|
def _merge_extraconfig(existing, changes):
|
|
"""Imposes the changes in extraConfig over the existing extraConfig."""
|
|
existing = existing or []
|
|
if (changes):
|
|
for c in changes:
|
|
if len([x for x in existing if x.key == c.key]) > 0:
|
|
extraConf = [x for x in existing if x.key == c.key][0]
|
|
extraConf.value = c.value
|
|
else:
|
|
existing.append(c)
|
|
return existing
|
|
|
|
|
|
class FakeFactory(object):
|
|
"""Fake factory class for the suds client."""
|
|
|
|
def create(self, obj_name):
|
|
"""Creates a namespace object."""
|
|
return DataObject(obj_name)
|
|
|
|
|
|
class FakeVim(object):
|
|
"""Fake VIM Class."""
|
|
|
|
def __init__(self, protocol="https", host="localhost", trace=None):
|
|
"""Initializes the suds client object, sets the service content
|
|
contents and the cookies for the session.
|
|
"""
|
|
self._session = None
|
|
self.client = DataObject()
|
|
self.client.factory = FakeFactory()
|
|
|
|
transport = DataObject()
|
|
transport.cookiejar = "Fake-CookieJar"
|
|
options = DataObject()
|
|
options.transport = transport
|
|
|
|
self.client.options = options
|
|
|
|
service_content = self.client.factory.create('ns0:ServiceContent')
|
|
service_content.propertyCollector = "PropCollector"
|
|
service_content.virtualDiskManager = "VirtualDiskManager"
|
|
service_content.fileManager = "FileManager"
|
|
service_content.rootFolder = "RootFolder"
|
|
service_content.sessionManager = "SessionManager"
|
|
service_content.searchIndex = "SearchIndex"
|
|
|
|
about_info = DataObject()
|
|
about_info.name = "VMware vCenter Server"
|
|
about_info.version = "5.1.0"
|
|
service_content.about = about_info
|
|
|
|
self._service_content = service_content
|
|
|
|
def get_service_content(self):
|
|
return self._service_content
|
|
|
|
def __repr__(self):
|
|
return "Fake VIM Object"
|
|
|
|
def __str__(self):
|
|
return "Fake VIM Object"
|
|
|
|
def _login(self):
|
|
"""Logs in and sets the session object in the db."""
|
|
self._session = uuidutils.generate_uuid()
|
|
session = DataObject()
|
|
session.key = self._session
|
|
session.userName = 'sessionUserName'
|
|
_db_content['session'][self._session] = session
|
|
return session
|
|
|
|
def _logout(self):
|
|
"""Logs out and remove the session object ref from the db."""
|
|
s = self._session
|
|
self._session = None
|
|
if s not in _db_content['session']:
|
|
raise exception.NovaException(
|
|
_("Logging out a session that is invalid or already logged "
|
|
"out: %s") % s)
|
|
del _db_content['session'][s]
|
|
|
|
def _terminate_session(self, *args, **kwargs):
|
|
"""Terminates a session."""
|
|
s = kwargs.get("sessionId")[0]
|
|
if s not in _db_content['session']:
|
|
return
|
|
del _db_content['session'][s]
|
|
|
|
def _check_session(self):
|
|
"""Checks if the session is active."""
|
|
if (self._session is None or self._session not in
|
|
_db_content['session']):
|
|
LOG.debug(_("Session is faulty"))
|
|
raise error_util.VimFaultException(
|
|
[error_util.NOT_AUTHENTICATED],
|
|
_("Session Invalid"))
|
|
|
|
def _session_is_active(self, *args, **kwargs):
|
|
try:
|
|
self._check_session()
|
|
return True
|
|
except Exception:
|
|
return False
|
|
|
|
def _create_vm(self, method, *args, **kwargs):
|
|
"""Creates and registers a VM object with the Host System."""
|
|
config_spec = kwargs.get("config")
|
|
pool = kwargs.get('pool')
|
|
ds = _db_content["Datastore"].keys()[0]
|
|
host = _db_content["HostSystem"].keys()[0]
|
|
vm_dict = {"name": config_spec.name,
|
|
"ds": [ds],
|
|
"runtime_host": host,
|
|
"powerstate": "poweredOff",
|
|
"vmPathName": config_spec.files.vmPathName,
|
|
"numCpu": config_spec.numCPUs,
|
|
"mem": config_spec.memoryMB,
|
|
"extra_config": config_spec.extraConfig,
|
|
"virtual_device": config_spec.deviceChange,
|
|
"instanceUuid": config_spec.instanceUuid}
|
|
virtual_machine = VirtualMachine(**vm_dict)
|
|
_create_object("VirtualMachine", virtual_machine)
|
|
res_pool = _get_object(pool)
|
|
res_pool.vm.ManagedObjectReference.append(virtual_machine.obj)
|
|
task_mdo = create_task(method, "success", result=virtual_machine.obj)
|
|
return task_mdo.obj
|
|
|
|
def _reconfig_vm(self, method, *args, **kwargs):
|
|
"""Reconfigures a VM and sets the properties supplied."""
|
|
vm_ref = args[0]
|
|
vm_mdo = _get_vm_mdo(vm_ref)
|
|
vm_mdo.reconfig(self.client.factory, kwargs.get("spec"))
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def _create_copy_disk(self, method, vmdk_file_path):
|
|
"""Creates/copies a vmdk file object in the datastore."""
|
|
# We need to add/create both .vmdk and .-flat.vmdk files
|
|
flat_vmdk_file_path = vmdk_file_path.replace(".vmdk", "-flat.vmdk")
|
|
_add_file(vmdk_file_path)
|
|
_add_file(flat_vmdk_file_path)
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def _extend_disk(self, method, size):
|
|
"""Extend disk size when create a instance."""
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def _snapshot_vm(self, method):
|
|
"""Snapshots a VM. Here we do nothing for faking sake."""
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def _find_all_by_uuid(self, *args, **kwargs):
|
|
uuid = kwargs.get('uuid')
|
|
vm_refs = []
|
|
for vm_ref in _db_content.get("VirtualMachine"):
|
|
vm = _get_object(vm_ref)
|
|
vm_uuid = vm.get("summary.config.instanceUuid")
|
|
if vm_uuid == uuid:
|
|
vm_refs.append(vm_ref)
|
|
return vm_refs
|
|
|
|
def _delete_snapshot(self, method, *args, **kwargs):
|
|
"""Deletes a VM snapshot. Here we do nothing for faking sake."""
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def _delete_disk(self, method, *args, **kwargs):
|
|
"""Deletes .vmdk and -flat.vmdk files corresponding to the VM."""
|
|
vmdk_file_path = kwargs.get("name")
|
|
flat_vmdk_file_path = vmdk_file_path.replace(".vmdk", "-flat.vmdk")
|
|
_remove_file(vmdk_file_path)
|
|
_remove_file(flat_vmdk_file_path)
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def _delete_file(self, method, *args, **kwargs):
|
|
"""Deletes a file from the datastore."""
|
|
_remove_file(kwargs.get("name"))
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def _just_return(self):
|
|
"""Fakes a return."""
|
|
return
|
|
|
|
def _just_return_task(self, method):
|
|
"""Fakes a task return."""
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def _clone_vm(self, method, *args, **kwargs):
|
|
"""Fakes a VM clone."""
|
|
"""Creates and registers a VM object with the Host System."""
|
|
source_vmref = args[0]
|
|
source_vm_mdo = _get_vm_mdo(source_vmref)
|
|
clone_spec = kwargs.get("spec")
|
|
ds = _db_content["Datastore"].keys()[0]
|
|
host = _db_content["HostSystem"].keys()[0]
|
|
vm_dict = {
|
|
"name": kwargs.get("name"),
|
|
"ds": source_vm_mdo.get("datastore"),
|
|
"runtime_host": source_vm_mdo.get("runtime.host"),
|
|
"powerstate": source_vm_mdo.get("runtime.powerState"),
|
|
"vmPathName": source_vm_mdo.get("config.files.vmPathName"),
|
|
"numCpu": source_vm_mdo.get("summary.config.numCpu"),
|
|
"mem": source_vm_mdo.get("summary.config.memorySizeMB"),
|
|
"extra_config": source_vm_mdo.get("config.extraConfig").OptionValue,
|
|
"virtual_device": source_vm_mdo.get("config.hardware.device"),
|
|
"instanceUuid": source_vm_mdo.get("summary.config.instanceUuid")}
|
|
|
|
if clone_spec.config is not None:
|
|
# Impose the config changes specified in the config property
|
|
if (hasattr(clone_spec.config, 'instanceUuid') and
|
|
clone_spec.config.instanceUuid is not None):
|
|
vm_dict["instanceUuid"] = clone_spec.config.instanceUuid
|
|
|
|
if hasattr(clone_spec.config, 'extraConfig'):
|
|
extraConfigs = _merge_extraconfig(vm_dict["extra_config"],
|
|
clone_spec.config.extraConfig)
|
|
vm_dict["extra_config"] = extraConfigs
|
|
|
|
virtual_machine = VirtualMachine(**vm_dict)
|
|
_create_object("VirtualMachine", virtual_machine)
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def _unregister_vm(self, method, *args, **kwargs):
|
|
"""Unregisters a VM from the Host System."""
|
|
vm_ref = args[0]
|
|
_get_vm_mdo(vm_ref)
|
|
del _db_content["VirtualMachine"][vm_ref]
|
|
|
|
def _search_ds(self, method, *args, **kwargs):
|
|
"""Searches the datastore for a file."""
|
|
# TODO(garyk): add support for spec parameter
|
|
ds_path = kwargs.get("datastorePath")
|
|
if _db_content.get("files", None) is None:
|
|
raise exception.NoFilesFound()
|
|
matched_files = set()
|
|
# Check if we are searching for a file or a directory
|
|
directory = False
|
|
dname = '%s/' % ds_path
|
|
for file in _db_content.get("files"):
|
|
if file == dname:
|
|
directory = True
|
|
break
|
|
# A directory search implies that we must return all
|
|
# subdirectories
|
|
if directory:
|
|
for file in _db_content.get("files"):
|
|
if file.find(ds_path) != -1:
|
|
if not file.endswith(ds_path):
|
|
path = file.lstrip(dname).split('/')
|
|
if path:
|
|
matched_files.add(path[0])
|
|
if not matched_files:
|
|
matched_files.add('/')
|
|
else:
|
|
for file in _db_content.get("files"):
|
|
if file.find(ds_path) != -1:
|
|
matched_files.add(ds_path)
|
|
if matched_files:
|
|
result = DataObject()
|
|
result.path = ds_path
|
|
result.file = []
|
|
for file in matched_files:
|
|
matched = DataObject()
|
|
matched.path = file
|
|
result.file.append(matched)
|
|
task_mdo = create_task(method, "success", result=result)
|
|
else:
|
|
task_mdo = create_task(method, "error",
|
|
error_fault=FileNotFound())
|
|
return task_mdo.obj
|
|
|
|
def _move_file(self, method, *args, **kwargs):
|
|
source = kwargs.get('sourceName')
|
|
destination = kwargs.get('destinationName')
|
|
new_files = []
|
|
if source != destination:
|
|
for file in _db_content.get("files"):
|
|
if source in file:
|
|
new_file = file.replace(source, destination)
|
|
new_files.append(new_file)
|
|
# if source is not a file then the children will also
|
|
# be deleted
|
|
_remove_file(source)
|
|
for file in new_files:
|
|
_add_file(file)
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def fake_transfer_file(self, ds_name, file_path):
|
|
"""Fakes fetch image call.
|
|
Just adds a reference to the db for the file.
|
|
"""
|
|
ds_file_path = "[" + ds_name + "] " + file_path
|
|
_add_file(ds_file_path)
|
|
|
|
def _make_dir(self, method, *args, **kwargs):
|
|
"""Creates a directory in the datastore."""
|
|
ds_path = kwargs.get("name")
|
|
if _db_content.get("files", None) is None:
|
|
raise exception.NoFilesFound()
|
|
if get_file(ds_path):
|
|
raise error_util.FileAlreadyExistsException()
|
|
_db_content["files"].append('%s/' % ds_path)
|
|
|
|
def _set_power_state(self, method, vm_ref, pwr_state="poweredOn"):
|
|
"""Sets power state for the VM."""
|
|
if _db_content.get("VirtualMachine", None) is None:
|
|
raise exception.NotFound(_("No Virtual Machine has been "
|
|
"registered yet"))
|
|
if vm_ref not in _db_content.get("VirtualMachine"):
|
|
raise exception.NotFound(_("Virtual Machine with ref %s is not "
|
|
"there") % vm_ref)
|
|
vm_mdo = _db_content.get("VirtualMachine").get(vm_ref)
|
|
vm_mdo.set("runtime.powerState", pwr_state)
|
|
task_mdo = create_task(method, "success")
|
|
return task_mdo.obj
|
|
|
|
def _retrieve_properties_continue(self, method, *args, **kwargs):
|
|
"""Continues the retrieve."""
|
|
return FakeRetrieveResult()
|
|
|
|
def _retrieve_properties_cancel(self, method, *args, **kwargs):
|
|
"""Cancels the retrieve."""
|
|
return None
|
|
|
|
def _retrieve_properties(self, method, *args, **kwargs):
|
|
"""Retrieves properties based on the type."""
|
|
spec_set = kwargs.get("specSet")[0]
|
|
spec_type = spec_set.propSet[0].type
|
|
properties = spec_set.propSet[0].pathSet
|
|
if not isinstance(properties, list):
|
|
properties = properties.split()
|
|
objs = spec_set.objectSet
|
|
lst_ret_objs = FakeRetrieveResult()
|
|
for obj in objs:
|
|
try:
|
|
obj_ref = obj.obj
|
|
if obj_ref == "RootFolder":
|
|
# This means that we are retrieving props for all managed
|
|
# data objects of the specified 'type' in the entire
|
|
# inventory. This gets invoked by vim_util.get_objects.
|
|
mdo_refs = _db_content[spec_type]
|
|
elif obj_ref.type != spec_type:
|
|
# This means that we are retrieving props for the managed
|
|
# data objects in the parent object's 'path' property.
|
|
# This gets invoked by vim_util.get_inner_objects
|
|
# eg. obj_ref = <ManagedObjectReference of a cluster>
|
|
# type = 'DataStore'
|
|
# path = 'datastore'
|
|
# the above will retrieve all datastores in the given
|
|
# cluster.
|
|
parent_mdo = _db_content[obj_ref.type][obj_ref]
|
|
path = obj.selectSet[0].path
|
|
mdo_refs = parent_mdo.get(path).ManagedObjectReference
|
|
else:
|
|
# This means that we are retrieving props of the given
|
|
# managed data object. This gets invoked by
|
|
# vim_util.get_properties_for_a_collection_of_objects.
|
|
mdo_refs = [obj_ref]
|
|
|
|
for mdo_ref in mdo_refs:
|
|
mdo = _db_content[spec_type][mdo_ref]
|
|
prop_list = []
|
|
for prop_name in properties:
|
|
prop = Prop(prop_name, mdo.get(prop_name))
|
|
prop_list.append(prop)
|
|
obj_content = ObjectContent(mdo.obj, prop_list)
|
|
lst_ret_objs.add_object(obj_content)
|
|
except Exception as exc:
|
|
LOG.exception(exc)
|
|
continue
|
|
return lst_ret_objs
|
|
|
|
def _add_port_group(self, method, *args, **kwargs):
|
|
"""Adds a port group to the host system."""
|
|
_host_sk = _db_content["HostSystem"].keys()[0]
|
|
host_mdo = _db_content["HostSystem"][_host_sk]
|
|
host_mdo._add_port_group(kwargs.get("portgrp"))
|
|
|
|
def _add_iscsi_send_tgt(self, method, *args, **kwargs):
|
|
"""Adds a iscsi send target to the hba."""
|
|
send_targets = kwargs.get('targets')
|
|
host_storage_sys = _get_objects('HostStorageSystem').objects[0]
|
|
iscsi_hba_array = host_storage_sys.get('storageDeviceInfo'
|
|
'.hostBusAdapter')
|
|
iscsi_hba = iscsi_hba_array.HostHostBusAdapter[0]
|
|
if hasattr(iscsi_hba, 'configuredSendTarget'):
|
|
iscsi_hba.configuredSendTarget.extend(send_targets)
|
|
else:
|
|
iscsi_hba.configuredSendTarget = send_targets
|
|
|
|
def __getattr__(self, attr_name):
|
|
if attr_name != "Login":
|
|
self._check_session()
|
|
if attr_name == "Login":
|
|
return lambda *args, **kwargs: self._login()
|
|
elif attr_name == "Logout":
|
|
self._logout()
|
|
elif attr_name == "SessionIsActive":
|
|
return lambda *args, **kwargs: self._session_is_active(
|
|
*args, **kwargs)
|
|
elif attr_name == "TerminateSession":
|
|
return lambda *args, **kwargs: self._terminate_session(
|
|
*args, **kwargs)
|
|
elif attr_name == "CreateVM_Task":
|
|
return lambda *args, **kwargs: self._create_vm(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "ReconfigVM_Task":
|
|
return lambda *args, **kwargs: self._reconfig_vm(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "CreateVirtualDisk_Task":
|
|
return lambda *args, **kwargs: self._create_copy_disk(attr_name,
|
|
kwargs.get("name"))
|
|
elif attr_name == "DeleteDatastoreFile_Task":
|
|
return lambda *args, **kwargs: self._delete_file(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "PowerOnVM_Task":
|
|
return lambda *args, **kwargs: self._set_power_state(attr_name,
|
|
args[0], "poweredOn")
|
|
elif attr_name == "PowerOffVM_Task":
|
|
return lambda *args, **kwargs: self._set_power_state(attr_name,
|
|
args[0], "poweredOff")
|
|
elif attr_name == "RebootGuest":
|
|
return lambda *args, **kwargs: self._just_return()
|
|
elif attr_name == "ResetVM_Task":
|
|
return lambda *args, **kwargs: self._set_power_state(attr_name,
|
|
args[0], "poweredOn")
|
|
elif attr_name == "SuspendVM_Task":
|
|
return lambda *args, **kwargs: self._set_power_state(attr_name,
|
|
args[0], "suspended")
|
|
elif attr_name == "CreateSnapshot_Task":
|
|
return lambda *args, **kwargs: self._snapshot_vm(attr_name)
|
|
elif attr_name == "RemoveSnapshot_Task":
|
|
return lambda *args, **kwargs: self._delete_snapshot(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "CopyVirtualDisk_Task":
|
|
return lambda *args, **kwargs: self._create_copy_disk(attr_name,
|
|
kwargs.get("destName"))
|
|
elif attr_name == "ExtendVirtualDisk_Task":
|
|
return lambda *args, **kwargs: self._extend_disk(attr_name,
|
|
kwargs.get("size"))
|
|
elif attr_name == "Destroy_Task":
|
|
return lambda *args, **kwargs: self._unregister_vm(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "UnregisterVM":
|
|
return lambda *args, **kwargs: self._unregister_vm(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "CloneVM_Task":
|
|
return lambda *args, **kwargs: self._clone_vm(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "FindAllByUuid":
|
|
return lambda *args, **kwargs: self._find_all_by_uuid(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "Rename_Task":
|
|
return lambda *args, **kwargs: self._just_return_task(attr_name)
|
|
elif attr_name == "SearchDatastore_Task":
|
|
return lambda *args, **kwargs: self._search_ds(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "MoveDatastoreFile_Task":
|
|
return lambda *args, **kwargs: self._move_file(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "MakeDirectory":
|
|
return lambda *args, **kwargs: self._make_dir(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "RetrievePropertiesEx":
|
|
return lambda *args, **kwargs: self._retrieve_properties(
|
|
attr_name, *args, **kwargs)
|
|
elif attr_name == "ContinueRetrievePropertiesEx":
|
|
return lambda *args, **kwargs: self._retrieve_properties_continue(
|
|
attr_name, *args, **kwargs)
|
|
elif attr_name == "CancelRetrievePropertiesEx":
|
|
return lambda *args, **kwargs: self._retrieve_properties_cancel(
|
|
attr_name, *args, **kwargs)
|
|
elif attr_name == "AcquireCloneTicket":
|
|
return lambda *args, **kwargs: self._just_return()
|
|
elif attr_name == "AddPortGroup":
|
|
return lambda *args, **kwargs: self._add_port_group(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "RebootHost_Task":
|
|
return lambda *args, **kwargs: self._just_return_task(attr_name)
|
|
elif attr_name == "ShutdownHost_Task":
|
|
return lambda *args, **kwargs: self._just_return_task(attr_name)
|
|
elif attr_name == "PowerDownHostToStandBy_Task":
|
|
return lambda *args, **kwargs: self._just_return_task(attr_name)
|
|
elif attr_name == "PowerUpHostFromStandBy_Task":
|
|
return lambda *args, **kwargs: self._just_return_task(attr_name)
|
|
elif attr_name == "EnterMaintenanceMode_Task":
|
|
return lambda *args, **kwargs: self._just_return_task(attr_name)
|
|
elif attr_name == "ExitMaintenanceMode_Task":
|
|
return lambda *args, **kwargs: self._just_return_task(attr_name)
|
|
elif attr_name == "AddInternetScsiSendTargets":
|
|
return lambda *args, **kwargs: self._add_iscsi_send_tgt(attr_name,
|
|
*args, **kwargs)
|
|
elif attr_name == "RescanHba":
|
|
return lambda *args, **kwargs: self._just_return_task(attr_name)
|