summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark McLoughlin <markmc@redhat.com>2012-01-25 11:57:25 +0000
committerMark McLoughlin <markmc@redhat.com>2012-01-25 12:08:12 +0000
commit50f3198477253d730d11d42215efe7e527a230d0 (patch)
treea1a9993233fa5682906bad271980f813aec33f58
parent99daaea663ade3839142f538427faa85d0e64c8f (diff)
Convert vmwareapi code to UNIX style line endings
It's the only code in the codebase using evil CRLF line endings. Change-Id: I8b1a2b12a5707fbd4d32588c081599beaa34aca5
-rw-r--r--nova/tests/vmwareapi/__init__.py42
-rw-r--r--nova/tests/vmwareapi/db_fakes.py218
-rw-r--r--nova/tests/vmwareapi/stubs.py102
-rw-r--r--nova/virt/vmwareapi/error_util.py192
-rw-r--r--nova/virt/vmwareapi/fake.py1438
-rw-r--r--nova/virt/vmwareapi/io_util.py338
-rw-r--r--nova/virt/vmwareapi/network_utils.py340
-rw-r--r--nova/virt/vmwareapi/read_write_util.py358
-rw-r--r--nova/virt/vmwareapi/vim.py362
-rw-r--r--nova/virt/vmwareapi/vim_util.py446
-rw-r--r--nova/virt/vmwareapi/vm_util.py650
-rw-r--r--nova/virt/vmwareapi/vmops.py1648
-rw-r--r--nova/virt/vmwareapi/vmware_images.py290
13 files changed, 3212 insertions, 3212 deletions
diff --git a/nova/tests/vmwareapi/__init__.py b/nova/tests/vmwareapi/__init__.py
index 478ee742b..228186621 100644
--- a/nova/tests/vmwareapi/__init__.py
+++ b/nova/tests/vmwareapi/__init__.py
@@ -1,21 +1,21 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""
-:mod:`vmwareapi` -- Stubs for VMware API
-=======================================
-"""
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""
+:mod:`vmwareapi` -- Stubs for VMware API
+=======================================
+"""
diff --git a/nova/tests/vmwareapi/db_fakes.py b/nova/tests/vmwareapi/db_fakes.py
index 1425a8751..ab2c01580 100644
--- a/nova/tests/vmwareapi/db_fakes.py
+++ b/nova/tests/vmwareapi/db_fakes.py
@@ -1,109 +1,109 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""
-Stubouts, mocks and fixtures for the test suite
-"""
-
-import time
-
-from nova import db
-from nova import utils
-from nova.compute import task_states
-from nova.compute import vm_states
-
-
-def stub_out_db_instance_api(stubs):
- """Stubs out the db API for creating Instances."""
-
- INSTANCE_TYPES = {
- 'm1.tiny': dict(memory_mb=512, vcpus=1, root_gb=0, flavorid=1),
- 'm1.small': dict(memory_mb=2048, vcpus=1, root_gb=20, flavorid=2),
- 'm1.medium':
- dict(memory_mb=4096, vcpus=2, root_gb=40, flavorid=3),
- 'm1.large': dict(memory_mb=8192, vcpus=4, root_gb=80, flavorid=4),
- 'm1.xlarge':
- dict(memory_mb=16384, vcpus=8, root_gb=160, flavorid=5)}
-
- class FakeModel(object):
- """Stubs out for model."""
-
- def __init__(self, values):
- self.values = values
-
- def __getattr__(self, name):
- return self.values[name]
-
- def __getitem__(self, key):
- if key in self.values:
- return self.values[key]
- else:
- raise NotImplementedError()
-
- def fake_instance_create(context, values):
- """Stubs out the db.instance_create method."""
-
- type_data = INSTANCE_TYPES[values['instance_type']]
-
- base_options = {
- 'name': values['name'],
- 'id': values['id'],
- 'uuid': utils.gen_uuid(),
- 'reservation_id': utils.generate_uid('r'),
- 'image_ref': values['image_ref'],
- 'kernel_id': values['kernel_id'],
- 'ramdisk_id': values['ramdisk_id'],
- 'vm_state': vm_states.BUILDING,
- 'task_state': task_states.SCHEDULING,
- 'user_id': values['user_id'],
- 'project_id': values['project_id'],
- 'launch_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
- 'instance_type': values['instance_type'],
- 'memory_mb': type_data['memory_mb'],
- 'vcpus': type_data['vcpus'],
- 'mac_addresses': [{'address': values['mac_address']}],
- 'root_gb': type_data['root_gb'],
- }
- return FakeModel(base_options)
-
- def fake_network_get_by_instance(context, instance_id):
- """Stubs out the db.network_get_by_instance method."""
-
- fields = {
- 'bridge': 'vmnet0',
- 'netmask': '255.255.255.0',
- 'gateway': '10.10.10.1',
- 'broadcast': '10.10.10.255',
- 'dns1': 'fake',
- 'vlan': 100}
- return FakeModel(fields)
-
- def fake_instance_action_create(context, action):
- """Stubs out the db.instance_action_create method."""
- pass
-
- def fake_instance_type_get_all(context, inactive=0, filters=None):
- return INSTANCE_TYPES.values()
-
- def fake_instance_type_get_by_name(context, name):
- return INSTANCE_TYPES[name]
-
- stubs.Set(db, 'instance_create', fake_instance_create)
- stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance)
- stubs.Set(db, 'instance_action_create', fake_instance_action_create)
- stubs.Set(db, 'instance_type_get_all', fake_instance_type_get_all)
- stubs.Set(db, 'instance_type_get_by_name', fake_instance_type_get_by_name)
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""
+Stubouts, mocks and fixtures for the test suite
+"""
+
+import time
+
+from nova import db
+from nova import utils
+from nova.compute import task_states
+from nova.compute import vm_states
+
+
+def stub_out_db_instance_api(stubs):
+ """Stubs out the db API for creating Instances."""
+
+ INSTANCE_TYPES = {
+ 'm1.tiny': dict(memory_mb=512, vcpus=1, root_gb=0, flavorid=1),
+ 'm1.small': dict(memory_mb=2048, vcpus=1, root_gb=20, flavorid=2),
+ 'm1.medium':
+ dict(memory_mb=4096, vcpus=2, root_gb=40, flavorid=3),
+ 'm1.large': dict(memory_mb=8192, vcpus=4, root_gb=80, flavorid=4),
+ 'm1.xlarge':
+ dict(memory_mb=16384, vcpus=8, root_gb=160, flavorid=5)}
+
+ class FakeModel(object):
+ """Stubs out for model."""
+
+ def __init__(self, values):
+ self.values = values
+
+ def __getattr__(self, name):
+ return self.values[name]
+
+ def __getitem__(self, key):
+ if key in self.values:
+ return self.values[key]
+ else:
+ raise NotImplementedError()
+
+ def fake_instance_create(context, values):
+ """Stubs out the db.instance_create method."""
+
+ type_data = INSTANCE_TYPES[values['instance_type']]
+
+ base_options = {
+ 'name': values['name'],
+ 'id': values['id'],
+ 'uuid': utils.gen_uuid(),
+ 'reservation_id': utils.generate_uid('r'),
+ 'image_ref': values['image_ref'],
+ 'kernel_id': values['kernel_id'],
+ 'ramdisk_id': values['ramdisk_id'],
+ 'vm_state': vm_states.BUILDING,
+ 'task_state': task_states.SCHEDULING,
+ 'user_id': values['user_id'],
+ 'project_id': values['project_id'],
+ 'launch_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
+ 'instance_type': values['instance_type'],
+ 'memory_mb': type_data['memory_mb'],
+ 'vcpus': type_data['vcpus'],
+ 'mac_addresses': [{'address': values['mac_address']}],
+ 'root_gb': type_data['root_gb'],
+ }
+ return FakeModel(base_options)
+
+ def fake_network_get_by_instance(context, instance_id):
+ """Stubs out the db.network_get_by_instance method."""
+
+ fields = {
+ 'bridge': 'vmnet0',
+ 'netmask': '255.255.255.0',
+ 'gateway': '10.10.10.1',
+ 'broadcast': '10.10.10.255',
+ 'dns1': 'fake',
+ 'vlan': 100}
+ return FakeModel(fields)
+
+ def fake_instance_action_create(context, action):
+ """Stubs out the db.instance_action_create method."""
+ pass
+
+ def fake_instance_type_get_all(context, inactive=0, filters=None):
+ return INSTANCE_TYPES.values()
+
+ def fake_instance_type_get_by_name(context, name):
+ return INSTANCE_TYPES[name]
+
+ stubs.Set(db, 'instance_create', fake_instance_create)
+ stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance)
+ stubs.Set(db, 'instance_action_create', fake_instance_action_create)
+ stubs.Set(db, 'instance_type_get_all', fake_instance_type_get_all)
+ stubs.Set(db, 'instance_type_get_by_name', fake_instance_type_get_by_name)
diff --git a/nova/tests/vmwareapi/stubs.py b/nova/tests/vmwareapi/stubs.py
index 7de10e612..cbb0da0fd 100644
--- a/nova/tests/vmwareapi/stubs.py
+++ b/nova/tests/vmwareapi/stubs.py
@@ -1,51 +1,51 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""
-Stubouts for the test suite
-"""
-
-from nova.virt import vmwareapi_conn
-from nova.virt.vmwareapi import fake
-from nova.virt.vmwareapi import vmware_images
-from nova.virt.vmwareapi import vmops
-from nova.virt.vmwareapi import network_utils
-
-
-def fake_get_vim_object(arg):
- """Stubs out the VMWareAPISession's get_vim_object method."""
- return fake.FakeVim()
-
-
-def fake_is_vim_object(arg, module):
- """Stubs out the VMWareAPISession's is_vim_object method."""
- return isinstance(module, fake.FakeVim)
-
-
-def set_stubs(stubs):
- """Set the stubs."""
- stubs.Set(vmops.VMWareVMOps, 'plug_vifs', fake.fake_plug_vifs)
- stubs.Set(network_utils, 'get_network_with_the_name',
- fake.fake_get_network)
- stubs.Set(vmware_images, 'fetch_image', fake.fake_fetch_image)
- stubs.Set(vmware_images, 'get_vmdk_size_and_properties',
- fake.fake_get_vmdk_size_and_properties)
- stubs.Set(vmware_images, 'upload_image', fake.fake_upload_image)
- stubs.Set(vmwareapi_conn.VMWareAPISession, "_get_vim_object",
- fake_get_vim_object)
- stubs.Set(vmwareapi_conn.VMWareAPISession, "_is_vim_object",
- fake_is_vim_object)
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""
+Stubouts for the test suite
+"""
+
+from nova.virt import vmwareapi_conn
+from nova.virt.vmwareapi import fake
+from nova.virt.vmwareapi import vmware_images
+from nova.virt.vmwareapi import vmops
+from nova.virt.vmwareapi import network_utils
+
+
+def fake_get_vim_object(arg):
+ """Stubs out the VMWareAPISession's get_vim_object method."""
+ return fake.FakeVim()
+
+
+def fake_is_vim_object(arg, module):
+ """Stubs out the VMWareAPISession's is_vim_object method."""
+ return isinstance(module, fake.FakeVim)
+
+
+def set_stubs(stubs):
+ """Set the stubs."""
+ stubs.Set(vmops.VMWareVMOps, 'plug_vifs', fake.fake_plug_vifs)
+ stubs.Set(network_utils, 'get_network_with_the_name',
+ fake.fake_get_network)
+ stubs.Set(vmware_images, 'fetch_image', fake.fake_fetch_image)
+ stubs.Set(vmware_images, 'get_vmdk_size_and_properties',
+ fake.fake_get_vmdk_size_and_properties)
+ stubs.Set(vmware_images, 'upload_image', fake.fake_upload_image)
+ stubs.Set(vmwareapi_conn.VMWareAPISession, "_get_vim_object",
+ fake_get_vim_object)
+ stubs.Set(vmwareapi_conn.VMWareAPISession, "_is_vim_object",
+ fake_is_vim_object)
diff --git a/nova/virt/vmwareapi/error_util.py b/nova/virt/vmwareapi/error_util.py
index 53fa8f24d..be82f4646 100644
--- a/nova/virt/vmwareapi/error_util.py
+++ b/nova/virt/vmwareapi/error_util.py
@@ -1,96 +1,96 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""
-Exception classes and SOAP response error checking module.
-"""
-
-FAULT_NOT_AUTHENTICATED = "NotAuthenticated"
-FAULT_ALREADY_EXISTS = "AlreadyExists"
-
-
-class VimException(Exception):
- """The VIM Exception class."""
-
- def __init__(self, exception_summary, excep):
- Exception.__init__(self)
- self.exception_summary = exception_summary
- self.exception_obj = excep
-
- def __str__(self):
- return self.exception_summary + str(self.exception_obj)
-
-
-class SessionOverLoadException(VimException):
- """Session Overload Exception."""
- pass
-
-
-class VimAttributeError(VimException):
- """VI Attribute Error."""
- pass
-
-
-class VimFaultException(Exception):
- """The VIM Fault exception class."""
-
- def __init__(self, fault_list, excep):
- Exception.__init__(self)
- self.fault_list = fault_list
- self.exception_obj = excep
-
- def __str__(self):
- return str(self.exception_obj)
-
-
-class FaultCheckers(object):
- """
- Methods for fault checking of SOAP response. Per Method error handlers
- for which we desire error checking are defined. SOAP faults are
- embedded in the SOAP messages as properties and not as SOAP faults.
- """
-
- @staticmethod
- def retrieveproperties_fault_checker(resp_obj):
- """
- Checks the RetrieveProperties response for errors. Certain faults
- are sent as part of the SOAP body as property of missingSet.
- For example NotAuthenticated fault.
- """
- fault_list = []
- if not resp_obj:
- # This is the case when the session has timed out. ESX SOAP server
- # sends an empty RetrievePropertiesResponse. Normally missingSet in
- # the returnval field has the specifics about the error, but that's
- # not the case with a timed out idle session. It is as bad as a
- # terminated session for we cannot use the session. So setting
- # fault to NotAuthenticated fault.
- fault_list = ["NotAuthenticated"]
- else:
- for obj_cont in resp_obj:
- if hasattr(obj_cont, "missingSet"):
- for missing_elem in obj_cont.missingSet:
- fault_type = \
- missing_elem.fault.fault.__class__.__name__
- # Fault needs to be added to the type of fault for
- # uniformity in error checking as SOAP faults define
- fault_list.append(fault_type)
- if fault_list:
- exc_msg_list = ', '.join(fault_list)
- raise VimFaultException(fault_list, Exception(_("Error(s) %s "
- "occurred in the call to RetrieveProperties") %
- exc_msg_list))
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""
+Exception classes and SOAP response error checking module.
+"""
+
+FAULT_NOT_AUTHENTICATED = "NotAuthenticated"
+FAULT_ALREADY_EXISTS = "AlreadyExists"
+
+
+class VimException(Exception):
+ """The VIM Exception class."""
+
+ def __init__(self, exception_summary, excep):
+ Exception.__init__(self)
+ self.exception_summary = exception_summary
+ self.exception_obj = excep
+
+ def __str__(self):
+ return self.exception_summary + str(self.exception_obj)
+
+
+class SessionOverLoadException(VimException):
+ """Session Overload Exception."""
+ pass
+
+
+class VimAttributeError(VimException):
+ """VI Attribute Error."""
+ pass
+
+
+class VimFaultException(Exception):
+ """The VIM Fault exception class."""
+
+ def __init__(self, fault_list, excep):
+ Exception.__init__(self)
+ self.fault_list = fault_list
+ self.exception_obj = excep
+
+ def __str__(self):
+ return str(self.exception_obj)
+
+
+class FaultCheckers(object):
+ """
+ Methods for fault checking of SOAP response. Per Method error handlers
+ for which we desire error checking are defined. SOAP faults are
+ embedded in the SOAP messages as properties and not as SOAP faults.
+ """
+
+ @staticmethod
+ def retrieveproperties_fault_checker(resp_obj):
+ """
+ Checks the RetrieveProperties response for errors. Certain faults
+ are sent as part of the SOAP body as property of missingSet.
+ For example NotAuthenticated fault.
+ """
+ fault_list = []
+ if not resp_obj:
+ # This is the case when the session has timed out. ESX SOAP server
+ # sends an empty RetrievePropertiesResponse. Normally missingSet in
+ # the returnval field has the specifics about the error, but that's
+ # not the case with a timed out idle session. It is as bad as a
+ # terminated session for we cannot use the session. So setting
+ # fault to NotAuthenticated fault.
+ fault_list = ["NotAuthenticated"]
+ else:
+ for obj_cont in resp_obj:
+ if hasattr(obj_cont, "missingSet"):
+ for missing_elem in obj_cont.missingSet:
+ fault_type = \
+ missing_elem.fault.fault.__class__.__name__
+ # Fault needs to be added to the type of fault for
+ # uniformity in error checking as SOAP faults define
+ fault_list.append(fault_type)
+ if fault_list:
+ exc_msg_list = ', '.join(fault_list)
+ raise VimFaultException(fault_list, Exception(_("Error(s) %s "
+ "occurred in the call to RetrieveProperties") %
+ exc_msg_list))
diff --git a/nova/virt/vmwareapi/fake.py b/nova/virt/vmwareapi/fake.py
index fec644770..72f6cdc61 100644
--- a/nova/virt/vmwareapi/fake.py
+++ b/nova/virt/vmwareapi/fake.py
@@ -1,719 +1,719 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-"""
-
-from pprint import pformat
-import uuid
-
-from nova import exception
-from nova import log as logging
-from nova.virt.vmwareapi import error_util
-
-_CLASSES = ['Datacenter', 'Datastore', 'ResourcePool', 'VirtualMachine',
- 'Network', 'HostSystem', 'HostNetworkSystem', 'Task', 'session',
- 'files']
-
-_FAKE_FILE_SIZE = 1024
-
-_db_content = {}
-
-LOG = logging.getLogger("nova.virt.vmwareapi.fake")
-
-
-def log_db_contents(msg=None):
- """Log DB Contents."""
- text = msg or ""
- content = pformat(_db_content)
- LOG.debug(_("%(text)s: _db_content => %(content)s") % locals())
-
-
-def reset():
- """Resets 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] = {}
- create_network()
- create_host_network_system()
- create_host()
- create_datacenter()
- create_datastore()
- create_res_pool()
-
-
-def cleanup():
- """Clear the db contents."""
- for c in _CLASSES:
- _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_objects(obj_type):
- """Get objects of the type."""
- lst_objs = []
- for key in _db_content[obj_type]:
- lst_objs.append(_db_content[obj_type][key])
- return lst_objs
-
-
-class Prop(object):
- """Property Object base class."""
-
- def __init__(self):
- self.name = None
- self.val = None
-
-
-class ManagedObject(object):
- """Managed Data Object base class."""
-
- def __init__(self, name="ManagedObject", obj_ref=None):
- """Sets the obj property which acts as a reference to the object."""
- super(ManagedObject, self).__setattr__('objName', name)
- if obj_ref is None:
- obj_ref = str(uuid.uuid4())
- object.__setattr__(self, 'obj', obj_ref)
- object.__setattr__(self, 'propSet', [])
-
- 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):
- 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):
- for elem in self.propSet:
- if elem.name == attr:
- return elem.val
- raise exception.Error(_("Property %(attr)s not set for the managed "
- "object %(objName)s") %
- {'attr': attr,
- 'objName': self.objName})
-
-
-class DataObject(object):
- """Data object base class."""
- pass
-
-
-class VirtualDisk(DataObject):
- """
- Virtual Disk class. Does nothing special except setting
- __class__.__name__ to 'VirtualDisk'. Refer place where __class__.__name__
- is used in the code.
- """
- pass
-
-
-class VirtualDiskFlatVer2BackingInfo(DataObject):
- """VirtualDiskFlatVer2BackingInfo class."""
- pass
-
-
-class VirtualLsiLogicController(DataObject):
- """VirtualLsiLogicController class."""
- pass
-
-
-class VirtualMachine(ManagedObject):
- """Virtual Machine class."""
-
- def __init__(self, **kwargs):
- super(VirtualMachine, self).__init__("VirtualMachine")
- self.set("name", kwargs.get("name"))
- self.set("runtime.connectionState",
- kwargs.get("conn_state", "connected"))
- self.set("summary.config.guestId", kwargs.get("guest", "otherGuest"))
- ds_do = DataObject()
- ds_do.ManagedObjectReference = [kwargs.get("ds").obj]
- self.set("datastore", 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("config.hardware.device", kwargs.get("virtual_disk", None))
- self.set("config.extraConfig", kwargs.get("extra_config", None))
-
- def reconfig(self, factory, val):
- """
- Called to reconfigure the VM. Actually customizes the property
- setting of the Virtual Machine object.
- """
- try:
- # Case of Reconfig of VM to attach disk
- controller_key = val.deviceChange[1].device.controllerKey
- filename = val.deviceChange[1].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])
- except AttributeError:
- # Case of Reconfig of VM to set extra params
- self.set("config.extraConfig", val.extraConfig)
-
-
-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):
- super(ResourcePool, self).__init__("ResourcePool")
- self.set("name", "ResPool")
-
-
-class Datastore(ManagedObject):
- """Datastore class."""
-
- def __init__(self):
- super(Datastore, self).__init__("Datastore")
- self.set("summary.type", "VMFS")
- self.set("summary.name", "fake-ds")
-
-
-class HostNetworkSystem(ManagedObject):
- """HostNetworkSystem class."""
-
- def __init__(self):
- super(HostNetworkSystem, self).__init__("HostNetworkSystem")
- self.set("name", "networkSystem")
-
- 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 HostSystem(ManagedObject):
- """Host System class."""
-
- def __init__(self):
- super(HostSystem, self).__init__("HostSystem")
- self.set("name", "ha-host")
- if _db_content.get("HostNetworkSystem", None) is None:
- create_host_network_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)
-
- 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)
-
- 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):
- super(Datacenter, self).__init__("Datacenter")
- self.set("name", "ha-datacenter")
- 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)
-
-
-class Task(ManagedObject):
- """Task class."""
-
- def __init__(self, task_name, state="running"):
- super(Task, self).__init__("Task")
- info = DataObject
- info.name = task_name
- info.state = state
- self.set("info", info)
-
-
-def create_host_network_system():
- host_net_system = HostNetworkSystem()
- _create_object("HostNetworkSystem", host_net_system)
-
-
-def create_host():
- host_system = HostSystem()
- _create_object('HostSystem', host_system)
-
-
-def create_datacenter():
- data_center = Datacenter()
- _create_object('Datacenter', data_center)
-
-
-def create_datastore():
- data_store = Datastore()
- _create_object('Datastore', data_store)
-
-
-def create_res_pool():
- res_pool = ResourcePool()
- _create_object('ResourcePool', res_pool)
-
-
-def create_network():
- network = Network()
- _create_object('Network', network)
-
-
-def create_task(task_name, state="running"):
- task = Task(task_name, state)
- _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
- for file in _db_content.get("files"):
- if file.find(file_path) != -1:
- lst_files = _db_content.get("files")
- if lst_files and lst_files.count(file):
- lst_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 fake_fetch_image(context, image, instance, **kwargs):
- """Fakes fetch image call. Just adds a reference to the db for the file."""
- ds_name = kwargs.get("datastore_name")
- file_path = kwargs.get("file_path")
- ds_file_path = "[" + ds_name + "] " + file_path
- _add_file(ds_file_path)
-
-
-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]
-
-
-class FakeFactory(object):
- """Fake factory class for the suds client."""
-
- def create(self, obj_name):
- """Creates a namespace object."""
- return DataObject()
-
-
-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"
- 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 = str(uuid.uuid4())
- session = DataObject()
- session.key = self._session
- _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.Error(
- _("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.FAULT_NOT_AUTHENTICATED],
- _("Session Invalid"))
-
- def _create_vm(self, method, *args, **kwargs):
- """Creates and registers a VM object with the Host System."""
- config_spec = kwargs.get("config")
- ds = _db_content["Datastore"][_db_content["Datastore"].keys()[0]]
- vm_dict = {"name": config_spec.name,
- "ds": ds,
- "powerstate": "poweredOff",
- "vmPathName": config_spec.files.vmPathName,
- "numCpu": config_spec.numCPUs,
- "mem": config_spec.memoryMB}
- virtual_machine = VirtualMachine(**vm_dict)
- _create_object("VirtualMachine", virtual_machine)
- task_mdo = create_task(method, "success")
- 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 _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 _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 _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."""
- ds_path = kwargs.get("datastorePath")
- if _db_content.get("files", None) is None:
- raise exception.NoFilesFound()
- for file in _db_content.get("files"):
- if file.find(ds_path) != -1:
- task_mdo = create_task(method, "success")
- return task_mdo.obj
- task_mdo = create_task(method, "error")
- return task_mdo.obj
-
- 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()
- _db_content["files"].append(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(self, method, *args, **kwargs):
- """Retrieves properties based on the type."""
- spec_set = kwargs.get("specSet")[0]
- type = spec_set.propSet[0].type
- properties = spec_set.propSet[0].pathSet
- objs = spec_set.objectSet
- lst_ret_objs = []
- for obj in objs:
- try:
- obj_ref = obj.obj
- # This means that we are doing a search for the managed
- # dataobjects of the type in the inventory
- if obj_ref == "RootFolder":
- for mdo_ref in _db_content[type]:
- mdo = _db_content[type][mdo_ref]
- # Create a temp Managed object which has the same ref
- # as the parent object and copies just the properties
- # asked for. We need .obj along with the propSet of
- # just the properties asked for
- temp_mdo = ManagedObject(mdo.objName, mdo.obj)
- for prop in properties:
- temp_mdo.set(prop, mdo.get(prop))
- lst_ret_objs.append(temp_mdo)
- else:
- if obj_ref in _db_content[type]:
- mdo = _db_content[type][obj_ref]
- temp_mdo = ManagedObject(mdo.objName, obj_ref)
- for prop in properties:
- temp_mdo.set(prop, mdo.get(prop))
- lst_ret_objs.append(temp_mdo)
- except Exception, 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_mdo = \
- _db_content["HostSystem"][_db_content["HostSystem"].keys()[0]]
- host_mdo._add_port_group(kwargs.get("portgrp"))
-
- 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 == "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 == "CopyVirtualDisk_Task":
- return lambda *args, **kwargs: self._create_copy_disk(attr_name,
- kwargs.get("destName"))
- elif attr_name == "DeleteVirtualDisk_Task":
- return lambda *args, **kwargs: self._delete_disk(attr_name,
- *args, **kwargs)
- elif attr_name == "UnregisterVM":
- return lambda *args, **kwargs: self._unregister_vm(attr_name,
- *args, **kwargs)
- elif attr_name == "SearchDatastore_Task":
- return lambda *args, **kwargs: self._search_ds(attr_name,
- *args, **kwargs)
- elif attr_name == "MakeDirectory":
- return lambda *args, **kwargs: self._make_dir(attr_name,
- *args, **kwargs)
- elif attr_name == "RetrieveProperties":
- return lambda *args, **kwargs: self._retrieve_properties(
- 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)
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+"""
+
+from pprint import pformat
+import uuid
+
+from nova import exception
+from nova import log as logging
+from nova.virt.vmwareapi import error_util
+
+_CLASSES = ['Datacenter', 'Datastore', 'ResourcePool', 'VirtualMachine',
+ 'Network', 'HostSystem', 'HostNetworkSystem', 'Task', 'session',
+ 'files']
+
+_FAKE_FILE_SIZE = 1024
+
+_db_content = {}
+
+LOG = logging.getLogger("nova.virt.vmwareapi.fake")
+
+
+def log_db_contents(msg=None):
+ """Log DB Contents."""
+ text = msg or ""
+ content = pformat(_db_content)
+ LOG.debug(_("%(text)s: _db_content => %(content)s") % locals())
+
+
+def reset():
+ """Resets 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] = {}
+ create_network()
+ create_host_network_system()
+ create_host()
+ create_datacenter()
+ create_datastore()
+ create_res_pool()
+
+
+def cleanup():
+ """Clear the db contents."""
+ for c in _CLASSES:
+ _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_objects(obj_type):
+ """Get objects of the type."""
+ lst_objs = []
+ for key in _db_content[obj_type]:
+ lst_objs.append(_db_content[obj_type][key])
+ return lst_objs
+
+
+class Prop(object):
+ """Property Object base class."""
+
+ def __init__(self):
+ self.name = None
+ self.val = None
+
+
+class ManagedObject(object):
+ """Managed Data Object base class."""
+
+ def __init__(self, name="ManagedObject", obj_ref=None):
+ """Sets the obj property which acts as a reference to the object."""
+ super(ManagedObject, self).__setattr__('objName', name)
+ if obj_ref is None:
+ obj_ref = str(uuid.uuid4())
+ object.__setattr__(self, 'obj', obj_ref)
+ object.__setattr__(self, 'propSet', [])
+
+ 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):
+ 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):
+ for elem in self.propSet:
+ if elem.name == attr:
+ return elem.val
+ raise exception.Error(_("Property %(attr)s not set for the managed "
+ "object %(objName)s") %
+ {'attr': attr,
+ 'objName': self.objName})
+
+
+class DataObject(object):
+ """Data object base class."""
+ pass
+
+
+class VirtualDisk(DataObject):
+ """
+ Virtual Disk class. Does nothing special except setting
+ __class__.__name__ to 'VirtualDisk'. Refer place where __class__.__name__
+ is used in the code.
+ """
+ pass
+
+
+class VirtualDiskFlatVer2BackingInfo(DataObject):
+ """VirtualDiskFlatVer2BackingInfo class."""
+ pass
+
+
+class VirtualLsiLogicController(DataObject):
+ """VirtualLsiLogicController class."""
+ pass
+
+
+class VirtualMachine(ManagedObject):
+ """Virtual Machine class."""
+
+ def __init__(self, **kwargs):
+ super(VirtualMachine, self).__init__("VirtualMachine")
+ self.set("name", kwargs.get("name"))
+ self.set("runtime.connectionState",
+ kwargs.get("conn_state", "connected"))
+ self.set("summary.config.guestId", kwargs.get("guest", "otherGuest"))
+ ds_do = DataObject()
+ ds_do.ManagedObjectReference = [kwargs.get("ds").obj]
+ self.set("datastore", 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("config.hardware.device", kwargs.get("virtual_disk", None))
+ self.set("config.extraConfig", kwargs.get("extra_config", None))
+
+ def reconfig(self, factory, val):
+ """
+ Called to reconfigure the VM. Actually customizes the property
+ setting of the Virtual Machine object.
+ """
+ try:
+ # Case of Reconfig of VM to attach disk
+ controller_key = val.deviceChange[1].device.controllerKey
+ filename = val.deviceChange[1].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])
+ except AttributeError:
+ # Case of Reconfig of VM to set extra params
+ self.set("config.extraConfig", val.extraConfig)
+
+
+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):
+ super(ResourcePool, self).__init__("ResourcePool")
+ self.set("name", "ResPool")
+
+
+class Datastore(ManagedObject):
+ """Datastore class."""
+
+ def __init__(self):
+ super(Datastore, self).__init__("Datastore")
+ self.set("summary.type", "VMFS")
+ self.set("summary.name", "fake-ds")
+
+
+class HostNetworkSystem(ManagedObject):
+ """HostNetworkSystem class."""
+
+ def __init__(self):
+ super(HostNetworkSystem, self).__init__("HostNetworkSystem")
+ self.set("name", "networkSystem")
+
+ 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 HostSystem(ManagedObject):
+ """Host System class."""
+
+ def __init__(self):
+ super(HostSystem, self).__init__("HostSystem")
+ self.set("name", "ha-host")
+ if _db_content.get("HostNetworkSystem", None) is None:
+ create_host_network_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)
+
+ 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)
+
+ 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):
+ super(Datacenter, self).__init__("Datacenter")
+ self.set("name", "ha-datacenter")
+ 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)
+
+
+class Task(ManagedObject):
+ """Task class."""
+
+ def __init__(self, task_name, state="running"):
+ super(Task, self).__init__("Task")
+ info = DataObject
+ info.name = task_name
+ info.state = state
+ self.set("info", info)
+
+
+def create_host_network_system():
+ host_net_system = HostNetworkSystem()
+ _create_object("HostNetworkSystem", host_net_system)
+
+
+def create_host():
+ host_system = HostSystem()
+ _create_object('HostSystem', host_system)
+
+
+def create_datacenter():
+ data_center = Datacenter()
+ _create_object('Datacenter', data_center)
+
+
+def create_datastore():
+ data_store = Datastore()
+ _create_object('Datastore', data_store)
+
+
+def create_res_pool():
+ res_pool = ResourcePool()
+ _create_object('ResourcePool', res_pool)
+
+
+def create_network():
+ network = Network()
+ _create_object('Network', network)
+
+
+def create_task(task_name, state="running"):
+ task = Task(task_name, state)
+ _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
+ for file in _db_content.get("files"):
+ if file.find(file_path) != -1:
+ lst_files = _db_content.get("files")
+ if lst_files and lst_files.count(file):
+ lst_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 fake_fetch_image(context, image, instance, **kwargs):
+ """Fakes fetch image call. Just adds a reference to the db for the file."""
+ ds_name = kwargs.get("datastore_name")
+ file_path = kwargs.get("file_path")
+ ds_file_path = "[" + ds_name + "] " + file_path
+ _add_file(ds_file_path)
+
+
+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]
+
+
+class FakeFactory(object):
+ """Fake factory class for the suds client."""
+
+ def create(self, obj_name):
+ """Creates a namespace object."""
+ return DataObject()
+
+
+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"
+ 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 = str(uuid.uuid4())
+ session = DataObject()
+ session.key = self._session
+ _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.Error(
+ _("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.FAULT_NOT_AUTHENTICATED],
+ _("Session Invalid"))
+
+ def _create_vm(self, method, *args, **kwargs):
+ """Creates and registers a VM object with the Host System."""
+ config_spec = kwargs.get("config")
+ ds = _db_content["Datastore"][_db_content["Datastore"].keys()[0]]
+ vm_dict = {"name": config_spec.name,
+ "ds": ds,
+ "powerstate": "poweredOff",
+ "vmPathName": config_spec.files.vmPathName,
+ "numCpu": config_spec.numCPUs,
+ "mem": config_spec.memoryMB}
+ virtual_machine = VirtualMachine(**vm_dict)
+ _create_object("VirtualMachine", virtual_machine)
+ task_mdo = create_task(method, "success")
+ 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 _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 _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 _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."""
+ ds_path = kwargs.get("datastorePath")
+ if _db_content.get("files", None) is None:
+ raise exception.NoFilesFound()
+ for file in _db_content.get("files"):
+ if file.find(ds_path) != -1:
+ task_mdo = create_task(method, "success")
+ return task_mdo.obj
+ task_mdo = create_task(method, "error")
+ return task_mdo.obj
+
+ 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()
+ _db_content["files"].append(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(self, method, *args, **kwargs):
+ """Retrieves properties based on the type."""
+ spec_set = kwargs.get("specSet")[0]
+ type = spec_set.propSet[0].type
+ properties = spec_set.propSet[0].pathSet
+ objs = spec_set.objectSet
+ lst_ret_objs = []
+ for obj in objs:
+ try:
+ obj_ref = obj.obj
+ # This means that we are doing a search for the managed
+ # dataobjects of the type in the inventory
+ if obj_ref == "RootFolder":
+ for mdo_ref in _db_content[type]:
+ mdo = _db_content[type][mdo_ref]
+ # Create a temp Managed object which has the same ref
+ # as the parent object and copies just the properties
+ # asked for. We need .obj along with the propSet of
+ # just the properties asked for
+ temp_mdo = ManagedObject(mdo.objName, mdo.obj)
+ for prop in properties:
+ temp_mdo.set(prop, mdo.get(prop))
+ lst_ret_objs.append(temp_mdo)
+ else:
+ if obj_ref in _db_content[type]:
+ mdo = _db_content[type][obj_ref]
+ temp_mdo = ManagedObject(mdo.objName, obj_ref)
+ for prop in properties:
+ temp_mdo.set(prop, mdo.get(prop))
+ lst_ret_objs.append(temp_mdo)
+ except Exception, 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_mdo = \
+ _db_content["HostSystem"][_db_content["HostSystem"].keys()[0]]
+ host_mdo._add_port_group(kwargs.get("portgrp"))
+
+ 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 == "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 == "CopyVirtualDisk_Task":
+ return lambda *args, **kwargs: self._create_copy_disk(attr_name,
+ kwargs.get("destName"))
+ elif attr_name == "DeleteVirtualDisk_Task":
+ return lambda *args, **kwargs: self._delete_disk(attr_name,
+ *args, **kwargs)
+ elif attr_name == "UnregisterVM":
+ return lambda *args, **kwargs: self._unregister_vm(attr_name,
+ *args, **kwargs)
+ elif attr_name == "SearchDatastore_Task":
+ return lambda *args, **kwargs: self._search_ds(attr_name,
+ *args, **kwargs)
+ elif attr_name == "MakeDirectory":
+ return lambda *args, **kwargs: self._make_dir(attr_name,
+ *args, **kwargs)
+ elif attr_name == "RetrieveProperties":
+ return lambda *args, **kwargs: self._retrieve_properties(
+ 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)
diff --git a/nova/virt/vmwareapi/io_util.py b/nova/virt/vmwareapi/io_util.py
index cb9587afc..0e0159c97 100644
--- a/nova/virt/vmwareapi/io_util.py
+++ b/nova/virt/vmwareapi/io_util.py
@@ -1,169 +1,169 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""
-Utility classes for defining the time saving transfer of data from the reader
-to the write using a LightQueue as a Pipe between the reader and the writer.
-"""
-
-from eventlet import event
-from eventlet import greenthread
-from eventlet.queue import LightQueue
-
-from nova import exception
-from nova import log as logging
-
-LOG = logging.getLogger("nova.virt.vmwareapi.io_util")
-
-IO_THREAD_SLEEP_TIME = .01
-GLANCE_POLL_INTERVAL = 5
-
-
-class ThreadSafePipe(LightQueue):
- """The pipe to hold the data which the reader writes to and the writer
- reads from."""
-
- def __init__(self, maxsize, transfer_size):
- LightQueue.__init__(self, maxsize)
- self.transfer_size = transfer_size
- self.transferred = 0
-
- def read(self, chunk_size):
- """Read data from the pipe. Chunksize if ignored for we have ensured
- that the data chunks written to the pipe by readers is the same as the
- chunks asked for by the Writer."""
- if self.transferred < self.transfer_size:
- data_item = self.get()
- self.transferred += len(data_item)
- return data_item
- else:
- return ""
-
- def write(self, data):
- """Put a data item in the pipe."""
- self.put(data)
-
- def close(self):
- """A place-holder to maintain consistency."""
- pass
-
-
-class GlanceWriteThread(object):
- """Ensures that image data is written to in the glance client and that
- it is in correct ('active')state."""
-
- def __init__(self, input, glance_client, image_id, image_meta=None):
- if not image_meta:
- image_meta = {}
-
- self.input = input
- self.glance_client = glance_client
- self.image_id = image_id
- self.image_meta = image_meta
- self._running = False
-
- def start(self):
- self.done = event.Event()
-
- def _inner():
- """Function to do the image data transfer through an update
- and thereon checks if the state is 'active'."""
- self.glance_client.update_image(self.image_id,
- image_meta=self.image_meta,
- image_data=self.input)
- self._running = True
- while self._running:
- try:
- image_status = \
- self.glance_client.get_image_meta(self.image_id).get(
- "status")
- if image_status == "active":
- self.stop()
- self.done.send(True)
- # If the state is killed, then raise an exception.
- elif image_status == "killed":
- self.stop()
- exc_msg = _("Glance image %s is in killed state") %\
- self.image_id
- LOG.exception(exc_msg)
- self.done.send_exception(exception.Error(exc_msg))
- elif image_status in ["saving", "queued"]:
- greenthread.sleep(GLANCE_POLL_INTERVAL)
- else:
- self.stop()
- exc_msg = _("Glance image "
- "%(image_id)s is in unknown state "
- "- %(state)s") % {
- "image_id": self.image_id,
- "state": image_status}
- LOG.exception(exc_msg)
- self.done.send_exception(exception.Error(exc_msg))
- except Exception, exc:
- self.stop()
- self.done.send_exception(exc)
-
- greenthread.spawn(_inner)
- return self.done
-
- def stop(self):
- self._running = False
-
- def wait(self):
- return self.done.wait()
-
- def close(self):
- pass
-
-
-class IOThread(object):
- """Class that reads chunks from the input file and writes them to the
- output file till the transfer is completely done."""
-
- def __init__(self, input, output):
- self.input = input
- self.output = output
- self._running = False
- self.got_exception = False
-
- def start(self):
- self.done = event.Event()
-
- def _inner():
- """Read data from the input and write the same to the output
- until the transfer completes."""
- self._running = True
- while self._running:
- try:
- data = self.input.read(None)
- if not data:
- self.stop()
- self.done.send(True)
- self.output.write(data)
- greenthread.sleep(IO_THREAD_SLEEP_TIME)
- except Exception, exc:
- self.stop()
- LOG.exception(exc)
- self.done.send_exception(exc)
-
- greenthread.spawn(_inner)
- return self.done
-
- def stop(self):
- self._running = False
-
- def wait(self):
- return self.done.wait()
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""
+Utility classes for defining the time saving transfer of data from the reader
+to the write using a LightQueue as a Pipe between the reader and the writer.
+"""
+
+from eventlet import event
+from eventlet import greenthread
+from eventlet.queue import LightQueue
+
+from nova import exception
+from nova import log as logging
+
+LOG = logging.getLogger("nova.virt.vmwareapi.io_util")
+
+IO_THREAD_SLEEP_TIME = .01
+GLANCE_POLL_INTERVAL = 5
+
+
+class ThreadSafePipe(LightQueue):
+ """The pipe to hold the data which the reader writes to and the writer
+ reads from."""
+
+ def __init__(self, maxsize, transfer_size):
+ LightQueue.__init__(self, maxsize)
+ self.transfer_size = transfer_size
+ self.transferred = 0
+
+ def read(self, chunk_size):
+ """Read data from the pipe. Chunksize if ignored for we have ensured
+ that the data chunks written to the pipe by readers is the same as the
+ chunks asked for by the Writer."""
+ if self.transferred < self.transfer_size:
+ data_item = self.get()
+ self.transferred += len(data_item)
+ return data_item
+ else:
+ return ""
+
+ def write(self, data):
+ """Put a data item in the pipe."""
+ self.put(data)
+
+ def close(self):
+ """A place-holder to maintain consistency."""
+ pass
+
+
+class GlanceWriteThread(object):
+ """Ensures that image data is written to in the glance client and that
+ it is in correct ('active')state."""
+
+ def __init__(self, input, glance_client, image_id, image_meta=None):
+ if not image_meta:
+ image_meta = {}
+
+ self.input = input
+ self.glance_client = glance_client
+ self.image_id = image_id
+ self.image_meta = image_meta
+ self._running = False
+
+ def start(self):
+ self.done = event.Event()
+
+ def _inner():
+ """Function to do the image data transfer through an update
+ and thereon checks if the state is 'active'."""
+ self.glance_client.update_image(self.image_id,
+ image_meta=self.image_meta,
+ image_data=self.input)
+ self._running = True
+ while self._running:
+ try:
+ image_status = \
+ self.glance_client.get_image_meta(self.image_id).get(
+ "status")
+ if image_status == "active":
+ self.stop()
+ self.done.send(True)
+ # If the state is killed, then raise an exception.
+ elif image_status == "killed":
+ self.stop()
+ exc_msg = _("Glance image %s is in killed state") %\
+ self.image_id
+ LOG.exception(exc_msg)
+ self.done.send_exception(exception.Error(exc_msg))
+ elif image_status in ["saving", "queued"]:
+ greenthread.sleep(GLANCE_POLL_INTERVAL)
+ else:
+ self.stop()
+ exc_msg = _("Glance image "
+ "%(image_id)s is in unknown state "
+ "- %(state)s") % {
+ "image_id": self.image_id,
+ "state": image_status}
+ LOG.exception(exc_msg)
+ self.done.send_exception(exception.Error(exc_msg))
+ except Exception, exc:
+ self.stop()
+ self.done.send_exception(exc)
+
+ greenthread.spawn(_inner)
+ return self.done
+
+ def stop(self):
+ self._running = False
+
+ def wait(self):
+ return self.done.wait()
+
+ def close(self):
+ pass
+
+
+class IOThread(object):
+ """Class that reads chunks from the input file and writes them to the
+ output file till the transfer is completely done."""
+
+ def __init__(self, input, output):
+ self.input = input
+ self.output = output
+ self._running = False
+ self.got_exception = False
+
+ def start(self):
+ self.done = event.Event()
+
+ def _inner():
+ """Read data from the input and write the same to the output
+ until the transfer completes."""
+ self._running = True
+ while self._running:
+ try:
+ data = self.input.read(None)
+ if not data:
+ self.stop()
+ self.done.send(True)
+ self.output.write(data)
+ greenthread.sleep(IO_THREAD_SLEEP_TIME)
+ except Exception, exc:
+ self.stop()
+ LOG.exception(exc)
+ self.done.send_exception(exc)
+
+ greenthread.spawn(_inner)
+ return self.done
+
+ def stop(self):
+ self._running = False
+
+ def wait(self):
+ return self.done.wait()
diff --git a/nova/virt/vmwareapi/network_utils.py b/nova/virt/vmwareapi/network_utils.py
index ec3b93fe7..9d1918bd3 100644
--- a/nova/virt/vmwareapi/network_utils.py
+++ b/nova/virt/vmwareapi/network_utils.py
@@ -1,170 +1,170 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""
-Utility functions for ESX Networking.
-"""
-
-from nova import exception
-from nova import log as logging
-from nova.virt.vmwareapi import error_util
-from nova.virt.vmwareapi import vim_util
-from nova.virt.vmwareapi import vm_util
-
-LOG = logging.getLogger("nova.virt.vmwareapi.network_utils")
-
-
-def get_network_with_the_name(session, network_name="vmnet0"):
- """
- Gets reference to the network whose name is passed as the
- argument.
- """
- hostsystems = session._call_method(vim_util, "get_objects",
- "HostSystem", ["network"])
- vm_networks_ret = hostsystems[0].propSet[0].val
- # Meaning there are no networks on the host. suds responds with a ""
- # in the parent property field rather than a [] in the
- # ManagedObjectRefernce property field of the parent
- if not vm_networks_ret:
- return None
- vm_networks = vm_networks_ret.ManagedObjectReference
- networks = session._call_method(vim_util,
- "get_properties_for_a_collection_of_objects",
- "Network", vm_networks, ["summary.name"])
- network_obj = {}
- LOG.warn(vm_networks)
- for network in vm_networks:
- # Get network properties
- if network._type == 'DistributedVirtualPortgroup':
- props = session._call_method(vim_util,
- "get_dynamic_property", network,
- "DistributedVirtualPortgroup", "config")
- # NOTE(asomya): This only works on ESXi if the port binding is
- # set to ephemeral
- if props.name == network_name:
- network_obj['type'] = 'DistributedVirtualPortgroup'
- network_obj['dvpg'] = props.key
- network_obj['dvsw'] = props.distributedVirtualSwitch.value
- else:
- props = session._call_method(vim_util,
- "get_dynamic_property", network,
- "Network", "summary.name")
- if props == network_name:
- network_obj['type'] = 'Network'
- network_obj['name'] = network_name
- if (len(network_obj) > 0):
- return network_obj
- else:
- return None
-
-
-def get_vswitch_for_vlan_interface(session, vlan_interface):
- """
- Gets the vswitch associated with the physical network adapter
- with the name supplied.
- """
- # Get the list of vSwicthes on the Host System
- host_mor = session._call_method(vim_util, "get_objects",
- "HostSystem")[0].obj
- vswitches_ret = session._call_method(vim_util,
- "get_dynamic_property", host_mor,
- "HostSystem", "config.network.vswitch")
- # Meaning there are no vSwitches on the host. Shouldn't be the case,
- # but just doing code check
- if not vswitches_ret:
- return
- vswitches = vswitches_ret.HostVirtualSwitch
- # Get the vSwitch associated with the network adapter
- for elem in vswitches:
- try:
- for nic_elem in elem.pnic:
- if str(nic_elem).split('-')[-1].find(vlan_interface) != -1:
- return elem.name
- # Catching Attribute error as a vSwitch may not be associated with a
- # physical NIC.
- except AttributeError:
- pass
-
-
-def check_if_vlan_interface_exists(session, vlan_interface):
- """Checks if the vlan_inteface exists on the esx host."""
- host_net_system_mor = session._call_method(vim_util, "get_objects",
- "HostSystem", ["configManager.networkSystem"])[0].propSet[0].val
- physical_nics_ret = session._call_method(vim_util,
- "get_dynamic_property", host_net_system_mor,
- "HostNetworkSystem", "networkInfo.pnic")
- # Meaning there are no physical nics on the host
- if not physical_nics_ret:
- return False
- physical_nics = physical_nics_ret.PhysicalNic
- for pnic in physical_nics:
- if vlan_interface == pnic.device:
- return True
- return False
-
-
-def get_vlanid_and_vswitch_for_portgroup(session, pg_name):
- """Get the vlan id and vswicth associated with the port group."""
- host_mor = session._call_method(vim_util, "get_objects",
- "HostSystem")[0].obj
- port_grps_on_host_ret = session._call_method(vim_util,
- "get_dynamic_property", host_mor,
- "HostSystem", "config.network.portgroup")
- if not port_grps_on_host_ret:
- excep = ("ESX SOAP server returned an empty port group "
- "for the host system in its response")
- LOG.exception(excep)
- raise exception.Error(_(excep))
- port_grps_on_host = port_grps_on_host_ret.HostPortGroup
- for p_gp in port_grps_on_host:
- if p_gp.spec.name == pg_name:
- p_grp_vswitch_name = p_gp.vswitch.split("-")[-1]
- return p_gp.spec.vlanId, p_grp_vswitch_name
-
-
-def create_port_group(session, pg_name, vswitch_name, vlan_id=0):
- """
- Creates a port group on the host system with the vlan tags
- supplied. VLAN id 0 means no vlan id association.
- """
- client_factory = session._get_vim().client.factory
- add_prt_grp_spec = vm_util.get_add_vswitch_port_group_spec(
- client_factory,
- vswitch_name,
- pg_name,
- vlan_id)
- host_mor = session._call_method(vim_util, "get_objects",
- "HostSystem")[0].obj
- network_system_mor = session._call_method(vim_util,
- "get_dynamic_property", host_mor,
- "HostSystem", "configManager.networkSystem")
- LOG.debug(_("Creating Port Group with name %s on "
- "the ESX host") % pg_name)
- try:
- session._call_method(session._get_vim(),
- "AddPortGroup", network_system_mor,
- portgrp=add_prt_grp_spec)
- except error_util.VimFaultException, exc:
- # There can be a race condition when two instances try
- # adding port groups at the same time. One succeeds, then
- # the other one will get an exception. Since we are
- # concerned with the port group being created, which is done
- # by the other call, we can ignore the exception.
- if error_util.FAULT_ALREADY_EXISTS not in exc.fault_list:
- raise exception.Error(exc)
- LOG.debug(_("Created Port Group with name %s on "
- "the ESX host") % pg_name)
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""
+Utility functions for ESX Networking.
+"""
+
+from nova import exception
+from nova import log as logging
+from nova.virt.vmwareapi import error_util
+from nova.virt.vmwareapi import vim_util
+from nova.virt.vmwareapi import vm_util
+
+LOG = logging.getLogger("nova.virt.vmwareapi.network_utils")
+
+
+def get_network_with_the_name(session, network_name="vmnet0"):
+ """
+ Gets reference to the network whose name is passed as the
+ argument.
+ """
+ hostsystems = session._call_method(vim_util, "get_objects",
+ "HostSystem", ["network"])
+ vm_networks_ret = hostsystems[0].propSet[0].val
+ # Meaning there are no networks on the host. suds responds with a ""
+ # in the parent property field rather than a [] in the
+ # ManagedObjectRefernce property field of the parent
+ if not vm_networks_ret:
+ return None
+ vm_networks = vm_networks_ret.ManagedObjectReference
+ networks = session._call_method(vim_util,
+ "get_properties_for_a_collection_of_objects",
+ "Network", vm_networks, ["summary.name"])
+ network_obj = {}
+ LOG.warn(vm_networks)
+ for network in vm_networks:
+ # Get network properties
+ if network._type == 'DistributedVirtualPortgroup':
+ props = session._call_method(vim_util,
+ "get_dynamic_property", network,
+ "DistributedVirtualPortgroup", "config")
+ # NOTE(asomya): This only works on ESXi if the port binding is
+ # set to ephemeral
+ if props.name == network_name:
+ network_obj['type'] = 'DistributedVirtualPortgroup'
+ network_obj['dvpg'] = props.key
+ network_obj['dvsw'] = props.distributedVirtualSwitch.value
+ else:
+ props = session._call_method(vim_util,
+ "get_dynamic_property", network,
+ "Network", "summary.name")
+ if props == network_name:
+ network_obj['type'] = 'Network'
+ network_obj['name'] = network_name
+ if (len(network_obj) > 0):
+ return network_obj
+ else:
+ return None
+
+
+def get_vswitch_for_vlan_interface(session, vlan_interface):
+ """
+ Gets the vswitch associated with the physical network adapter
+ with the name supplied.
+ """
+ # Get the list of vSwicthes on the Host System
+ host_mor = session._call_method(vim_util, "get_objects",
+ "HostSystem")[0].obj
+ vswitches_ret = session._call_method(vim_util,
+ "get_dynamic_property", host_mor,
+ "HostSystem", "config.network.vswitch")
+ # Meaning there are no vSwitches on the host. Shouldn't be the case,
+ # but just doing code check
+ if not vswitches_ret:
+ return
+ vswitches = vswitches_ret.HostVirtualSwitch
+ # Get the vSwitch associated with the network adapter
+ for elem in vswitches:
+ try:
+ for nic_elem in elem.pnic:
+ if str(nic_elem).split('-')[-1].find(vlan_interface) != -1:
+ return elem.name
+ # Catching Attribute error as a vSwitch may not be associated with a
+ # physical NIC.
+ except AttributeError:
+ pass
+
+
+def check_if_vlan_interface_exists(session, vlan_interface):
+ """Checks if the vlan_inteface exists on the esx host."""
+ host_net_system_mor = session._call_method(vim_util, "get_objects",
+ "HostSystem", ["configManager.networkSystem"])[0].propSet[0].val
+ physical_nics_ret = session._call_method(vim_util,
+ "get_dynamic_property", host_net_system_mor,
+ "HostNetworkSystem", "networkInfo.pnic")
+ # Meaning there are no physical nics on the host
+ if not physical_nics_ret:
+ return False
+ physical_nics = physical_nics_ret.PhysicalNic
+ for pnic in physical_nics:
+ if vlan_interface == pnic.device:
+ return True
+ return False
+
+
+def get_vlanid_and_vswitch_for_portgroup(session, pg_name):
+ """Get the vlan id and vswicth associated with the port group."""
+ host_mor = session._call_method(vim_util, "get_objects",
+ "HostSystem")[0].obj
+ port_grps_on_host_ret = session._call_method(vim_util,
+ "get_dynamic_property", host_mor,
+ "HostSystem", "config.network.portgroup")
+ if not port_grps_on_host_ret:
+ excep = ("ESX SOAP server returned an empty port group "
+ "for the host system in its response")
+ LOG.exception(excep)
+ raise exception.Error(_(excep))
+ port_grps_on_host = port_grps_on_host_ret.HostPortGroup
+ for p_gp in port_grps_on_host:
+ if p_gp.spec.name == pg_name:
+ p_grp_vswitch_name = p_gp.vswitch.split("-")[-1]
+ return p_gp.spec.vlanId, p_grp_vswitch_name
+
+
+def create_port_group(session, pg_name, vswitch_name, vlan_id=0):
+ """
+ Creates a port group on the host system with the vlan tags
+ supplied. VLAN id 0 means no vlan id association.
+ """
+ client_factory = session._get_vim().client.factory
+ add_prt_grp_spec = vm_util.get_add_vswitch_port_group_spec(
+ client_factory,
+ vswitch_name,
+ pg_name,
+ vlan_id)
+ host_mor = session._call_method(vim_util, "get_objects",
+ "HostSystem")[0].obj
+ network_system_mor = session._call_method(vim_util,
+ "get_dynamic_property", host_mor,
+ "HostSystem", "configManager.networkSystem")
+ LOG.debug(_("Creating Port Group with name %s on "
+ "the ESX host") % pg_name)
+ try:
+ session._call_method(session._get_vim(),
+ "AddPortGroup", network_system_mor,
+ portgrp=add_prt_grp_spec)
+ except error_util.VimFaultException, exc:
+ # There can be a race condition when two instances try
+ # adding port groups at the same time. One succeeds, then
+ # the other one will get an exception. Since we are
+ # concerned with the port group being created, which is done
+ # by the other call, we can ignore the exception.
+ if error_util.FAULT_ALREADY_EXISTS not in exc.fault_list:
+ raise exception.Error(exc)
+ LOG.debug(_("Created Port Group with name %s on "
+ "the ESX host") % pg_name)
diff --git a/nova/virt/vmwareapi/read_write_util.py b/nova/virt/vmwareapi/read_write_util.py
index 33bef6d18..9663b1ca6 100644
--- a/nova/virt/vmwareapi/read_write_util.py
+++ b/nova/virt/vmwareapi/read_write_util.py
@@ -1,179 +1,179 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""Classes to handle image files
-
-Collection of classes to handle image upload/download to/from Image service
-(like Glance image storage and retrieval service) from/to ESX/ESXi server.
-
-"""
-
-import httplib
-import urllib
-import urllib2
-import urlparse
-
-from glance import client
-
-from nova import flags
-from nova import log as logging
-
-LOG = logging.getLogger("nova.virt.vmwareapi.read_write_util")
-
-FLAGS = flags.FLAGS
-
-USER_AGENT = "OpenStack-ESX-Adapter"
-
-try:
- READ_CHUNKSIZE = client.BaseClient.CHUNKSIZE
-except AttributeError:
- READ_CHUNKSIZE = 65536
-
-
-class GlanceFileRead(object):
- """Glance file read handler class."""
-
- def __init__(self, glance_read_iter):
- self.glance_read_iter = glance_read_iter
- self.iter = self.get_next()
-
- def read(self, chunk_size):
- """Read an item from the queue. The chunk size is ignored for the
- Client ImageBodyIterator uses its own CHUNKSIZE."""
- try:
- return self.iter.next()
- except StopIteration:
- return ""
-
- def get_next(self):
- """Get the next item from the image iterator."""
- for data in self.glance_read_iter:
- yield data
-
- def close(self):
- """A dummy close just to maintain consistency."""
- pass
-
-
-class VMwareHTTPFile(object):
- """Base class for HTTP file."""
-
- def __init__(self, file_handle):
- self.eof = False
- self.file_handle = file_handle
-
- def set_eof(self, eof):
- """Set the end of file marker."""
- self.eof = eof
-
- def get_eof(self):
- """Check if the end of file has been reached."""
- return self.eof
-
- def close(self):
- """Close the file handle."""
- try:
- self.file_handle.close()
- except Exception, exc:
- LOG.exception(exc)
-
- def __del__(self):
- """Close the file handle on garbage collection."""
- self.close()
-
- def _build_vim_cookie_headers(self, vim_cookies):
- """Build ESX host session cookie headers."""
- cookie_header = ""
- for vim_cookie in vim_cookies:
- cookie_header = vim_cookie.name + "=" + vim_cookie.value
- break
- return cookie_header
-
- def write(self, data):
- """Write data to the file."""
- raise NotImplementedError
-
- def read(self, chunk_size):
- """Read a chunk of data."""
- raise NotImplementedError
-
- def get_size(self):
- """Get size of the file to be read."""
- raise NotImplementedError
-
-
-class VMWareHTTPWriteFile(VMwareHTTPFile):
- """VMWare file write handler class."""
-
- def __init__(self, host, data_center_name, datastore_name, cookies,
- file_path, file_size, scheme="https"):
- base_url = "%s://%s/folder/%s" % (scheme, host, file_path)
- param_list = {"dcPath": data_center_name, "dsName": datastore_name}
- base_url = base_url + "?" + urllib.urlencode(param_list)
- (scheme, netloc, path, params, query, fragment) = \
- urlparse.urlparse(base_url)
- if scheme == "http":
- conn = httplib.HTTPConnection(netloc)
- elif scheme == "https":
- conn = httplib.HTTPSConnection(netloc)
- conn.putrequest("PUT", path + "?" + query)
- conn.putheader("User-Agent", USER_AGENT)
- conn.putheader("Content-Length", file_size)
- conn.putheader("Cookie", self._build_vim_cookie_headers(cookies))
- conn.endheaders()
- self.conn = conn
- VMwareHTTPFile.__init__(self, conn)
-
- def write(self, data):
- """Write to the file."""
- self.file_handle.send(data)
-
- def close(self):
- """Get the response and close the connection."""
- try:
- self.conn.getresponse()
- except Exception, excep:
- LOG.debug(_("Exception during HTTP connection close in "
- "VMWareHTTpWrite. Exception is %s") % excep)
- super(VMWareHTTPWriteFile, self).close()
-
-
-class VmWareHTTPReadFile(VMwareHTTPFile):
- """VMWare file read handler class."""
-
- def __init__(self, host, data_center_name, datastore_name, cookies,
- file_path, scheme="https"):
- base_url = "%s://%s/folder/%s" % (scheme, host,
- urllib.pathname2url(file_path))
- param_list = {"dcPath": data_center_name, "dsName": datastore_name}
- base_url = base_url + "?" + urllib.urlencode(param_list)
- headers = {'User-Agent': USER_AGENT,
- 'Cookie': self._build_vim_cookie_headers(cookies)}
- request = urllib2.Request(base_url, None, headers)
- conn = urllib2.urlopen(request)
- VMwareHTTPFile.__init__(self, conn)
-
- def read(self, chunk_size):
- """Read a chunk of data."""
- # We are ignoring the chunk size passed for we want the pipe to hold
- # data items of the chunk-size that Glance Client uses for read
- # while writing.
- return self.file_handle.read(READ_CHUNKSIZE)
-
- def get_size(self):
- """Get size of the file to be read."""
- return self.file_handle.headers.get("Content-Length", -1)
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""Classes to handle image files
+
+Collection of classes to handle image upload/download to/from Image service
+(like Glance image storage and retrieval service) from/to ESX/ESXi server.
+
+"""
+
+import httplib
+import urllib
+import urllib2
+import urlparse
+
+from glance import client
+
+from nova import flags
+from nova import log as logging
+
+LOG = logging.getLogger("nova.virt.vmwareapi.read_write_util")
+
+FLAGS = flags.FLAGS
+
+USER_AGENT = "OpenStack-ESX-Adapter"
+
+try:
+ READ_CHUNKSIZE = client.BaseClient.CHUNKSIZE
+except AttributeError:
+ READ_CHUNKSIZE = 65536
+
+
+class GlanceFileRead(object):
+ """Glance file read handler class."""
+
+ def __init__(self, glance_read_iter):
+ self.glance_read_iter = glance_read_iter
+ self.iter = self.get_next()
+
+ def read(self, chunk_size):
+ """Read an item from the queue. The chunk size is ignored for the
+ Client ImageBodyIterator uses its own CHUNKSIZE."""
+ try:
+ return self.iter.next()
+ except StopIteration:
+ return ""
+
+ def get_next(self):
+ """Get the next item from the image iterator."""
+ for data in self.glance_read_iter:
+ yield data
+
+ def close(self):
+ """A dummy close just to maintain consistency."""
+ pass
+
+
+class VMwareHTTPFile(object):
+ """Base class for HTTP file."""
+
+ def __init__(self, file_handle):
+ self.eof = False
+ self.file_handle = file_handle
+
+ def set_eof(self, eof):
+ """Set the end of file marker."""
+ self.eof = eof
+
+ def get_eof(self):
+ """Check if the end of file has been reached."""
+ return self.eof
+
+ def close(self):
+ """Close the file handle."""
+ try:
+ self.file_handle.close()
+ except Exception, exc:
+ LOG.exception(exc)
+
+ def __del__(self):
+ """Close the file handle on garbage collection."""
+ self.close()
+
+ def _build_vim_cookie_headers(self, vim_cookies):
+ """Build ESX host session cookie headers."""
+ cookie_header = ""
+ for vim_cookie in vim_cookies:
+ cookie_header = vim_cookie.name + "=" + vim_cookie.value
+ break
+ return cookie_header
+
+ def write(self, data):
+ """Write data to the file."""
+ raise NotImplementedError
+
+ def read(self, chunk_size):
+ """Read a chunk of data."""
+ raise NotImplementedError
+
+ def get_size(self):
+ """Get size of the file to be read."""
+ raise NotImplementedError
+
+
+class VMWareHTTPWriteFile(VMwareHTTPFile):
+ """VMWare file write handler class."""
+
+ def __init__(self, host, data_center_name, datastore_name, cookies,
+ file_path, file_size, scheme="https"):
+ base_url = "%s://%s/folder/%s" % (scheme, host, file_path)
+ param_list = {"dcPath": data_center_name, "dsName": datastore_name}
+ base_url = base_url + "?" + urllib.urlencode(param_list)
+ (scheme, netloc, path, params, query, fragment) = \
+ urlparse.urlparse(base_url)
+ if scheme == "http":
+ conn = httplib.HTTPConnection(netloc)
+ elif scheme == "https":
+ conn = httplib.HTTPSConnection(netloc)
+ conn.putrequest("PUT", path + "?" + query)
+ conn.putheader("User-Agent", USER_AGENT)
+ conn.putheader("Content-Length", file_size)
+ conn.putheader("Cookie", self._build_vim_cookie_headers(cookies))
+ conn.endheaders()
+ self.conn = conn
+ VMwareHTTPFile.__init__(self, conn)
+
+ def write(self, data):
+ """Write to the file."""
+ self.file_handle.send(data)
+
+ def close(self):
+ """Get the response and close the connection."""
+ try:
+ self.conn.getresponse()
+ except Exception, excep:
+ LOG.debug(_("Exception during HTTP connection close in "
+ "VMWareHTTpWrite. Exception is %s") % excep)
+ super(VMWareHTTPWriteFile, self).close()
+
+
+class VmWareHTTPReadFile(VMwareHTTPFile):
+ """VMWare file read handler class."""
+
+ def __init__(self, host, data_center_name, datastore_name, cookies,
+ file_path, scheme="https"):
+ base_url = "%s://%s/folder/%s" % (scheme, host,
+ urllib.pathname2url(file_path))
+ param_list = {"dcPath": data_center_name, "dsName": datastore_name}
+ base_url = base_url + "?" + urllib.urlencode(param_list)
+ headers = {'User-Agent': USER_AGENT,
+ 'Cookie': self._build_vim_cookie_headers(cookies)}
+ request = urllib2.Request(base_url, None, headers)
+ conn = urllib2.urlopen(request)
+ VMwareHTTPFile.__init__(self, conn)
+
+ def read(self, chunk_size):
+ """Read a chunk of data."""
+ # We are ignoring the chunk size passed for we want the pipe to hold
+ # data items of the chunk-size that Glance Client uses for read
+ # while writing.
+ return self.file_handle.read(READ_CHUNKSIZE)
+
+ def get_size(self):
+ """Get size of the file to be read."""
+ return self.file_handle.headers.get("Content-Length", -1)
diff --git a/nova/virt/vmwareapi/vim.py b/nova/virt/vmwareapi/vim.py
index e657824da..9a0647b28 100644
--- a/nova/virt/vmwareapi/vim.py
+++ b/nova/virt/vmwareapi/vim.py
@@ -1,181 +1,181 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""
-Classes for making VMware VI SOAP calls.
-"""
-
-import httplib
-
-try:
- import suds
-except ImportError:
- suds = None
-
-from nova import flags
-from nova.virt.vmwareapi import error_util
-
-RESP_NOT_XML_ERROR = 'Response is "text/html", not "text/xml"'
-CONN_ABORT_ERROR = 'Software caused connection abort'
-ADDRESS_IN_USE_ERROR = 'Address already in use'
-
-FLAGS = flags.FLAGS
-flags.DEFINE_string('vmwareapi_wsdl_loc',
- None,
- 'VIM Service WSDL Location'
- 'e.g http://<server>/vimService.wsdl'
- 'Due to a bug in vSphere ESX 4.1 default wsdl'
- 'Refer readme-vmware to setup')
-
-
-if suds:
-
- class VIMMessagePlugin(suds.plugin.MessagePlugin):
-
- def addAttributeForValue(self, node):
- # suds does not handle AnyType properly.
- # VI SDK requires type attribute to be set when AnyType is used
- if node.name == 'value':
- node.set('xsi:type', 'xsd:string')
-
- def marshalled(self, context):
- """suds will send the specified soap envelope.
- Provides the plugin with the opportunity to prune empty
- nodes and fixup nodes before sending it to the server.
- """
- # suds builds the entire request object based on the wsdl schema.
- # VI SDK throws server errors if optional SOAP nodes are sent
- # without values, e.g. <test/> as opposed to <test>test</test>
- context.envelope.prune()
- context.envelope.walk(self.addAttributeForValue)
-
-
-class Vim:
- """The VIM Object."""
-
- def __init__(self,
- protocol="https",
- host="localhost"):
- """
- Creates the necessary Communication interfaces and gets the
- ServiceContent for initiating SOAP transactions.
-
- protocol: http or https
- host : ESX IPAddress[:port] or ESX Hostname[:port]
- """
- if not suds:
- raise Exception(_("Unable to import suds."))
-
- self._protocol = protocol
- self._host_name = host
- wsdl_url = FLAGS.vmwareapi_wsdl_loc
- if wsdl_url is None:
- raise Exception(_("Must specify vmwareapi_wsdl_loc"))
- # TODO(sateesh): Use this when VMware fixes their faulty wsdl
- #wsdl_url = '%s://%s/sdk/vimService.wsdl' % (self._protocol,
- # self._host_name)
- url = '%s://%s/sdk' % (self._protocol, self._host_name)
- self.client = suds.client.Client(wsdl_url, location=url,
- plugins=[VIMMessagePlugin()])
- self._service_content = \
- self.RetrieveServiceContent("ServiceInstance")
-
- def get_service_content(self):
- """Gets the service content object."""
- return self._service_content
-
- def __getattr__(self, attr_name):
- """Makes the API calls and gets the result."""
- try:
- return object.__getattr__(self, attr_name)
- except AttributeError:
-
- def vim_request_handler(managed_object, **kwargs):
- """
- Builds the SOAP message and parses the response for fault
- checking and other errors.
-
- managed_object : Managed Object Reference or Managed
- Object Name
- **kwargs : Keyword arguments of the call
- """
- # Dynamic handler for VI SDK Calls
- try:
- request_mo = \
- self._request_managed_object_builder(managed_object)
- request = getattr(self.client.service, attr_name)
- response = request(request_mo, **kwargs)
- # To check for the faults that are part of the message body
- # and not returned as Fault object response from the ESX
- # SOAP server
- if hasattr(error_util.FaultCheckers,
- attr_name.lower() + "_fault_checker"):
- fault_checker = getattr(error_util.FaultCheckers,
- attr_name.lower() + "_fault_checker")
- fault_checker(response)
- return response
- # Catch the VimFaultException that is raised by the fault
- # check of the SOAP response
- except error_util.VimFaultException, excep:
- raise
- except suds.WebFault, excep:
- doc = excep.document
- detail = doc.childAtPath("/Envelope/Body/Fault/detail")
- fault_list = []
- for child in detail.getChildren():
- fault_list.append(child.get("type"))
- raise error_util.VimFaultException(fault_list, excep)
- except AttributeError, excep:
- raise error_util.VimAttributeError(_("No such SOAP method "
- "'%s' provided by VI SDK") % (attr_name), excep)
- except (httplib.CannotSendRequest,
- httplib.ResponseNotReady,
- httplib.CannotSendHeader), excep:
- raise error_util.SessionOverLoadException(_("httplib "
- "error in %s: ") % (attr_name), excep)
- except Exception, excep:
- # Socket errors which need special handling for they
- # might be caused by ESX API call overload
- if (str(excep).find(ADDRESS_IN_USE_ERROR) != -1 or
- str(excep).find(CONN_ABORT_ERROR)) != -1:
- raise error_util.SessionOverLoadException(_("Socket "
- "error in %s: ") % (attr_name), excep)
- # Type error that needs special handling for it might be
- # caused by ESX host API call overload
- elif str(excep).find(RESP_NOT_XML_ERROR) != -1:
- raise error_util.SessionOverLoadException(_("Type "
- "error in %s: ") % (attr_name), excep)
- else:
- raise error_util.VimException(
- _("Exception in %s ") % (attr_name), excep)
- return vim_request_handler
-
- def _request_managed_object_builder(self, managed_object):
- """Builds the request managed object."""
- # Request Managed Object Builder
- if isinstance(managed_object, str):
- mo = suds.sudsobject.Property(managed_object)
- mo._type = managed_object
- else:
- mo = managed_object
- return mo
-
- def __repr__(self):
- return "VIM Object"
-
- def __str__(self):
- return "VIM Object"
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""
+Classes for making VMware VI SOAP calls.
+"""
+
+import httplib
+
+try:
+ import suds
+except ImportError:
+ suds = None
+
+from nova import flags
+from nova.virt.vmwareapi import error_util
+
+RESP_NOT_XML_ERROR = 'Response is "text/html", not "text/xml"'
+CONN_ABORT_ERROR = 'Software caused connection abort'
+ADDRESS_IN_USE_ERROR = 'Address already in use'
+
+FLAGS = flags.FLAGS
+flags.DEFINE_string('vmwareapi_wsdl_loc',
+ None,
+ 'VIM Service WSDL Location'
+ 'e.g http://<server>/vimService.wsdl'
+ 'Due to a bug in vSphere ESX 4.1 default wsdl'
+ 'Refer readme-vmware to setup')
+
+
+if suds:
+
+ class VIMMessagePlugin(suds.plugin.MessagePlugin):
+
+ def addAttributeForValue(self, node):
+ # suds does not handle AnyType properly.
+ # VI SDK requires type attribute to be set when AnyType is used
+ if node.name == 'value':
+ node.set('xsi:type', 'xsd:string')
+
+ def marshalled(self, context):
+ """suds will send the specified soap envelope.
+ Provides the plugin with the opportunity to prune empty
+ nodes and fixup nodes before sending it to the server.
+ """
+ # suds builds the entire request object based on the wsdl schema.
+ # VI SDK throws server errors if optional SOAP nodes are sent
+ # without values, e.g. <test/> as opposed to <test>test</test>
+ context.envelope.prune()
+ context.envelope.walk(self.addAttributeForValue)
+
+
+class Vim:
+ """The VIM Object."""
+
+ def __init__(self,
+ protocol="https",
+ host="localhost"):
+ """
+ Creates the necessary Communication interfaces and gets the
+ ServiceContent for initiating SOAP transactions.
+
+ protocol: http or https
+ host : ESX IPAddress[:port] or ESX Hostname[:port]
+ """
+ if not suds:
+ raise Exception(_("Unable to import suds."))
+
+ self._protocol = protocol
+ self._host_name = host
+ wsdl_url = FLAGS.vmwareapi_wsdl_loc
+ if wsdl_url is None:
+ raise Exception(_("Must specify vmwareapi_wsdl_loc"))
+ # TODO(sateesh): Use this when VMware fixes their faulty wsdl
+ #wsdl_url = '%s://%s/sdk/vimService.wsdl' % (self._protocol,
+ # self._host_name)
+ url = '%s://%s/sdk' % (self._protocol, self._host_name)
+ self.client = suds.client.Client(wsdl_url, location=url,
+ plugins=[VIMMessagePlugin()])
+ self._service_content = \
+ self.RetrieveServiceContent("ServiceInstance")
+
+ def get_service_content(self):
+ """Gets the service content object."""
+ return self._service_content
+
+ def __getattr__(self, attr_name):
+ """Makes the API calls and gets the result."""
+ try:
+ return object.__getattr__(self, attr_name)
+ except AttributeError:
+
+ def vim_request_handler(managed_object, **kwargs):
+ """
+ Builds the SOAP message and parses the response for fault
+ checking and other errors.
+
+ managed_object : Managed Object Reference or Managed
+ Object Name
+ **kwargs : Keyword arguments of the call
+ """
+ # Dynamic handler for VI SDK Calls
+ try:
+ request_mo = \
+ self._request_managed_object_builder(managed_object)
+ request = getattr(self.client.service, attr_name)
+ response = request(request_mo, **kwargs)
+ # To check for the faults that are part of the message body
+ # and not returned as Fault object response from the ESX
+ # SOAP server
+ if hasattr(error_util.FaultCheckers,
+ attr_name.lower() + "_fault_checker"):
+ fault_checker = getattr(error_util.FaultCheckers,
+ attr_name.lower() + "_fault_checker")
+ fault_checker(response)
+ return response
+ # Catch the VimFaultException that is raised by the fault
+ # check of the SOAP response
+ except error_util.VimFaultException, excep:
+ raise
+ except suds.WebFault, excep:
+ doc = excep.document
+ detail = doc.childAtPath("/Envelope/Body/Fault/detail")
+ fault_list = []
+ for child in detail.getChildren():
+ fault_list.append(child.get("type"))
+ raise error_util.VimFaultException(fault_list, excep)
+ except AttributeError, excep:
+ raise error_util.VimAttributeError(_("No such SOAP method "
+ "'%s' provided by VI SDK") % (attr_name), excep)
+ except (httplib.CannotSendRequest,
+ httplib.ResponseNotReady,
+ httplib.CannotSendHeader), excep:
+ raise error_util.SessionOverLoadException(_("httplib "
+ "error in %s: ") % (attr_name), excep)
+ except Exception, excep:
+ # Socket errors which need special handling for they
+ # might be caused by ESX API call overload
+ if (str(excep).find(ADDRESS_IN_USE_ERROR) != -1 or
+ str(excep).find(CONN_ABORT_ERROR)) != -1:
+ raise error_util.SessionOverLoadException(_("Socket "
+ "error in %s: ") % (attr_name), excep)
+ # Type error that needs special handling for it might be
+ # caused by ESX host API call overload
+ elif str(excep).find(RESP_NOT_XML_ERROR) != -1:
+ raise error_util.SessionOverLoadException(_("Type "
+ "error in %s: ") % (attr_name), excep)
+ else:
+ raise error_util.VimException(
+ _("Exception in %s ") % (attr_name), excep)
+ return vim_request_handler
+
+ def _request_managed_object_builder(self, managed_object):
+ """Builds the request managed object."""
+ # Request Managed Object Builder
+ if isinstance(managed_object, str):
+ mo = suds.sudsobject.Property(managed_object)
+ mo._type = managed_object
+ else:
+ mo = managed_object
+ return mo
+
+ def __repr__(self):
+ return "VIM Object"
+
+ def __str__(self):
+ return "VIM Object"
diff --git a/nova/virt/vmwareapi/vim_util.py b/nova/virt/vmwareapi/vim_util.py
index e03daddac..08c85d82e 100644
--- a/nova/virt/vmwareapi/vim_util.py
+++ b/nova/virt/vmwareapi/vim_util.py
@@ -1,223 +1,223 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""
-The VMware API utility module.
-"""
-
-
-def build_selection_spec(client_factory, name):
- """Builds the selection spec."""
- sel_spec = client_factory.create('ns0:SelectionSpec')
- sel_spec.name = name
- return sel_spec
-
-
-def build_traversal_spec(client_factory, name, spec_type, path, skip,
- select_set):
- """Builds the traversal spec object."""
- traversal_spec = client_factory.create('ns0:TraversalSpec')
- traversal_spec.name = name
- traversal_spec.type = spec_type
- traversal_spec.path = path
- traversal_spec.skip = skip
- traversal_spec.selectSet = select_set
- return traversal_spec
-
-
-def build_recursive_traversal_spec(client_factory):
- """
- Builds the Recursive Traversal Spec to traverse the object managed
- object hierarchy.
- """
- visit_folders_select_spec = build_selection_spec(client_factory,
- "visitFolders")
- # For getting to hostFolder from datacenter
- dc_to_hf = build_traversal_spec(client_factory, "dc_to_hf", "Datacenter",
- "hostFolder", False,
- [visit_folders_select_spec])
- # For getting to vmFolder from datacenter
- dc_to_vmf = build_traversal_spec(client_factory, "dc_to_vmf", "Datacenter",
- "vmFolder", False,
- [visit_folders_select_spec])
- # For getting Host System to virtual machine
- h_to_vm = build_traversal_spec(client_factory, "h_to_vm", "HostSystem",
- "vm", False,
- [visit_folders_select_spec])
-
- # For getting to Host System from Compute Resource
- cr_to_h = build_traversal_spec(client_factory, "cr_to_h",
- "ComputeResource", "host", False, [])
-
- # For getting to datastore from Compute Resource
- cr_to_ds = build_traversal_spec(client_factory, "cr_to_ds",
- "ComputeResource", "datastore", False, [])
-
- rp_to_rp_select_spec = build_selection_spec(client_factory, "rp_to_rp")
- rp_to_vm_select_spec = build_selection_spec(client_factory, "rp_to_vm")
- # For getting to resource pool from Compute Resource
- cr_to_rp = build_traversal_spec(client_factory, "cr_to_rp",
- "ComputeResource", "resourcePool", False,
- [rp_to_rp_select_spec, rp_to_vm_select_spec])
-
- # For getting to child res pool from the parent res pool
- rp_to_rp = build_traversal_spec(client_factory, "rp_to_rp", "ResourcePool",
- "resourcePool", False,
- [rp_to_rp_select_spec, rp_to_vm_select_spec])
-
- # For getting to Virtual Machine from the Resource Pool
- rp_to_vm = build_traversal_spec(client_factory, "rp_to_vm", "ResourcePool",
- "vm", False,
- [rp_to_rp_select_spec, rp_to_vm_select_spec])
-
- # Get the assorted traversal spec which takes care of the objects to
- # be searched for from the root folder
- traversal_spec = build_traversal_spec(client_factory, "visitFolders",
- "Folder", "childEntity", False,
- [visit_folders_select_spec, dc_to_hf,
- dc_to_vmf, cr_to_ds, cr_to_h, cr_to_rp,
- rp_to_rp, h_to_vm, rp_to_vm])
- return traversal_spec
-
-
-def build_property_spec(client_factory, type="VirtualMachine",
- properties_to_collect=None,
- all_properties=False):
- """Builds the Property Spec."""
- if not properties_to_collect:
- properties_to_collect = ["name"]
-
- property_spec = client_factory.create('ns0:PropertySpec')
- property_spec.all = all_properties
- property_spec.pathSet = properties_to_collect
- property_spec.type = type
- return property_spec
-
-
-def build_object_spec(client_factory, root_folder, traversal_specs):
- """Builds the object Spec."""
- object_spec = client_factory.create('ns0:ObjectSpec')
- object_spec.obj = root_folder
- object_spec.skip = False
- object_spec.selectSet = traversal_specs
- return object_spec
-
-
-def build_property_filter_spec(client_factory, property_specs, object_specs):
- """Builds the Property Filter Spec."""
- property_filter_spec = client_factory.create('ns0:PropertyFilterSpec')
- property_filter_spec.propSet = property_specs
- property_filter_spec.objectSet = object_specs
- return property_filter_spec
-
-
-def get_object_properties(vim, collector, mobj, type, properties):
- """Gets the properties of the Managed object specified."""
- client_factory = vim.client.factory
- if mobj is None:
- return None
- usecoll = collector
- if usecoll is None:
- usecoll = vim.get_service_content().propertyCollector
- property_filter_spec = client_factory.create('ns0:PropertyFilterSpec')
- property_spec = client_factory.create('ns0:PropertySpec')
- property_spec.all = (properties is None or len(properties) == 0)
- property_spec.pathSet = properties
- property_spec.type = type
- object_spec = client_factory.create('ns0:ObjectSpec')
- object_spec.obj = mobj
- object_spec.skip = False
- property_filter_spec.propSet = [property_spec]
- property_filter_spec.objectSet = [object_spec]
- return vim.RetrieveProperties(usecoll, specSet=[property_filter_spec])
-
-
-def get_dynamic_property(vim, mobj, type, property_name):
- """Gets a particular property of the Managed Object."""
- obj_content = \
- get_object_properties(vim, None, mobj, type, [property_name])
- property_value = None
- if obj_content:
- dynamic_property = obj_content[0].propSet
- if dynamic_property:
- property_value = dynamic_property[0].val
- return property_value
-
-
-def get_objects(vim, type, properties_to_collect=None, all=False):
- """Gets the list of objects of the type specified."""
- if not properties_to_collect:
- properties_to_collect = ["name"]
-
- client_factory = vim.client.factory
- object_spec = build_object_spec(client_factory,
- vim.get_service_content().rootFolder,
- [build_recursive_traversal_spec(client_factory)])
- property_spec = build_property_spec(client_factory, type=type,
- properties_to_collect=properties_to_collect,
- all_properties=all)
- property_filter_spec = build_property_filter_spec(client_factory,
- [property_spec],
- [object_spec])
- return vim.RetrieveProperties(vim.get_service_content().propertyCollector,
- specSet=[property_filter_spec])
-
-
-def get_prop_spec(client_factory, spec_type, properties):
- """Builds the Property Spec Object."""
- prop_spec = client_factory.create('ns0:PropertySpec')
- prop_spec.type = spec_type
- prop_spec.pathSet = properties
- return prop_spec
-
-
-def get_obj_spec(client_factory, obj, select_set=None):
- """Builds the Object Spec object."""
- obj_spec = client_factory.create('ns0:ObjectSpec')
- obj_spec.obj = obj
- obj_spec.skip = False
- if select_set is not None:
- obj_spec.selectSet = select_set
- return obj_spec
-
-
-def get_prop_filter_spec(client_factory, obj_spec, prop_spec):
- """Builds the Property Filter Spec Object."""
- prop_filter_spec = \
- client_factory.create('ns0:PropertyFilterSpec')
- prop_filter_spec.propSet = prop_spec
- prop_filter_spec.objectSet = obj_spec
- return prop_filter_spec
-
-
-def get_properties_for_a_collection_of_objects(vim, type,
- obj_list, properties):
- """
- Gets the list of properties for the collection of
- objects of the type specified.
- """
- client_factory = vim.client.factory
- if len(obj_list) == 0:
- return []
- prop_spec = get_prop_spec(client_factory, type, properties)
- lst_obj_specs = []
- for obj in obj_list:
- lst_obj_specs.append(get_obj_spec(client_factory, obj))
- prop_filter_spec = get_prop_filter_spec(client_factory,
- lst_obj_specs, [prop_spec])
- return vim.RetrieveProperties(vim.get_service_content().propertyCollector,
- specSet=[prop_filter_spec])
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""
+The VMware API utility module.
+"""
+
+
+def build_selection_spec(client_factory, name):
+ """Builds the selection spec."""
+ sel_spec = client_factory.create('ns0:SelectionSpec')
+ sel_spec.name = name
+ return sel_spec
+
+
+def build_traversal_spec(client_factory, name, spec_type, path, skip,
+ select_set):
+ """Builds the traversal spec object."""
+ traversal_spec = client_factory.create('ns0:TraversalSpec')
+ traversal_spec.name = name
+ traversal_spec.type = spec_type
+ traversal_spec.path = path
+ traversal_spec.skip = skip
+ traversal_spec.selectSet = select_set
+ return traversal_spec
+
+
+def build_recursive_traversal_spec(client_factory):
+ """
+ Builds the Recursive Traversal Spec to traverse the object managed
+ object hierarchy.
+ """
+ visit_folders_select_spec = build_selection_spec(client_factory,
+ "visitFolders")
+ # For getting to hostFolder from datacenter
+ dc_to_hf = build_traversal_spec(client_factory, "dc_to_hf", "Datacenter",
+ "hostFolder", False,
+ [visit_folders_select_spec])
+ # For getting to vmFolder from datacenter
+ dc_to_vmf = build_traversal_spec(client_factory, "dc_to_vmf", "Datacenter",
+ "vmFolder", False,
+ [visit_folders_select_spec])
+ # For getting Host System to virtual machine
+ h_to_vm = build_traversal_spec(client_factory, "h_to_vm", "HostSystem",
+ "vm", False,
+ [visit_folders_select_spec])
+
+ # For getting to Host System from Compute Resource
+ cr_to_h = build_traversal_spec(client_factory, "cr_to_h",
+ "ComputeResource", "host", False, [])
+
+ # For getting to datastore from Compute Resource
+ cr_to_ds = build_traversal_spec(client_factory, "cr_to_ds",
+ "ComputeResource", "datastore", False, [])
+
+ rp_to_rp_select_spec = build_selection_spec(client_factory, "rp_to_rp")
+ rp_to_vm_select_spec = build_selection_spec(client_factory, "rp_to_vm")
+ # For getting to resource pool from Compute Resource
+ cr_to_rp = build_traversal_spec(client_factory, "cr_to_rp",
+ "ComputeResource", "resourcePool", False,
+ [rp_to_rp_select_spec, rp_to_vm_select_spec])
+
+ # For getting to child res pool from the parent res pool
+ rp_to_rp = build_traversal_spec(client_factory, "rp_to_rp", "ResourcePool",
+ "resourcePool", False,
+ [rp_to_rp_select_spec, rp_to_vm_select_spec])
+
+ # For getting to Virtual Machine from the Resource Pool
+ rp_to_vm = build_traversal_spec(client_factory, "rp_to_vm", "ResourcePool",
+ "vm", False,
+ [rp_to_rp_select_spec, rp_to_vm_select_spec])
+
+ # Get the assorted traversal spec which takes care of the objects to
+ # be searched for from the root folder
+ traversal_spec = build_traversal_spec(client_factory, "visitFolders",
+ "Folder", "childEntity", False,
+ [visit_folders_select_spec, dc_to_hf,
+ dc_to_vmf, cr_to_ds, cr_to_h, cr_to_rp,
+ rp_to_rp, h_to_vm, rp_to_vm])
+ return traversal_spec
+
+
+def build_property_spec(client_factory, type="VirtualMachine",
+ properties_to_collect=None,
+ all_properties=False):
+ """Builds the Property Spec."""
+ if not properties_to_collect:
+ properties_to_collect = ["name"]
+
+ property_spec = client_factory.create('ns0:PropertySpec')
+ property_spec.all = all_properties
+ property_spec.pathSet = properties_to_collect
+ property_spec.type = type
+ return property_spec
+
+
+def build_object_spec(client_factory, root_folder, traversal_specs):
+ """Builds the object Spec."""
+ object_spec = client_factory.create('ns0:ObjectSpec')
+ object_spec.obj = root_folder
+ object_spec.skip = False
+ object_spec.selectSet = traversal_specs
+ return object_spec
+
+
+def build_property_filter_spec(client_factory, property_specs, object_specs):
+ """Builds the Property Filter Spec."""
+ property_filter_spec = client_factory.create('ns0:PropertyFilterSpec')
+ property_filter_spec.propSet = property_specs
+ property_filter_spec.objectSet = object_specs
+ return property_filter_spec
+
+
+def get_object_properties(vim, collector, mobj, type, properties):
+ """Gets the properties of the Managed object specified."""
+ client_factory = vim.client.factory
+ if mobj is None:
+ return None
+ usecoll = collector
+ if usecoll is None:
+ usecoll = vim.get_service_content().propertyCollector
+ property_filter_spec = client_factory.create('ns0:PropertyFilterSpec')
+ property_spec = client_factory.create('ns0:PropertySpec')
+ property_spec.all = (properties is None or len(properties) == 0)
+ property_spec.pathSet = properties
+ property_spec.type = type
+ object_spec = client_factory.create('ns0:ObjectSpec')
+ object_spec.obj = mobj
+ object_spec.skip = False
+ property_filter_spec.propSet = [property_spec]
+ property_filter_spec.objectSet = [object_spec]
+ return vim.RetrieveProperties(usecoll, specSet=[property_filter_spec])
+
+
+def get_dynamic_property(vim, mobj, type, property_name):
+ """Gets a particular property of the Managed Object."""
+ obj_content = \
+ get_object_properties(vim, None, mobj, type, [property_name])
+ property_value = None
+ if obj_content:
+ dynamic_property = obj_content[0].propSet
+ if dynamic_property:
+ property_value = dynamic_property[0].val
+ return property_value
+
+
+def get_objects(vim, type, properties_to_collect=None, all=False):
+ """Gets the list of objects of the type specified."""
+ if not properties_to_collect:
+ properties_to_collect = ["name"]
+
+ client_factory = vim.client.factory
+ object_spec = build_object_spec(client_factory,
+ vim.get_service_content().rootFolder,
+ [build_recursive_traversal_spec(client_factory)])
+ property_spec = build_property_spec(client_factory, type=type,
+ properties_to_collect=properties_to_collect,
+ all_properties=all)
+ property_filter_spec = build_property_filter_spec(client_factory,
+ [property_spec],
+ [object_spec])
+ return vim.RetrieveProperties(vim.get_service_content().propertyCollector,
+ specSet=[property_filter_spec])
+
+
+def get_prop_spec(client_factory, spec_type, properties):
+ """Builds the Property Spec Object."""
+ prop_spec = client_factory.create('ns0:PropertySpec')
+ prop_spec.type = spec_type
+ prop_spec.pathSet = properties
+ return prop_spec
+
+
+def get_obj_spec(client_factory, obj, select_set=None):
+ """Builds the Object Spec object."""
+ obj_spec = client_factory.create('ns0:ObjectSpec')
+ obj_spec.obj = obj
+ obj_spec.skip = False
+ if select_set is not None:
+ obj_spec.selectSet = select_set
+ return obj_spec
+
+
+def get_prop_filter_spec(client_factory, obj_spec, prop_spec):
+ """Builds the Property Filter Spec Object."""
+ prop_filter_spec = \
+ client_factory.create('ns0:PropertyFilterSpec')
+ prop_filter_spec.propSet = prop_spec
+ prop_filter_spec.objectSet = obj_spec
+ return prop_filter_spec
+
+
+def get_properties_for_a_collection_of_objects(vim, type,
+ obj_list, properties):
+ """
+ Gets the list of properties for the collection of
+ objects of the type specified.
+ """
+ client_factory = vim.client.factory
+ if len(obj_list) == 0:
+ return []
+ prop_spec = get_prop_spec(client_factory, type, properties)
+ lst_obj_specs = []
+ for obj in obj_list:
+ lst_obj_specs.append(get_obj_spec(client_factory, obj))
+ prop_filter_spec = get_prop_filter_spec(client_factory,
+ lst_obj_specs, [prop_spec])
+ return vim.RetrieveProperties(vim.get_service_content().propertyCollector,
+ specSet=[prop_filter_spec])
diff --git a/nova/virt/vmwareapi/vm_util.py b/nova/virt/vmwareapi/vm_util.py
index dd1c81196..a23b1575c 100644
--- a/nova/virt/vmwareapi/vm_util.py
+++ b/nova/virt/vmwareapi/vm_util.py
@@ -1,325 +1,325 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-"""
-The VMware API VM utility module to build SOAP object specs.
-"""
-
-
-def build_datastore_path(datastore_name, path):
- """Build the datastore compliant path."""
- return "[%s] %s" % (datastore_name, path)
-
-
-def split_datastore_path(datastore_path):
- """
- Split the VMWare style datastore path to get the Datastore
- name and the entity path.
- """
- spl = datastore_path.split('[', 1)[1].split(']', 1)
- path = ""
- if len(spl) == 1:
- datastore_url = spl[0]
- else:
- datastore_url, path = spl
- return datastore_url, path.strip()
-
-
-def get_vm_create_spec(client_factory, instance, data_store_name,
- vif_infos, os_type="otherGuest"):
- """Builds the VM Create spec."""
- config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
- config_spec.name = instance.name
- config_spec.guestId = os_type
-
- vm_file_info = client_factory.create('ns0:VirtualMachineFileInfo')
- vm_file_info.vmPathName = "[" + data_store_name + "]"
- config_spec.files = vm_file_info
-
- tools_info = client_factory.create('ns0:ToolsConfigInfo')
- tools_info.afterPowerOn = True
- tools_info.afterResume = True
- tools_info.beforeGuestStandby = True
- tools_info.beforeGuestShutdown = True
- tools_info.beforeGuestReboot = True
-
- config_spec.tools = tools_info
- config_spec.numCPUs = int(instance.vcpus)
- config_spec.memoryMB = int(instance.memory_mb)
-
- vif_spec_list = []
- for vif_info in vif_infos:
- vif_spec = create_network_spec(client_factory, vif_info)
- vif_spec_list.append(vif_spec)
-
- device_config_spec = vif_spec_list
-
- config_spec.deviceChange = device_config_spec
- return config_spec
-
-
-def create_controller_spec(client_factory, key):
- """
- Builds a Config Spec for the LSI Logic Controller's addition
- which acts as the controller for the virtual hard disk to be attached
- to the VM.
- """
- # Create a controller for the Virtual Hard Disk
- virtual_device_config = \
- client_factory.create('ns0:VirtualDeviceConfigSpec')
- virtual_device_config.operation = "add"
- virtual_lsi = \
- client_factory.create('ns0:VirtualLsiLogicController')
- virtual_lsi.key = key
- virtual_lsi.busNumber = 0
- virtual_lsi.sharedBus = "noSharing"
- virtual_device_config.device = virtual_lsi
- return virtual_device_config
-
-
-def create_network_spec(client_factory, vif_info):
- """
- Builds a config spec for the addition of a new network
- adapter to the VM.
- """
- network_spec = \
- client_factory.create('ns0:VirtualDeviceConfigSpec')
- network_spec.operation = "add"
-
- # Get the recommended card type for the VM based on the guest OS of the VM
- net_device = client_factory.create('ns0:VirtualPCNet32')
-
- # NOTE(asomya): Only works on ESXi if the portgroup binding is set to
- # ephemeral. Invalid configuration if set to static and the NIC does
- # not come up on boot if set to dynamic.
- network_ref = vif_info['network_ref']
- network_name = vif_info['network_name']
- mac_address = vif_info['mac_address']
- backing = None
- if (network_ref and
- network_ref['type'] == "DistributedVirtualPortgroup"):
- backing_name = \
- 'ns0:VirtualEthernetCardDistributedVirtualPortBackingInfo'
- backing = \
- client_factory.create(backing_name)
- portgroup = \
- client_factory.create('ns0:DistributedVirtualSwitchPortConnection')
- portgroup.switchUuid = network_ref['dvsw']
- portgroup.portgroupKey = network_ref['dvpg']
- backing.port = portgroup
- else:
- backing = \
- client_factory.create('ns0:VirtualEthernetCardNetworkBackingInfo')
- backing.deviceName = network_name
-
- connectable_spec = \
- client_factory.create('ns0:VirtualDeviceConnectInfo')
- connectable_spec.startConnected = True
- connectable_spec.allowGuestControl = True
- connectable_spec.connected = True
-
- net_device.connectable = connectable_spec
- net_device.backing = backing
-
- # The Server assigns a Key to the device. Here we pass a -ve temporary key.
- # -ve because actual keys are +ve numbers and we don't
- # want a clash with the key that server might associate with the device
- net_device.key = -47
- net_device.addressType = "manual"
- net_device.macAddress = mac_address
- net_device.wakeOnLanEnabled = True
-
- network_spec.device = net_device
- return network_spec
-
-
-def get_vmdk_attach_config_spec(client_factory, disksize, file_path,
- adapter_type="lsiLogic"):
- """Builds the vmdk attach config spec."""
- config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
-
- # The controller Key pertains to the Key of the LSI Logic Controller, which
- # controls this Hard Disk
- device_config_spec = []
- # For IDE devices, there are these two default controllers created in the
- # VM having keys 200 and 201
- if adapter_type == "ide":
- controller_key = 200
- else:
- controller_key = -101
- controller_spec = create_controller_spec(client_factory,
- controller_key)
- device_config_spec.append(controller_spec)
- virtual_device_config_spec = create_virtual_disk_spec(client_factory,
- disksize, controller_key, file_path)
-
- device_config_spec.append(virtual_device_config_spec)
-
- config_spec.deviceChange = device_config_spec
- return config_spec
-
-
-def get_vmdk_file_path_and_adapter_type(client_factory, hardware_devices):
- """Gets the vmdk file path and the storage adapter type."""
- if hardware_devices.__class__.__name__ == "ArrayOfVirtualDevice":
- hardware_devices = hardware_devices.VirtualDevice
- vmdk_file_path = None
- vmdk_controler_key = None
-
- adapter_type_dict = {}
- for device in hardware_devices:
- if device.__class__.__name__ == "VirtualDisk" and \
- device.backing.__class__.__name__ \
- == "VirtualDiskFlatVer2BackingInfo":
- vmdk_file_path = device.backing.fileName
- vmdk_controler_key = device.controllerKey
- elif device.__class__.__name__ == "VirtualLsiLogicController":
- adapter_type_dict[device.key] = "lsiLogic"
- elif device.__class__.__name__ == "VirtualBusLogicController":
- adapter_type_dict[device.key] = "busLogic"
- elif device.__class__.__name__ == "VirtualIDEController":
- adapter_type_dict[device.key] = "ide"
- elif device.__class__.__name__ == "VirtualLsiLogicSASController":
- adapter_type_dict[device.key] = "lsiLogic"
-
- adapter_type = adapter_type_dict.get(vmdk_controler_key, "")
-
- return vmdk_file_path, adapter_type
-
-
-def get_copy_virtual_disk_spec(client_factory, adapter_type="lsilogic"):
- """Builds the Virtual Disk copy spec."""
- dest_spec = client_factory.create('ns0:VirtualDiskSpec')
- dest_spec.adapterType = adapter_type
- dest_spec.diskType = "thick"
- return dest_spec
-
-
-def get_vmdk_create_spec(client_factory, size_in_kb, adapter_type="lsiLogic"):
- """Builds the virtual disk create spec."""
- create_vmdk_spec = \
- client_factory.create('ns0:FileBackedVirtualDiskSpec')
- create_vmdk_spec.adapterType = adapter_type
- create_vmdk_spec.diskType = "thick"
- create_vmdk_spec.capacityKb = size_in_kb
- return create_vmdk_spec
-
-
-def create_virtual_disk_spec(client_factory, disksize, controller_key,
- file_path=None):
- """
- Builds spec for the creation of a new/ attaching of an already existing
- Virtual Disk to the VM.
- """
- virtual_device_config = \
- client_factory.create('ns0:VirtualDeviceConfigSpec')
- virtual_device_config.operation = "add"
- if file_path is None:
- virtual_device_config.fileOperation = "create"
-
- virtual_disk = client_factory.create('ns0:VirtualDisk')
-
- disk_file_backing = \
- client_factory.create('ns0:VirtualDiskFlatVer2BackingInfo')
- disk_file_backing.diskMode = "persistent"
- disk_file_backing.thinProvisioned = False
- if file_path is not None:
- disk_file_backing.fileName = file_path
- else:
- disk_file_backing.fileName = ""
-
- connectable_spec = client_factory.create('ns0:VirtualDeviceConnectInfo')
- connectable_spec.startConnected = True
- connectable_spec.allowGuestControl = False
- connectable_spec.connected = True
-
- virtual_disk.backing = disk_file_backing
- virtual_disk.connectable = connectable_spec
-
- # The Server assigns a Key to the device. Here we pass a -ve random key.
- # -ve because actual keys are +ve numbers and we don't
- # want a clash with the key that server might associate with the device
- virtual_disk.key = -100
- virtual_disk.controllerKey = controller_key
- virtual_disk.unitNumber = 0
- virtual_disk.capacityInKB = disksize
-
- virtual_device_config.device = virtual_disk
-
- return virtual_device_config
-
-
-def get_dummy_vm_create_spec(client_factory, name, data_store_name):
- """Builds the dummy VM create spec."""
- config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
-
- config_spec.name = name
- config_spec.guestId = "otherGuest"
-
- vm_file_info = client_factory.create('ns0:VirtualMachineFileInfo')
- vm_file_info.vmPathName = "[" + data_store_name + "]"
- config_spec.files = vm_file_info
-
- tools_info = client_factory.create('ns0:ToolsConfigInfo')
- tools_info.afterPowerOn = True
- tools_info.afterResume = True
- tools_info.beforeGuestStandby = True
- tools_info.beforeGuestShutdown = True
- tools_info.beforeGuestReboot = True
-
- config_spec.tools = tools_info
- config_spec.numCPUs = 1
- config_spec.memoryMB = 4
-
- controller_key = -101
- controller_spec = create_controller_spec(client_factory, controller_key)
- disk_spec = create_virtual_disk_spec(client_factory, 1024, controller_key)
-
- device_config_spec = [controller_spec, disk_spec]
-
- config_spec.deviceChange = device_config_spec
- return config_spec
-
-
-def get_machine_id_change_spec(client_factory, machine_id_str):
- """Builds the machine id change config spec."""
- virtual_machine_config_spec = \
- client_factory.create('ns0:VirtualMachineConfigSpec')
-
- opt = client_factory.create('ns0:OptionValue')
- opt.key = "machine.id"
- opt.value = machine_id_str
- virtual_machine_config_spec.extraConfig = [opt]
- return virtual_machine_config_spec
-
-
-def get_add_vswitch_port_group_spec(client_factory, vswitch_name,
- port_group_name, vlan_id):
- """Builds the virtual switch port group add spec."""
- vswitch_port_group_spec = client_factory.create('ns0:HostPortGroupSpec')
- vswitch_port_group_spec.name = port_group_name
- vswitch_port_group_spec.vswitchName = vswitch_name
-
- # VLAN ID of 0 means that VLAN tagging is not to be done for the network.
- vswitch_port_group_spec.vlanId = int(vlan_id)
-
- policy = client_factory.create('ns0:HostNetworkPolicy')
- nicteaming = client_factory.create('ns0:HostNicTeamingPolicy')
- nicteaming.notifySwitches = True
- policy.nicTeaming = nicteaming
-
- vswitch_port_group_spec.policy = policy
- return vswitch_port_group_spec
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+"""
+The VMware API VM utility module to build SOAP object specs.
+"""
+
+
+def build_datastore_path(datastore_name, path):
+ """Build the datastore compliant path."""
+ return "[%s] %s" % (datastore_name, path)
+
+
+def split_datastore_path(datastore_path):
+ """
+ Split the VMWare style datastore path to get the Datastore
+ name and the entity path.
+ """
+ spl = datastore_path.split('[', 1)[1].split(']', 1)
+ path = ""
+ if len(spl) == 1:
+ datastore_url = spl[0]
+ else:
+ datastore_url, path = spl
+ return datastore_url, path.strip()
+
+
+def get_vm_create_spec(client_factory, instance, data_store_name,
+ vif_infos, os_type="otherGuest"):
+ """Builds the VM Create spec."""
+ config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
+ config_spec.name = instance.name
+ config_spec.guestId = os_type
+
+ vm_file_info = client_factory.create('ns0:VirtualMachineFileInfo')
+ vm_file_info.vmPathName = "[" + data_store_name + "]"
+ config_spec.files = vm_file_info
+
+ tools_info = client_factory.create('ns0:ToolsConfigInfo')
+ tools_info.afterPowerOn = True
+ tools_info.afterResume = True
+ tools_info.beforeGuestStandby = True
+ tools_info.beforeGuestShutdown = True
+ tools_info.beforeGuestReboot = True
+
+ config_spec.tools = tools_info
+ config_spec.numCPUs = int(instance.vcpus)
+ config_spec.memoryMB = int(instance.memory_mb)
+
+ vif_spec_list = []
+ for vif_info in vif_infos:
+ vif_spec = create_network_spec(client_factory, vif_info)
+ vif_spec_list.append(vif_spec)
+
+ device_config_spec = vif_spec_list
+
+ config_spec.deviceChange = device_config_spec
+ return config_spec
+
+
+def create_controller_spec(client_factory, key):
+ """
+ Builds a Config Spec for the LSI Logic Controller's addition
+ which acts as the controller for the virtual hard disk to be attached
+ to the VM.
+ """
+ # Create a controller for the Virtual Hard Disk
+ virtual_device_config = \
+ client_factory.create('ns0:VirtualDeviceConfigSpec')
+ virtual_device_config.operation = "add"
+ virtual_lsi = \
+ client_factory.create('ns0:VirtualLsiLogicController')
+ virtual_lsi.key = key
+ virtual_lsi.busNumber = 0
+ virtual_lsi.sharedBus = "noSharing"
+ virtual_device_config.device = virtual_lsi
+ return virtual_device_config
+
+
+def create_network_spec(client_factory, vif_info):
+ """
+ Builds a config spec for the addition of a new network
+ adapter to the VM.
+ """
+ network_spec = \
+ client_factory.create('ns0:VirtualDeviceConfigSpec')
+ network_spec.operation = "add"
+
+ # Get the recommended card type for the VM based on the guest OS of the VM
+ net_device = client_factory.create('ns0:VirtualPCNet32')
+
+ # NOTE(asomya): Only works on ESXi if the portgroup binding is set to
+ # ephemeral. Invalid configuration if set to static and the NIC does
+ # not come up on boot if set to dynamic.
+ network_ref = vif_info['network_ref']
+ network_name = vif_info['network_name']
+ mac_address = vif_info['mac_address']
+ backing = None
+ if (network_ref and
+ network_ref['type'] == "DistributedVirtualPortgroup"):
+ backing_name = \
+ 'ns0:VirtualEthernetCardDistributedVirtualPortBackingInfo'
+ backing = \
+ client_factory.create(backing_name)
+ portgroup = \
+ client_factory.create('ns0:DistributedVirtualSwitchPortConnection')
+ portgroup.switchUuid = network_ref['dvsw']
+ portgroup.portgroupKey = network_ref['dvpg']
+ backing.port = portgroup
+ else:
+ backing = \
+ client_factory.create('ns0:VirtualEthernetCardNetworkBackingInfo')
+ backing.deviceName = network_name
+
+ connectable_spec = \
+ client_factory.create('ns0:VirtualDeviceConnectInfo')
+ connectable_spec.startConnected = True
+ connectable_spec.allowGuestControl = True
+ connectable_spec.connected = True
+
+ net_device.connectable = connectable_spec
+ net_device.backing = backing
+
+ # The Server assigns a Key to the device. Here we pass a -ve temporary key.
+ # -ve because actual keys are +ve numbers and we don't
+ # want a clash with the key that server might associate with the device
+ net_device.key = -47
+ net_device.addressType = "manual"
+ net_device.macAddress = mac_address
+ net_device.wakeOnLanEnabled = True
+
+ network_spec.device = net_device
+ return network_spec
+
+
+def get_vmdk_attach_config_spec(client_factory, disksize, file_path,
+ adapter_type="lsiLogic"):
+ """Builds the vmdk attach config spec."""
+ config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
+
+ # The controller Key pertains to the Key of the LSI Logic Controller, which
+ # controls this Hard Disk
+ device_config_spec = []
+ # For IDE devices, there are these two default controllers created in the
+ # VM having keys 200 and 201
+ if adapter_type == "ide":
+ controller_key = 200
+ else:
+ controller_key = -101
+ controller_spec = create_controller_spec(client_factory,
+ controller_key)
+ device_config_spec.append(controller_spec)
+ virtual_device_config_spec = create_virtual_disk_spec(client_factory,
+ disksize, controller_key, file_path)
+
+ device_config_spec.append(virtual_device_config_spec)
+
+ config_spec.deviceChange = device_config_spec
+ return config_spec
+
+
+def get_vmdk_file_path_and_adapter_type(client_factory, hardware_devices):
+ """Gets the vmdk file path and the storage adapter type."""
+ if hardware_devices.__class__.__name__ == "ArrayOfVirtualDevice":
+ hardware_devices = hardware_devices.VirtualDevice
+ vmdk_file_path = None
+ vmdk_controler_key = None
+
+ adapter_type_dict = {}
+ for device in hardware_devices:
+ if device.__class__.__name__ == "VirtualDisk" and \
+ device.backing.__class__.__name__ \
+ == "VirtualDiskFlatVer2BackingInfo":
+ vmdk_file_path = device.backing.fileName
+ vmdk_controler_key = device.controllerKey
+ elif device.__class__.__name__ == "VirtualLsiLogicController":
+ adapter_type_dict[device.key] = "lsiLogic"
+ elif device.__class__.__name__ == "VirtualBusLogicController":
+ adapter_type_dict[device.key] = "busLogic"
+ elif device.__class__.__name__ == "VirtualIDEController":
+ adapter_type_dict[device.key] = "ide"
+ elif device.__class__.__name__ == "VirtualLsiLogicSASController":
+ adapter_type_dict[device.key] = "lsiLogic"
+
+ adapter_type = adapter_type_dict.get(vmdk_controler_key, "")
+
+ return vmdk_file_path, adapter_type
+
+
+def get_copy_virtual_disk_spec(client_factory, adapter_type="lsilogic"):
+ """Builds the Virtual Disk copy spec."""
+ dest_spec = client_factory.create('ns0:VirtualDiskSpec')
+ dest_spec.adapterType = adapter_type
+ dest_spec.diskType = "thick"
+ return dest_spec
+
+
+def get_vmdk_create_spec(client_factory, size_in_kb, adapter_type="lsiLogic"):
+ """Builds the virtual disk create spec."""
+ create_vmdk_spec = \
+ client_factory.create('ns0:FileBackedVirtualDiskSpec')
+ create_vmdk_spec.adapterType = adapter_type
+ create_vmdk_spec.diskType = "thick"
+ create_vmdk_spec.capacityKb = size_in_kb
+ return create_vmdk_spec
+
+
+def create_virtual_disk_spec(client_factory, disksize, controller_key,
+ file_path=None):
+ """
+ Builds spec for the creation of a new/ attaching of an already existing
+ Virtual Disk to the VM.
+ """
+ virtual_device_config = \
+ client_factory.create('ns0:VirtualDeviceConfigSpec')
+ virtual_device_config.operation = "add"
+ if file_path is None:
+ virtual_device_config.fileOperation = "create"
+
+ virtual_disk = client_factory.create('ns0:VirtualDisk')
+
+ disk_file_backing = \
+ client_factory.create('ns0:VirtualDiskFlatVer2BackingInfo')
+ disk_file_backing.diskMode = "persistent"
+ disk_file_backing.thinProvisioned = False
+ if file_path is not None:
+ disk_file_backing.fileName = file_path
+ else:
+ disk_file_backing.fileName = ""
+
+ connectable_spec = client_factory.create('ns0:VirtualDeviceConnectInfo')
+ connectable_spec.startConnected = True
+ connectable_spec.allowGuestControl = False
+ connectable_spec.connected = True
+
+ virtual_disk.backing = disk_file_backing
+ virtual_disk.connectable = connectable_spec
+
+ # The Server assigns a Key to the device. Here we pass a -ve random key.
+ # -ve because actual keys are +ve numbers and we don't
+ # want a clash with the key that server might associate with the device
+ virtual_disk.key = -100
+ virtual_disk.controllerKey = controller_key
+ virtual_disk.unitNumber = 0
+ virtual_disk.capacityInKB = disksize
+
+ virtual_device_config.device = virtual_disk
+
+ return virtual_device_config
+
+
+def get_dummy_vm_create_spec(client_factory, name, data_store_name):
+ """Builds the dummy VM create spec."""
+ config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
+
+ config_spec.name = name
+ config_spec.guestId = "otherGuest"
+
+ vm_file_info = client_factory.create('ns0:VirtualMachineFileInfo')
+ vm_file_info.vmPathName = "[" + data_store_name + "]"
+ config_spec.files = vm_file_info
+
+ tools_info = client_factory.create('ns0:ToolsConfigInfo')
+ tools_info.afterPowerOn = True
+ tools_info.afterResume = True
+ tools_info.beforeGuestStandby = True
+ tools_info.beforeGuestShutdown = True
+ tools_info.beforeGuestReboot = True
+
+ config_spec.tools = tools_info
+ config_spec.numCPUs = 1
+ config_spec.memoryMB = 4
+
+ controller_key = -101
+ controller_spec = create_controller_spec(client_factory, controller_key)
+ disk_spec = create_virtual_disk_spec(client_factory, 1024, controller_key)
+
+ device_config_spec = [controller_spec, disk_spec]
+
+ config_spec.deviceChange = device_config_spec
+ return config_spec
+
+
+def get_machine_id_change_spec(client_factory, machine_id_str):
+ """Builds the machine id change config spec."""
+ virtual_machine_config_spec = \
+ client_factory.create('ns0:VirtualMachineConfigSpec')
+
+ opt = client_factory.create('ns0:OptionValue')
+ opt.key = "machine.id"
+ opt.value = machine_id_str
+ virtual_machine_config_spec.extraConfig = [opt]
+ return virtual_machine_config_spec
+
+
+def get_add_vswitch_port_group_spec(client_factory, vswitch_name,
+ port_group_name, vlan_id):
+ """Builds the virtual switch port group add spec."""
+ vswitch_port_group_spec = client_factory.create('ns0:HostPortGroupSpec')
+ vswitch_port_group_spec.name = port_group_name
+ vswitch_port_group_spec.vswitchName = vswitch_name
+
+ # VLAN ID of 0 means that VLAN tagging is not to be done for the network.
+ vswitch_port_group_spec.vlanId = int(vlan_id)
+
+ policy = client_factory.create('ns0:HostNetworkPolicy')
+ nicteaming = client_factory.create('ns0:HostNicTeamingPolicy')
+ nicteaming.notifySwitches = True
+ policy.nicTeaming = nicteaming
+
+ vswitch_port_group_spec.policy = policy
+ return vswitch_port_group_spec
diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py
index 1a2d1dc19..780caa65b 100644
--- a/nova/virt/vmwareapi/vmops.py
+++ b/nova/virt/vmwareapi/vmops.py
@@ -1,824 +1,824 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-
-"""
-Class for VM tasks like spawn, snapshot, suspend, resume etc.
-"""
-
-import base64
-import os
-import time
-import urllib
-import urllib2
-import uuid
-
-from nova.compute import power_state
-from nova import exception
-from nova import flags
-from nova import log as logging
-from nova import utils
-from nova.virt.vmwareapi import vim_util
-from nova.virt.vmwareapi import vm_util
-from nova.virt.vmwareapi import vmware_images
-from nova.virt.vmwareapi import network_utils
-
-FLAGS = flags.FLAGS
-flags.DEFINE_string('vmware_vif_driver',
- 'nova.virt.vmwareapi.vif.VMWareVlanBridgeDriver',
- 'The VMWare VIF driver to configure the VIFs.')
-
-LOG = logging.getLogger("nova.virt.vmwareapi.vmops")
-
-VMWARE_POWER_STATES = {
- 'poweredOff': power_state.SHUTDOWN,
- 'poweredOn': power_state.RUNNING,
- 'suspended': power_state.PAUSED}
-
-
-class VMWareVMOps(object):
- """Management class for VM-related tasks."""
-
- def __init__(self, session):
- """Initializer."""
- self._session = session
- self._vif_driver = utils.import_object(FLAGS.vmware_vif_driver)
-
- def list_instances(self):
- """Lists the VM instances that are registered with the ESX host."""
- LOG.debug(_("Getting list of instances"))
- vms = self._session._call_method(vim_util, "get_objects",
- "VirtualMachine",
- ["name", "runtime.connectionState"])
- lst_vm_names = []
- for vm in vms:
- vm_name = None
- conn_state = None
- for prop in vm.propSet:
- if prop.name == "name":
- vm_name = prop.val
- elif prop.name == "runtime.connectionState":
- conn_state = prop.val
- # Ignoring the oprhaned or inaccessible VMs
- if conn_state not in ["orphaned", "inaccessible"]:
- lst_vm_names.append(vm_name)
- LOG.debug(_("Got total of %s instances") % str(len(lst_vm_names)))
- return lst_vm_names
-
- def spawn(self, context, instance, image_meta, network_info):
- """
- Creates a VM instance.
-
- Steps followed are:
- 1. Create a VM with no disk and the specifics in the instance object
- like RAM size.
- 2. Create a dummy vmdk of the size of the disk file that is to be
- uploaded. This is required just to create the metadata file.
- 3. Delete the -flat.vmdk file created in the above step and retain
- the metadata .vmdk file.
- 4. Upload the disk file.
- 5. Attach the disk to the VM by reconfiguring the same.
- 6. Power on the VM.
- """
- vm_ref = self._get_vm_ref_from_the_name(instance.name)
- if vm_ref:
- raise exception.InstanceExists(name=instance.name)
-
- client_factory = self._session._get_vim().client.factory
- service_content = self._session._get_vim().get_service_content()
-
- def _get_datastore_ref():
- """Get the datastore list and choose the first local storage."""
- data_stores = self._session._call_method(vim_util, "get_objects",
- "Datastore", ["summary.type", "summary.name"])
- for elem in data_stores:
- ds_name = None
- ds_type = None
- for prop in elem.propSet:
- if prop.name == "summary.type":
- ds_type = prop.val
- elif prop.name == "summary.name":
- ds_name = prop.val
- # Local storage identifier
- if ds_type == "VMFS":
- data_store_name = ds_name
- return data_store_name
-
- if data_store_name is None:
- msg = _("Couldn't get a local Datastore reference")
- LOG.exception(msg)
- raise exception.Error(msg)
-
- data_store_name = _get_datastore_ref()
-
- def _get_image_properties():
- """
- Get the Size of the flat vmdk file that is there on the storage
- repository.
- """
- image_size, image_properties = \
- vmware_images.get_vmdk_size_and_properties(context,
- instance.image_ref, instance)
- vmdk_file_size_in_kb = int(image_size) / 1024
- os_type = image_properties.get("vmware_ostype", "otherGuest")
- adapter_type = image_properties.get("vmware_adaptertype",
- "lsiLogic")
- return vmdk_file_size_in_kb, os_type, adapter_type
-
- vmdk_file_size_in_kb, os_type, adapter_type = _get_image_properties()
-
- def _get_vmfolder_and_res_pool_mors():
- """Get the Vm folder ref from the datacenter."""
- dc_objs = self._session._call_method(vim_util, "get_objects",
- "Datacenter", ["vmFolder"])
- # There is only one default datacenter in a standalone ESX host
- vm_folder_mor = dc_objs[0].propSet[0].val
-
- # Get the resource pool. Taking the first resource pool coming our
- # way. Assuming that is the default resource pool.
- res_pool_mor = self._session._call_method(vim_util, "get_objects",
- "ResourcePool")[0].obj
- return vm_folder_mor, res_pool_mor
-
- vm_folder_mor, res_pool_mor = _get_vmfolder_and_res_pool_mors()
-
- def _check_if_network_bridge_exists(network_name):
- network_ref = \
- network_utils.get_network_with_the_name(self._session,
- network_name)
- if network_ref is None:
- raise exception.NetworkNotFoundForBridge(bridge=network_name)
- return network_ref
-
- def _get_vif_infos():
- vif_infos = []
- for (network, mapping) in network_info:
- mac_address = mapping['mac']
- network_name = network['bridge']
- if mapping.get('should_create_vlan'):
- network_ref = self._vif_driver.ensure_vlan_bridge(
- self._session, network)
- else:
- network_ref = _check_if_network_bridge_exists(network_name)
- vif_infos.append({'network_name': network_name,
- 'mac_address': mac_address,
- 'network_ref': network_ref,
- })
- return vif_infos
-
- vif_infos = _get_vif_infos()
-
- # Get the create vm config spec
- config_spec = vm_util.get_vm_create_spec(
- client_factory, instance,
- data_store_name, vif_infos, os_type)
-
- def _execute_create_vm():
- """Create VM on ESX host."""
- LOG.debug(_("Creating VM with the name %s on the ESX host") %
- instance.name)
- # Create the VM on the ESX host
- vm_create_task = self._session._call_method(
- self._session._get_vim(),
- "CreateVM_Task", vm_folder_mor,
- config=config_spec, pool=res_pool_mor)
- self._session._wait_for_task(instance['uuid'], vm_create_task)
-
- LOG.debug(_("Created VM with the name %s on the ESX host") %
- instance.name)
-
- _execute_create_vm()
-
- # Set the machine.id parameter of the instance to inject
- # the NIC configuration inside the VM
- if FLAGS.flat_injected:
- self._set_machine_id(client_factory, instance, network_info)
-
- # Naming the VM files in correspondence with the VM instance name
- # The flat vmdk file name
- flat_uploaded_vmdk_name = "%s/%s-flat.vmdk" % (instance.name,
- instance.name)
- # The vmdk meta-data file
- uploaded_vmdk_name = "%s/%s.vmdk" % (instance.name, instance.name)
- flat_uploaded_vmdk_path = vm_util.build_datastore_path(data_store_name,
- flat_uploaded_vmdk_name)
- uploaded_vmdk_path = vm_util.build_datastore_path(data_store_name,
- uploaded_vmdk_name)
-
- def _create_virtual_disk():
- """Create a virtual disk of the size of flat vmdk file."""
- # Create a Virtual Disk of the size of the flat vmdk file. This is
- # done just to generate the meta-data file whose specifics
- # depend on the size of the disk, thin/thick provisioning and the
- # storage adapter type.
- # Here we assume thick provisioning and lsiLogic for the adapter
- # type
- LOG.debug(_("Creating Virtual Disk of size "
- "%(vmdk_file_size_in_kb)s KB and adapter type "
- "%(adapter_type)s on the ESX host local store"
- " %(data_store_name)s") %
- {"vmdk_file_size_in_kb": vmdk_file_size_in_kb,
- "adapter_type": adapter_type,
- "data_store_name": data_store_name})
- vmdk_create_spec = vm_util.get_vmdk_create_spec(client_factory,
- vmdk_file_size_in_kb, adapter_type)
- vmdk_create_task = self._session._call_method(
- self._session._get_vim(),
- "CreateVirtualDisk_Task",
- service_content.virtualDiskManager,
- name=uploaded_vmdk_path,
- datacenter=self._get_datacenter_name_and_ref()[0],
- spec=vmdk_create_spec)
- self._session._wait_for_task(instance['uuid'], vmdk_create_task)
- LOG.debug(_("Created Virtual Disk of size %(vmdk_file_size_in_kb)s"
- " KB on the ESX host local store "
- "%(data_store_name)s") %
- {"vmdk_file_size_in_kb": vmdk_file_size_in_kb,
- "data_store_name": data_store_name})
-
- _create_virtual_disk()
-
- def _delete_disk_file():
- LOG.debug(_("Deleting the file %(flat_uploaded_vmdk_path)s "
- "on the ESX host local"
- "store %(data_store_name)s") %
- {"flat_uploaded_vmdk_path": flat_uploaded_vmdk_path,
- "data_store_name": data_store_name})
- # Delete the -flat.vmdk file created. .vmdk file is retained.
- vmdk_delete_task = self._session._call_method(
- self._session._get_vim(),
- "DeleteDatastoreFile_Task",
- service_content.fileManager,
- name=flat_uploaded_vmdk_path)
- self._session._wait_for_task(instance['uuid'], vmdk_delete_task)
- LOG.debug(_("Deleted the file %(flat_uploaded_vmdk_path)s on the "
- "ESX host local store %(data_store_name)s") %
- {"flat_uploaded_vmdk_path": flat_uploaded_vmdk_path,
- "data_store_name": data_store_name})
-
- _delete_disk_file()
-
- cookies = self._session._get_vim().client.options.transport.cookiejar
-
- def _fetch_image_on_esx_datastore():
- """Fetch image from Glance to ESX datastore."""
- LOG.debug(_("Downloading image file data %(image_ref)s to the ESX "
- "data store %(data_store_name)s") %
- ({'image_ref': instance.image_ref,
- 'data_store_name': data_store_name}))
- # Upload the -flat.vmdk file whose meta-data file we just created
- # above
- vmware_images.fetch_image(
- context,
- instance.image_ref,
- instance,
- host=self._session._host_ip,
- data_center_name=self._get_datacenter_name_and_ref()[1],
- datastore_name=data_store_name,
- cookies=cookies,
- file_path=flat_uploaded_vmdk_name)
- LOG.debug(_("Downloaded image file data %(image_ref)s to the ESX "
- "data store %(data_store_name)s") %
- ({'image_ref': instance.image_ref,
- 'data_store_name': data_store_name}))
- _fetch_image_on_esx_datastore()
-
- vm_ref = self._get_vm_ref_from_the_name(instance.name)
-
- def _attach_vmdk_to_the_vm():
- """
- Attach the vmdk uploaded to the VM. VM reconfigure is done
- to do so.
- """
- vmdk_attach_config_spec = vm_util.get_vmdk_attach_config_spec(
- client_factory,
- vmdk_file_size_in_kb, uploaded_vmdk_path,
- adapter_type)
- LOG.debug(_("Reconfiguring VM instance %s to attach the image "
- "disk") % instance.name)
- reconfig_task = self._session._call_method(
- self._session._get_vim(),
- "ReconfigVM_Task", vm_ref,
- spec=vmdk_attach_config_spec)
- self._session._wait_for_task(instance['uuid'], reconfig_task)
- LOG.debug(_("Reconfigured VM instance %s to attach the image "
- "disk") % instance.name)
-
- _attach_vmdk_to_the_vm()
-
- def _power_on_vm():
- """Power on the VM."""
- LOG.debug(_("Powering on the VM instance %s") % instance.name)
- # Power On the VM
- power_on_task = self._session._call_method(
- self._session._get_vim(),
- "PowerOnVM_Task", vm_ref)
- self._session._wait_for_task(instance['uuid'], power_on_task)
- LOG.debug(_("Powered on the VM instance %s") % instance.name)
- _power_on_vm()
-
- def snapshot(self, context, instance, snapshot_name):
- """
- Create snapshot from a running VM instance.
- Steps followed are:
- 1. Get the name of the vmdk file which the VM points to right now.
- Can be a chain of snapshots, so we need to know the last in the
- chain.
- 2. Create the snapshot. A new vmdk is created which the VM points to
- now. The earlier vmdk becomes read-only.
- 3. Call CopyVirtualDisk which coalesces the disk chain to form a single
- vmdk, rather a .vmdk metadata file and a -flat.vmdk disk data file.
- 4. Now upload the -flat.vmdk file to the image store.
- 5. Delete the coalesced .vmdk and -flat.vmdk created.
- """
- vm_ref = self._get_vm_ref_from_the_name(instance.name)
- if vm_ref is None:
- raise exception.InstanceNotFound(instance_id=instance.id)
-
- client_factory = self._session._get_vim().client.factory
- service_content = self._session._get_vim().get_service_content()
-
- def _get_vm_and_vmdk_attribs():
- # Get the vmdk file name that the VM is pointing to
- hardware_devices = self._session._call_method(vim_util,
- "get_dynamic_property", vm_ref,
- "VirtualMachine", "config.hardware.device")
- vmdk_file_path_before_snapshot, adapter_type = \
- vm_util.get_vmdk_file_path_and_adapter_type(client_factory,
- hardware_devices)
- datastore_name = vm_util.split_datastore_path(
- vmdk_file_path_before_snapshot)[0]
- os_type = self._session._call_method(vim_util,
- "get_dynamic_property", vm_ref,
- "VirtualMachine", "summary.config.guestId")
- return (vmdk_file_path_before_snapshot, adapter_type,
- datastore_name, os_type)
-
- vmdk_file_path_before_snapshot, adapter_type, datastore_name,\
- os_type = _get_vm_and_vmdk_attribs()
-
- def _create_vm_snapshot():
- # Create a snapshot of the VM
- LOG.debug(_("Creating Snapshot of the VM instance %s ") %
- instance.name)
- snapshot_task = self._session._call_method(
- self._session._get_vim(),
- "CreateSnapshot_Task", vm_ref,
- name="%s-snapshot" % instance.name,
- description="Taking Snapshot of the VM",
- memory=True,
- quiesce=True)
- self._session._wait_for_task(instance['uuid'], snapshot_task)
- LOG.debug(_("Created Snapshot of the VM instance %s ") %
- instance.name)
-
- _create_vm_snapshot()
-
- def _check_if_tmp_folder_exists():
- # Copy the contents of the VM that were there just before the
- # snapshot was taken
- ds_ref_ret = vim_util.get_dynamic_property(
- self._session._get_vim(),
- vm_ref,
- "VirtualMachine",
- "datastore")
- if not ds_ref_ret:
- raise exception.DatastoreNotFound()
- ds_ref = ds_ref_ret.ManagedObjectReference[0]
- ds_browser = vim_util.get_dynamic_property(
- self._session._get_vim(),
- ds_ref,
- "Datastore",
- "browser")
- # Check if the vmware-tmp folder exists or not. If not, create one
- tmp_folder_path = vm_util.build_datastore_path(datastore_name,
- "vmware-tmp")
- if not self._path_exists(ds_browser, tmp_folder_path):
- self._mkdir(vm_util.build_datastore_path(datastore_name,
- "vmware-tmp"))
-
- _check_if_tmp_folder_exists()
-
- # Generate a random vmdk file name to which the coalesced vmdk content
- # will be copied to. A random name is chosen so that we don't have
- # name clashes.
- random_name = str(uuid.uuid4())
- dest_vmdk_file_location = vm_util.build_datastore_path(datastore_name,
- "vmware-tmp/%s.vmdk" % random_name)
- dc_ref = self._get_datacenter_name_and_ref()[0]
-
- def _copy_vmdk_content():
- # Copy the contents of the disk ( or disks, if there were snapshots
- # done earlier) to a temporary vmdk file.
- copy_spec = vm_util.get_copy_virtual_disk_spec(client_factory,
- adapter_type)
- LOG.debug(_("Copying disk data before snapshot of the VM "
- " instance %s") % instance.name)
- copy_disk_task = self._session._call_method(
- self._session._get_vim(),
- "CopyVirtualDisk_Task",
- service_content.virtualDiskManager,
- sourceName=vmdk_file_path_before_snapshot,
- sourceDatacenter=dc_ref,
- destName=dest_vmdk_file_location,
- destDatacenter=dc_ref,
- destSpec=copy_spec,
- force=False)
- self._session._wait_for_task(instance['uuid'], copy_disk_task)
- LOG.debug(_("Copied disk data before snapshot of the VM "
- "instance %s") % instance.name)
-
- _copy_vmdk_content()
-
- cookies = self._session._get_vim().client.options.transport.cookiejar
-
- def _upload_vmdk_to_image_repository():
- # Upload the contents of -flat.vmdk file which has the disk data.
- LOG.debug(_("Uploading image %s") % snapshot_name)
- vmware_images.upload_image(
- context,
- snapshot_name,
- instance,
- os_type=os_type,
- adapter_type=adapter_type,
- image_version=1,
- host=self._session._host_ip,
- data_center_name=self._get_datacenter_name_and_ref()[1],
- datastore_name=datastore_name,
- cookies=cookies,
- file_path="vmware-tmp/%s-flat.vmdk" % random_name)
- LOG.debug(_("Uploaded image %s") % snapshot_name)
-
- _upload_vmdk_to_image_repository()
-
- def _clean_temp_data():
- """
- Delete temporary vmdk files generated in image handling
- operations.
- """
- # Delete the temporary vmdk created above.
- LOG.debug(_("Deleting temporary vmdk file %s")
- % dest_vmdk_file_location)
- remove_disk_task = self._session._call_method(
- self._session._get_vim(),
- "DeleteVirtualDisk_Task",
- service_content.virtualDiskManager,
- name=dest_vmdk_file_location,
- datacenter=dc_ref)
- self._session._wait_for_task(instance['uuid'], remove_disk_task)
- LOG.debug(_("Deleted temporary vmdk file %s")
- % dest_vmdk_file_location)
-
- _clean_temp_data()
-
- def reboot(self, instance, network_info):
- """Reboot a VM instance."""
- vm_ref = self._get_vm_ref_from_the_name(instance.name)
- if vm_ref is None:
- raise exception.InstanceNotFound(instance_id=instance.id)
-
- self.plug_vifs(instance, network_info)
-
- lst_properties = ["summary.guest.toolsStatus", "runtime.powerState",
- "summary.guest.toolsRunningStatus"]
- props = self._session._call_method(vim_util, "get_object_properties",
- None, vm_ref, "VirtualMachine",
- lst_properties)
- pwr_state = None
- tools_status = None
- tools_running_status = False
- for elem in props:
- for prop in elem.propSet:
- if prop.name == "runtime.powerState":
- pwr_state = prop.val
- elif prop.name == "summary.guest.toolsStatus":
- tools_status = prop.val
- elif prop.name == "summary.guest.toolsRunningStatus":
- tools_running_status = prop.val
-
- # Raise an exception if the VM is not powered On.
- if pwr_state not in ["poweredOn"]:
- reason = _("instance is not powered on")
- raise exception.InstanceRebootFailure(reason=reason)
-
- # If latest vmware tools are installed in the VM, and that the tools
- # are running, then only do a guest reboot. Otherwise do a hard reset.
- if (tools_status == "toolsOk" and
- tools_running_status == "guestToolsRunning"):
- LOG.debug(_("Rebooting guest OS of VM %s") % instance.name)
- self._session._call_method(self._session._get_vim(), "RebootGuest",
- vm_ref)
- LOG.debug(_("Rebooted guest OS of VM %s") % instance.name)
- else:
- LOG.debug(_("Doing hard reboot of VM %s") % instance.name)
- reset_task = self._session._call_method(self._session._get_vim(),
- "ResetVM_Task", vm_ref)
- self._session._wait_for_task(instance['uuid'], reset_task)
- LOG.debug(_("Did hard reboot of VM %s") % instance.name)
-
- def destroy(self, instance, network_info):
- """
- Destroy a VM instance. Steps followed are:
- 1. Power off the VM, if it is in poweredOn state.
- 2. Un-register a VM.
- 3. Delete the contents of the folder holding the VM related data.
- """
- try:
- vm_ref = self._get_vm_ref_from_the_name(instance.name)
- if vm_ref is None:
- LOG.debug(_("instance - %s not present") % instance.name)
- return
- lst_properties = ["config.files.vmPathName", "runtime.powerState"]
- props = self._session._call_method(vim_util,
- "get_object_properties",
- None, vm_ref, "VirtualMachine", lst_properties)
- pwr_state = None
- for elem in props:
- vm_config_pathname = None
- for prop in elem.propSet:
- if prop.name == "runtime.powerState":
- pwr_state = prop.val
- elif prop.name == "config.files.vmPathName":
- vm_config_pathname = prop.val
- if vm_config_pathname:
- datastore_name, vmx_file_path = \
- vm_util.split_datastore_path(vm_config_pathname)
- # Power off the VM if it is in PoweredOn state.
- if pwr_state == "poweredOn":
- LOG.debug(_("Powering off the VM %s") % instance.name)
- poweroff_task = self._session._call_method(
- self._session._get_vim(),
- "PowerOffVM_Task", vm_ref)
- self._session._wait_for_task(instance['uuid'], poweroff_task)
- LOG.debug(_("Powered off the VM %s") % instance.name)
-
- # Un-register the VM
- try:
- LOG.debug(_("Unregistering the VM %s") % instance.name)
- self._session._call_method(self._session._get_vim(),
- "UnregisterVM", vm_ref)
- LOG.debug(_("Unregistered the VM %s") % instance.name)
- except Exception, excep:
- LOG.warn(_("In vmwareapi:vmops:destroy, got this exception"
- " while un-registering the VM: %s") % str(excep))
-
- self._unplug_vifs(instance, network_info)
-
- # Delete the folder holding the VM related content on
- # the datastore.
- try:
- dir_ds_compliant_path = vm_util.build_datastore_path(
- datastore_name,
- os.path.dirname(vmx_file_path))
- LOG.debug(_("Deleting contents of the VM %(name)s from "
- "datastore %(datastore_name)s") %
- ({'name': instance.name,
- 'datastore_name': datastore_name}))
- delete_task = self._session._call_method(
- self._session._get_vim(),
- "DeleteDatastoreFile_Task",
- self._session._get_vim().get_service_content().fileManager,
- name=dir_ds_compliant_path)
- self._session._wait_for_task(instance['uuid'], delete_task)
- LOG.debug(_("Deleted contents of the VM %(name)s from "
- "datastore %(datastore_name)s") %
- ({'name': instance.name,
- 'datastore_name': datastore_name}))
- except Exception, excep:
- LOG.warn(_("In vmwareapi:vmops:destroy, "
- "got this exception while deleting"
- " the VM contents from the disk: %s")
- % str(excep))
- except Exception, exc:
- LOG.exception(exc)
-
- def pause(self, instance):
- """Pause a VM instance."""
- raise exception.ApiError("pause not supported for vmwareapi")
-
- def unpause(self, instance):
- """Un-Pause a VM instance."""
- raise exception.ApiError("unpause not supported for vmwareapi")
-
- def suspend(self, instance):
- """Suspend the specified instance."""
- vm_ref = self._get_vm_ref_from_the_name(instance.name)
- if vm_ref is None:
- raise exception.InstanceNotFound(instance_id=instance.id)
-
- pwr_state = self._session._call_method(vim_util,
- "get_dynamic_property", vm_ref,
- "VirtualMachine", "runtime.powerState")
- # Only PoweredOn VMs can be suspended.
- if pwr_state == "poweredOn":
- LOG.debug(_("Suspending the VM %s ") % instance.name)
- suspend_task = self._session._call_method(self._session._get_vim(),
- "SuspendVM_Task", vm_ref)
- self._session._wait_for_task(instance['uuid'], suspend_task)
- LOG.debug(_("Suspended the VM %s ") % instance.name)
- # Raise Exception if VM is poweredOff
- elif pwr_state == "poweredOff":
- reason = _("instance is powered off and can not be suspended.")
- raise exception.InstanceSuspendFailure(reason=reason)
-
- LOG.debug(_("VM %s was already in suspended state. So returning "
- "without doing anything") % instance.name)
-
- def resume(self, instance):
- """Resume the specified instance."""
- vm_ref = self._get_vm_ref_from_the_name(instance.name)
- if vm_ref is None:
- raise exception.InstanceNotFound(instance_id=instance.id)
-
- pwr_state = self._session._call_method(vim_util,
- "get_dynamic_property", vm_ref,
- "VirtualMachine", "runtime.powerState")
- if pwr_state.lower() == "suspended":
- LOG.debug(_("Resuming the VM %s") % instance.name)
- suspend_task = self._session._call_method(
- self._session._get_vim(),
- "PowerOnVM_Task", vm_ref)
- self._session._wait_for_task(instance['uuid'], suspend_task)
- LOG.debug(_("Resumed the VM %s ") % instance.name)
- else:
- reason = _("instance is not in a suspended state")
- raise exception.InstanceResumeFailure(reason=reason)
-
- def get_info(self, instance_name):
- """Return data about the VM instance."""
- vm_ref = self._get_vm_ref_from_the_name(instance_name)
- if vm_ref is None:
- raise exception.InstanceNotFound(instance_id=instance_name)
-
- lst_properties = ["summary.config.numCpu",
- "summary.config.memorySizeMB",
- "runtime.powerState"]
- vm_props = self._session._call_method(vim_util,
- "get_object_properties", None, vm_ref, "VirtualMachine",
- lst_properties)
- max_mem = None
- pwr_state = None
- num_cpu = None
- for elem in vm_props:
- for prop in elem.propSet:
- if prop.name == "summary.config.numCpu":
- num_cpu = int(prop.val)
- elif prop.name == "summary.config.memorySizeMB":
- # In MB, but we want in KB
- max_mem = int(prop.val) * 1024
- elif prop.name == "runtime.powerState":
- pwr_state = VMWARE_POWER_STATES[prop.val]
-
- return {'state': pwr_state,
- 'max_mem': max_mem,
- 'mem': max_mem,
- 'num_cpu': num_cpu,
- 'cpu_time': 0}
-
- def get_diagnostics(self, instance):
- """Return data about VM diagnostics."""
- raise exception.ApiError("get_diagnostics not implemented for "
- "vmwareapi")
-
- def get_console_output(self, instance):
- """Return snapshot of console."""
- vm_ref = self._get_vm_ref_from_the_name(instance.name)
- if vm_ref is None:
- raise exception.InstanceNotFound(instance_id=instance.id)
- param_list = {"id": str(vm_ref)}
- base_url = "%s://%s/screen?%s" % (self._session._scheme,
- self._session._host_ip,
- urllib.urlencode(param_list))
- request = urllib2.Request(base_url)
- base64string = base64.encodestring(
- '%s:%s' % (
- self._session._host_username,
- self._session._host_password)).replace('\n', '')
- request.add_header("Authorization", "Basic %s" % base64string)
- result = urllib2.urlopen(request)
- if result.code == 200:
- return result.read()
- else:
- return ""
-
- def get_ajax_console(self, instance):
- """Return link to instance's ajax console."""
- return 'http://fakeajaxconsole/fake_url'
-
- def _set_machine_id(self, client_factory, instance, network_info):
- """
- Set the machine id of the VM for guest tools to pick up and reconfigure
- the network interfaces.
- """
- vm_ref = self._get_vm_ref_from_the_name(instance.name)
- if vm_ref is None:
- raise exception.InstanceNotFound(instance_id=instance.id)
-
- machine_id_str = ''
- for (network, info) in network_info:
- # TODO(vish): add support for dns2
- # TODO(sateesh): add support for injection of ipv6 configuration
- ip_v4 = ip_v6 = None
- if 'ips' in info and len(info['ips']) > 0:
- ip_v4 = info['ips'][0]
- if 'ip6s' in info and len(info['ip6s']) > 0:
- ip_v6 = info['ip6s'][0]
- if len(info['dns']) > 0:
- dns = info['dns'][0]
- else:
- dns = ''
-
- interface_str = "%s;%s;%s;%s;%s;%s" % \
- (info['mac'],
- ip_v4 and ip_v4['ip'] or '',
- ip_v4 and ip_v4['netmask'] or '',
- info['gateway'],
- info['broadcast'],
- dns)
- machine_id_str = machine_id_str + interface_str + '#'
-
- machine_id_change_spec = \
- vm_util.get_machine_id_change_spec(client_factory, machine_id_str)
-
- LOG.debug(_("Reconfiguring VM instance %(name)s to set the machine id "
- "with ip - %(ip_addr)s") %
- ({'name': instance.name,
- 'ip_addr': ip_v4['ip']}))
- reconfig_task = self._session._call_method(self._session._get_vim(),
- "ReconfigVM_Task", vm_ref,
- spec=machine_id_change_spec)
- self._session._wait_for_task(instance['uuid'], reconfig_task)
- LOG.debug(_("Reconfigured VM instance %(name)s to set the machine id "
- "with ip - %(ip_addr)s") %
- ({'name': instance.name,
- 'ip_addr': ip_v4['ip']}))
-
- def _get_datacenter_name_and_ref(self):
- """Get the datacenter name and the reference."""
- dc_obj = self._session._call_method(vim_util, "get_objects",
- "Datacenter", ["name"])
- return dc_obj[0].obj, dc_obj[0].propSet[0].val
-
- def _path_exists(self, ds_browser, ds_path):
- """Check if the path exists on the datastore."""
- search_task = self._session._call_method(self._session._get_vim(),
- "SearchDatastore_Task",
- ds_browser,
- datastorePath=ds_path)
- # Wait till the state changes from queued or running.
- # If an error state is returned, it means that the path doesn't exist.
- while True:
- task_info = self._session._call_method(vim_util,
- "get_dynamic_property",
- search_task, "Task", "info")
- if task_info.state in ['queued', 'running']:
- time.sleep(2)
- continue
- break
- if task_info.state == "error":
- return False
- return True
-
- def _mkdir(self, ds_path):
- """
- Creates a directory at the path specified. If it is just "NAME",
- then a directory with this name is created at the topmost level of the
- DataStore.
- """
- LOG.debug(_("Creating directory with path %s") % ds_path)
- self._session._call_method(self._session._get_vim(), "MakeDirectory",
- self._session._get_vim().get_service_content().fileManager,
- name=ds_path, createParentDirectories=False)
- LOG.debug(_("Created directory with path %s") % ds_path)
-
- def _get_vm_ref_from_the_name(self, vm_name):
- """Get reference to the VM with the name specified."""
- vms = self._session._call_method(vim_util, "get_objects",
- "VirtualMachine", ["name"])
- for vm in vms:
- if vm.propSet[0].val == vm_name:
- return vm.obj
- return None
-
- def plug_vifs(self, instance, network_info):
- """Plug VIFs into networks."""
- for (network, mapping) in network_info:
- self._vif_driver.plug(instance, network, mapping)
-
- def _unplug_vifs(self, instance, network_info):
- """Unplug VIFs from networks."""
- for (network, mapping) in network_info:
- self._vif_driver.unplug(instance, network, mapping)
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+
+"""
+Class for VM tasks like spawn, snapshot, suspend, resume etc.
+"""
+
+import base64
+import os
+import time
+import urllib
+import urllib2
+import uuid
+
+from nova.compute import power_state
+from nova import exception
+from nova import flags
+from nova import log as logging
+from nova import utils
+from nova.virt.vmwareapi import vim_util
+from nova.virt.vmwareapi import vm_util
+from nova.virt.vmwareapi import vmware_images
+from nova.virt.vmwareapi import network_utils
+
+FLAGS = flags.FLAGS
+flags.DEFINE_string('vmware_vif_driver',
+ 'nova.virt.vmwareapi.vif.VMWareVlanBridgeDriver',
+ 'The VMWare VIF driver to configure the VIFs.')
+
+LOG = logging.getLogger("nova.virt.vmwareapi.vmops")
+
+VMWARE_POWER_STATES = {
+ 'poweredOff': power_state.SHUTDOWN,
+ 'poweredOn': power_state.RUNNING,
+ 'suspended': power_state.PAUSED}
+
+
+class VMWareVMOps(object):
+ """Management class for VM-related tasks."""
+
+ def __init__(self, session):
+ """Initializer."""
+ self._session = session
+ self._vif_driver = utils.import_object(FLAGS.vmware_vif_driver)
+
+ def list_instances(self):
+ """Lists the VM instances that are registered with the ESX host."""
+ LOG.debug(_("Getting list of instances"))
+ vms = self._session._call_method(vim_util, "get_objects",
+ "VirtualMachine",
+ ["name", "runtime.connectionState"])
+ lst_vm_names = []
+ for vm in vms:
+ vm_name = None
+ conn_state = None
+ for prop in vm.propSet:
+ if prop.name == "name":
+ vm_name = prop.val
+ elif prop.name == "runtime.connectionState":
+ conn_state = prop.val
+ # Ignoring the oprhaned or inaccessible VMs
+ if conn_state not in ["orphaned", "inaccessible"]:
+ lst_vm_names.append(vm_name)
+ LOG.debug(_("Got total of %s instances") % str(len(lst_vm_names)))
+ return lst_vm_names
+
+ def spawn(self, context, instance, image_meta, network_info):
+ """
+ Creates a VM instance.
+
+ Steps followed are:
+ 1. Create a VM with no disk and the specifics in the instance object
+ like RAM size.
+ 2. Create a dummy vmdk of the size of the disk file that is to be
+ uploaded. This is required just to create the metadata file.
+ 3. Delete the -flat.vmdk file created in the above step and retain
+ the metadata .vmdk file.
+ 4. Upload the disk file.
+ 5. Attach the disk to the VM by reconfiguring the same.
+ 6. Power on the VM.
+ """
+ vm_ref = self._get_vm_ref_from_the_name(instance.name)
+ if vm_ref:
+ raise exception.InstanceExists(name=instance.name)
+
+ client_factory = self._session._get_vim().client.factory
+ service_content = self._session._get_vim().get_service_content()
+
+ def _get_datastore_ref():
+ """Get the datastore list and choose the first local storage."""
+ data_stores = self._session._call_method(vim_util, "get_objects",
+ "Datastore", ["summary.type", "summary.name"])
+ for elem in data_stores:
+ ds_name = None
+ ds_type = None
+ for prop in elem.propSet:
+ if prop.name == "summary.type":
+ ds_type = prop.val
+ elif prop.name == "summary.name":
+ ds_name = prop.val
+ # Local storage identifier
+ if ds_type == "VMFS":
+ data_store_name = ds_name
+ return data_store_name
+
+ if data_store_name is None:
+ msg = _("Couldn't get a local Datastore reference")
+ LOG.exception(msg)
+ raise exception.Error(msg)
+
+ data_store_name = _get_datastore_ref()
+
+ def _get_image_properties():
+ """
+ Get the Size of the flat vmdk file that is there on the storage
+ repository.
+ """
+ image_size, image_properties = \
+ vmware_images.get_vmdk_size_and_properties(context,
+ instance.image_ref, instance)
+ vmdk_file_size_in_kb = int(image_size) / 1024
+ os_type = image_properties.get("vmware_ostype", "otherGuest")
+ adapter_type = image_properties.get("vmware_adaptertype",
+ "lsiLogic")
+ return vmdk_file_size_in_kb, os_type, adapter_type
+
+ vmdk_file_size_in_kb, os_type, adapter_type = _get_image_properties()
+
+ def _get_vmfolder_and_res_pool_mors():
+ """Get the Vm folder ref from the datacenter."""
+ dc_objs = self._session._call_method(vim_util, "get_objects",
+ "Datacenter", ["vmFolder"])
+ # There is only one default datacenter in a standalone ESX host
+ vm_folder_mor = dc_objs[0].propSet[0].val
+
+ # Get the resource pool. Taking the first resource pool coming our
+ # way. Assuming that is the default resource pool.
+ res_pool_mor = self._session._call_method(vim_util, "get_objects",
+ "ResourcePool")[0].obj
+ return vm_folder_mor, res_pool_mor
+
+ vm_folder_mor, res_pool_mor = _get_vmfolder_and_res_pool_mors()
+
+ def _check_if_network_bridge_exists(network_name):
+ network_ref = \
+ network_utils.get_network_with_the_name(self._session,
+ network_name)
+ if network_ref is None:
+ raise exception.NetworkNotFoundForBridge(bridge=network_name)
+ return network_ref
+
+ def _get_vif_infos():
+ vif_infos = []
+ for (network, mapping) in network_info:
+ mac_address = mapping['mac']
+ network_name = network['bridge']
+ if mapping.get('should_create_vlan'):
+ network_ref = self._vif_driver.ensure_vlan_bridge(
+ self._session, network)
+ else:
+ network_ref = _check_if_network_bridge_exists(network_name)
+ vif_infos.append({'network_name': network_name,
+ 'mac_address': mac_address,
+ 'network_ref': network_ref,
+ })
+ return vif_infos
+
+ vif_infos = _get_vif_infos()
+
+ # Get the create vm config spec
+ config_spec = vm_util.get_vm_create_spec(
+ client_factory, instance,
+ data_store_name, vif_infos, os_type)
+
+ def _execute_create_vm():
+ """Create VM on ESX host."""
+ LOG.debug(_("Creating VM with the name %s on the ESX host") %
+ instance.name)
+ # Create the VM on the ESX host
+ vm_create_task = self._session._call_method(
+ self._session._get_vim(),
+ "CreateVM_Task", vm_folder_mor,
+ config=config_spec, pool=res_pool_mor)
+ self._session._wait_for_task(instance['uuid'], vm_create_task)
+
+ LOG.debug(_("Created VM with the name %s on the ESX host") %
+ instance.name)
+
+ _execute_create_vm()
+
+ # Set the machine.id parameter of the instance to inject
+ # the NIC configuration inside the VM
+ if FLAGS.flat_injected:
+ self._set_machine_id(client_factory, instance, network_info)
+
+ # Naming the VM files in correspondence with the VM instance name
+ # The flat vmdk file name
+ flat_uploaded_vmdk_name = "%s/%s-flat.vmdk" % (instance.name,
+ instance.name)
+ # The vmdk meta-data file
+ uploaded_vmdk_name = "%s/%s.vmdk" % (instance.name, instance.name)
+ flat_uploaded_vmdk_path = vm_util.build_datastore_path(data_store_name,
+ flat_uploaded_vmdk_name)
+ uploaded_vmdk_path = vm_util.build_datastore_path(data_store_name,
+ uploaded_vmdk_name)
+
+ def _create_virtual_disk():
+ """Create a virtual disk of the size of flat vmdk file."""
+ # Create a Virtual Disk of the size of the flat vmdk file. This is
+ # done just to generate the meta-data file whose specifics
+ # depend on the size of the disk, thin/thick provisioning and the
+ # storage adapter type.
+ # Here we assume thick provisioning and lsiLogic for the adapter
+ # type
+ LOG.debug(_("Creating Virtual Disk of size "
+ "%(vmdk_file_size_in_kb)s KB and adapter type "
+ "%(adapter_type)s on the ESX host local store"
+ " %(data_store_name)s") %
+ {"vmdk_file_size_in_kb": vmdk_file_size_in_kb,
+ "adapter_type": adapter_type,
+ "data_store_name": data_store_name})
+ vmdk_create_spec = vm_util.get_vmdk_create_spec(client_factory,
+ vmdk_file_size_in_kb, adapter_type)
+ vmdk_create_task = self._session._call_method(
+ self._session._get_vim(),
+ "CreateVirtualDisk_Task",
+ service_content.virtualDiskManager,
+ name=uploaded_vmdk_path,
+ datacenter=self._get_datacenter_name_and_ref()[0],
+ spec=vmdk_create_spec)
+ self._session._wait_for_task(instance['uuid'], vmdk_create_task)
+ LOG.debug(_("Created Virtual Disk of size %(vmdk_file_size_in_kb)s"
+ " KB on the ESX host local store "
+ "%(data_store_name)s") %
+ {"vmdk_file_size_in_kb": vmdk_file_size_in_kb,
+ "data_store_name": data_store_name})
+
+ _create_virtual_disk()
+
+ def _delete_disk_file():
+ LOG.debug(_("Deleting the file %(flat_uploaded_vmdk_path)s "
+ "on the ESX host local"
+ "store %(data_store_name)s") %
+ {"flat_uploaded_vmdk_path": flat_uploaded_vmdk_path,
+ "data_store_name": data_store_name})
+ # Delete the -flat.vmdk file created. .vmdk file is retained.
+ vmdk_delete_task = self._session._call_method(
+ self._session._get_vim(),
+ "DeleteDatastoreFile_Task",
+ service_content.fileManager,
+ name=flat_uploaded_vmdk_path)
+ self._session._wait_for_task(instance['uuid'], vmdk_delete_task)
+ LOG.debug(_("Deleted the file %(flat_uploaded_vmdk_path)s on the "
+ "ESX host local store %(data_store_name)s") %
+ {"flat_uploaded_vmdk_path": flat_uploaded_vmdk_path,
+ "data_store_name": data_store_name})
+
+ _delete_disk_file()
+
+ cookies = self._session._get_vim().client.options.transport.cookiejar
+
+ def _fetch_image_on_esx_datastore():
+ """Fetch image from Glance to ESX datastore."""
+ LOG.debug(_("Downloading image file data %(image_ref)s to the ESX "
+ "data store %(data_store_name)s") %
+ ({'image_ref': instance.image_ref,
+ 'data_store_name': data_store_name}))
+ # Upload the -flat.vmdk file whose meta-data file we just created
+ # above
+ vmware_images.fetch_image(
+ context,
+ instance.image_ref,
+ instance,
+ host=self._session._host_ip,
+ data_center_name=self._get_datacenter_name_and_ref()[1],
+ datastore_name=data_store_name,
+ cookies=cookies,
+ file_path=flat_uploaded_vmdk_name)
+ LOG.debug(_("Downloaded image file data %(image_ref)s to the ESX "
+ "data store %(data_store_name)s") %
+ ({'image_ref': instance.image_ref,
+ 'data_store_name': data_store_name}))
+ _fetch_image_on_esx_datastore()
+
+ vm_ref = self._get_vm_ref_from_the_name(instance.name)
+
+ def _attach_vmdk_to_the_vm():
+ """
+ Attach the vmdk uploaded to the VM. VM reconfigure is done
+ to do so.
+ """
+ vmdk_attach_config_spec = vm_util.get_vmdk_attach_config_spec(
+ client_factory,
+ vmdk_file_size_in_kb, uploaded_vmdk_path,
+ adapter_type)
+ LOG.debug(_("Reconfiguring VM instance %s to attach the image "
+ "disk") % instance.name)
+ reconfig_task = self._session._call_method(
+ self._session._get_vim(),
+ "ReconfigVM_Task", vm_ref,
+ spec=vmdk_attach_config_spec)
+ self._session._wait_for_task(instance['uuid'], reconfig_task)
+ LOG.debug(_("Reconfigured VM instance %s to attach the image "
+ "disk") % instance.name)
+
+ _attach_vmdk_to_the_vm()
+
+ def _power_on_vm():
+ """Power on the VM."""
+ LOG.debug(_("Powering on the VM instance %s") % instance.name)
+ # Power On the VM
+ power_on_task = self._session._call_method(
+ self._session._get_vim(),
+ "PowerOnVM_Task", vm_ref)
+ self._session._wait_for_task(instance['uuid'], power_on_task)
+ LOG.debug(_("Powered on the VM instance %s") % instance.name)
+ _power_on_vm()
+
+ def snapshot(self, context, instance, snapshot_name):
+ """
+ Create snapshot from a running VM instance.
+ Steps followed are:
+ 1. Get the name of the vmdk file which the VM points to right now.
+ Can be a chain of snapshots, so we need to know the last in the
+ chain.
+ 2. Create the snapshot. A new vmdk is created which the VM points to
+ now. The earlier vmdk becomes read-only.
+ 3. Call CopyVirtualDisk which coalesces the disk chain to form a single
+ vmdk, rather a .vmdk metadata file and a -flat.vmdk disk data file.
+ 4. Now upload the -flat.vmdk file to the image store.
+ 5. Delete the coalesced .vmdk and -flat.vmdk created.
+ """
+ vm_ref = self._get_vm_ref_from_the_name(instance.name)
+ if vm_ref is None:
+ raise exception.InstanceNotFound(instance_id=instance.id)
+
+ client_factory = self._session._get_vim().client.factory
+ service_content = self._session._get_vim().get_service_content()
+
+ def _get_vm_and_vmdk_attribs():
+ # Get the vmdk file name that the VM is pointing to
+ hardware_devices = self._session._call_method(vim_util,
+ "get_dynamic_property", vm_ref,
+ "VirtualMachine", "config.hardware.device")
+ vmdk_file_path_before_snapshot, adapter_type = \
+ vm_util.get_vmdk_file_path_and_adapter_type(client_factory,
+ hardware_devices)
+ datastore_name = vm_util.split_datastore_path(
+ vmdk_file_path_before_snapshot)[0]
+ os_type = self._session._call_method(vim_util,
+ "get_dynamic_property", vm_ref,
+ "VirtualMachine", "summary.config.guestId")
+ return (vmdk_file_path_before_snapshot, adapter_type,
+ datastore_name, os_type)
+
+ vmdk_file_path_before_snapshot, adapter_type, datastore_name,\
+ os_type = _get_vm_and_vmdk_attribs()
+
+ def _create_vm_snapshot():
+ # Create a snapshot of the VM
+ LOG.debug(_("Creating Snapshot of the VM instance %s ") %
+ instance.name)
+ snapshot_task = self._session._call_method(
+ self._session._get_vim(),
+ "CreateSnapshot_Task", vm_ref,
+ name="%s-snapshot" % instance.name,
+ description="Taking Snapshot of the VM",
+ memory=True,
+ quiesce=True)
+ self._session._wait_for_task(instance['uuid'], snapshot_task)
+ LOG.debug(_("Created Snapshot of the VM instance %s ") %
+ instance.name)
+
+ _create_vm_snapshot()
+
+ def _check_if_tmp_folder_exists():
+ # Copy the contents of the VM that were there just before the
+ # snapshot was taken
+ ds_ref_ret = vim_util.get_dynamic_property(
+ self._session._get_vim(),
+ vm_ref,
+ "VirtualMachine",
+ "datastore")
+ if not ds_ref_ret:
+ raise exception.DatastoreNotFound()
+ ds_ref = ds_ref_ret.ManagedObjectReference[0]
+ ds_browser = vim_util.get_dynamic_property(
+ self._session._get_vim(),
+ ds_ref,
+ "Datastore",
+ "browser")
+ # Check if the vmware-tmp folder exists or not. If not, create one
+ tmp_folder_path = vm_util.build_datastore_path(datastore_name,
+ "vmware-tmp")
+ if not self._path_exists(ds_browser, tmp_folder_path):
+ self._mkdir(vm_util.build_datastore_path(datastore_name,
+ "vmware-tmp"))
+
+ _check_if_tmp_folder_exists()
+
+ # Generate a random vmdk file name to which the coalesced vmdk content
+ # will be copied to. A random name is chosen so that we don't have
+ # name clashes.
+ random_name = str(uuid.uuid4())
+ dest_vmdk_file_location = vm_util.build_datastore_path(datastore_name,
+ "vmware-tmp/%s.vmdk" % random_name)
+ dc_ref = self._get_datacenter_name_and_ref()[0]
+
+ def _copy_vmdk_content():
+ # Copy the contents of the disk ( or disks, if there were snapshots
+ # done earlier) to a temporary vmdk file.
+ copy_spec = vm_util.get_copy_virtual_disk_spec(client_factory,
+ adapter_type)
+ LOG.debug(_("Copying disk data before snapshot of the VM "
+ " instance %s") % instance.name)
+ copy_disk_task = self._session._call_method(
+ self._session._get_vim(),
+ "CopyVirtualDisk_Task",
+ service_content.virtualDiskManager,
+ sourceName=vmdk_file_path_before_snapshot,
+ sourceDatacenter=dc_ref,
+ destName=dest_vmdk_file_location,
+ destDatacenter=dc_ref,
+ destSpec=copy_spec,
+ force=False)
+ self._session._wait_for_task(instance['uuid'], copy_disk_task)
+ LOG.debug(_("Copied disk data before snapshot of the VM "
+ "instance %s") % instance.name)
+
+ _copy_vmdk_content()
+
+ cookies = self._session._get_vim().client.options.transport.cookiejar
+
+ def _upload_vmdk_to_image_repository():
+ # Upload the contents of -flat.vmdk file which has the disk data.
+ LOG.debug(_("Uploading image %s") % snapshot_name)
+ vmware_images.upload_image(
+ context,
+ snapshot_name,
+ instance,
+ os_type=os_type,
+ adapter_type=adapter_type,
+ image_version=1,
+ host=self._session._host_ip,
+ data_center_name=self._get_datacenter_name_and_ref()[1],
+ datastore_name=datastore_name,
+ cookies=cookies,
+ file_path="vmware-tmp/%s-flat.vmdk" % random_name)
+ LOG.debug(_("Uploaded image %s") % snapshot_name)
+
+ _upload_vmdk_to_image_repository()
+
+ def _clean_temp_data():
+ """
+ Delete temporary vmdk files generated in image handling
+ operations.
+ """
+ # Delete the temporary vmdk created above.
+ LOG.debug(_("Deleting temporary vmdk file %s")
+ % dest_vmdk_file_location)
+ remove_disk_task = self._session._call_method(
+ self._session._get_vim(),
+ "DeleteVirtualDisk_Task",
+ service_content.virtualDiskManager,
+ name=dest_vmdk_file_location,
+ datacenter=dc_ref)
+ self._session._wait_for_task(instance['uuid'], remove_disk_task)
+ LOG.debug(_("Deleted temporary vmdk file %s")
+ % dest_vmdk_file_location)
+
+ _clean_temp_data()
+
+ def reboot(self, instance, network_info):
+ """Reboot a VM instance."""
+ vm_ref = self._get_vm_ref_from_the_name(instance.name)
+ if vm_ref is None:
+ raise exception.InstanceNotFound(instance_id=instance.id)
+
+ self.plug_vifs(instance, network_info)
+
+ lst_properties = ["summary.guest.toolsStatus", "runtime.powerState",
+ "summary.guest.toolsRunningStatus"]
+ props = self._session._call_method(vim_util, "get_object_properties",
+ None, vm_ref, "VirtualMachine",
+ lst_properties)
+ pwr_state = None
+ tools_status = None
+ tools_running_status = False
+ for elem in props:
+ for prop in elem.propSet:
+ if prop.name == "runtime.powerState":
+ pwr_state = prop.val
+ elif prop.name == "summary.guest.toolsStatus":
+ tools_status = prop.val
+ elif prop.name == "summary.guest.toolsRunningStatus":
+ tools_running_status = prop.val
+
+ # Raise an exception if the VM is not powered On.
+ if pwr_state not in ["poweredOn"]:
+ reason = _("instance is not powered on")
+ raise exception.InstanceRebootFailure(reason=reason)
+
+ # If latest vmware tools are installed in the VM, and that the tools
+ # are running, then only do a guest reboot. Otherwise do a hard reset.
+ if (tools_status == "toolsOk" and
+ tools_running_status == "guestToolsRunning"):
+ LOG.debug(_("Rebooting guest OS of VM %s") % instance.name)
+ self._session._call_method(self._session._get_vim(), "RebootGuest",
+ vm_ref)
+ LOG.debug(_("Rebooted guest OS of VM %s") % instance.name)
+ else:
+ LOG.debug(_("Doing hard reboot of VM %s") % instance.name)
+ reset_task = self._session._call_method(self._session._get_vim(),
+ "ResetVM_Task", vm_ref)
+ self._session._wait_for_task(instance['uuid'], reset_task)
+ LOG.debug(_("Did hard reboot of VM %s") % instance.name)
+
+ def destroy(self, instance, network_info):
+ """
+ Destroy a VM instance. Steps followed are:
+ 1. Power off the VM, if it is in poweredOn state.
+ 2. Un-register a VM.
+ 3. Delete the contents of the folder holding the VM related data.
+ """
+ try:
+ vm_ref = self._get_vm_ref_from_the_name(instance.name)
+ if vm_ref is None:
+ LOG.debug(_("instance - %s not present") % instance.name)
+ return
+ lst_properties = ["config.files.vmPathName", "runtime.powerState"]
+ props = self._session._call_method(vim_util,
+ "get_object_properties",
+ None, vm_ref, "VirtualMachine", lst_properties)
+ pwr_state = None
+ for elem in props:
+ vm_config_pathname = None
+ for prop in elem.propSet:
+ if prop.name == "runtime.powerState":
+ pwr_state = prop.val
+ elif prop.name == "config.files.vmPathName":
+ vm_config_pathname = prop.val
+ if vm_config_pathname:
+ datastore_name, vmx_file_path = \
+ vm_util.split_datastore_path(vm_config_pathname)
+ # Power off the VM if it is in PoweredOn state.
+ if pwr_state == "poweredOn":
+ LOG.debug(_("Powering off the VM %s") % instance.name)
+ poweroff_task = self._session._call_method(
+ self._session._get_vim(),
+ "PowerOffVM_Task", vm_ref)
+ self._session._wait_for_task(instance['uuid'], poweroff_task)
+ LOG.debug(_("Powered off the VM %s") % instance.name)
+
+ # Un-register the VM
+ try:
+ LOG.debug(_("Unregistering the VM %s") % instance.name)
+ self._session._call_method(self._session._get_vim(),
+ "UnregisterVM", vm_ref)
+ LOG.debug(_("Unregistered the VM %s") % instance.name)
+ except Exception, excep:
+ LOG.warn(_("In vmwareapi:vmops:destroy, got this exception"
+ " while un-registering the VM: %s") % str(excep))
+
+ self._unplug_vifs(instance, network_info)
+
+ # Delete the folder holding the VM related content on
+ # the datastore.
+ try:
+ dir_ds_compliant_path = vm_util.build_datastore_path(
+ datastore_name,
+ os.path.dirname(vmx_file_path))
+ LOG.debug(_("Deleting contents of the VM %(name)s from "
+ "datastore %(datastore_name)s") %
+ ({'name': instance.name,
+ 'datastore_name': datastore_name}))
+ delete_task = self._session._call_method(
+ self._session._get_vim(),
+ "DeleteDatastoreFile_Task",
+ self._session._get_vim().get_service_content().fileManager,
+ name=dir_ds_compliant_path)
+ self._session._wait_for_task(instance['uuid'], delete_task)
+ LOG.debug(_("Deleted contents of the VM %(name)s from "
+ "datastore %(datastore_name)s") %
+ ({'name': instance.name,
+ 'datastore_name': datastore_name}))
+ except Exception, excep:
+ LOG.warn(_("In vmwareapi:vmops:destroy, "
+ "got this exception while deleting"
+ " the VM contents from the disk: %s")
+ % str(excep))
+ except Exception, exc:
+ LOG.exception(exc)
+
+ def pause(self, instance):
+ """Pause a VM instance."""
+ raise exception.ApiError("pause not supported for vmwareapi")
+
+ def unpause(self, instance):
+ """Un-Pause a VM instance."""
+ raise exception.ApiError("unpause not supported for vmwareapi")
+
+ def suspend(self, instance):
+ """Suspend the specified instance."""
+ vm_ref = self._get_vm_ref_from_the_name(instance.name)
+ if vm_ref is None:
+ raise exception.InstanceNotFound(instance_id=instance.id)
+
+ pwr_state = self._session._call_method(vim_util,
+ "get_dynamic_property", vm_ref,
+ "VirtualMachine", "runtime.powerState")
+ # Only PoweredOn VMs can be suspended.
+ if pwr_state == "poweredOn":
+ LOG.debug(_("Suspending the VM %s ") % instance.name)
+ suspend_task = self._session._call_method(self._session._get_vim(),
+ "SuspendVM_Task", vm_ref)
+ self._session._wait_for_task(instance['uuid'], suspend_task)
+ LOG.debug(_("Suspended the VM %s ") % instance.name)
+ # Raise Exception if VM is poweredOff
+ elif pwr_state == "poweredOff":
+ reason = _("instance is powered off and can not be suspended.")
+ raise exception.InstanceSuspendFailure(reason=reason)
+
+ LOG.debug(_("VM %s was already in suspended state. So returning "
+ "without doing anything") % instance.name)
+
+ def resume(self, instance):
+ """Resume the specified instance."""
+ vm_ref = self._get_vm_ref_from_the_name(instance.name)
+ if vm_ref is None:
+ raise exception.InstanceNotFound(instance_id=instance.id)
+
+ pwr_state = self._session._call_method(vim_util,
+ "get_dynamic_property", vm_ref,
+ "VirtualMachine", "runtime.powerState")
+ if pwr_state.lower() == "suspended":
+ LOG.debug(_("Resuming the VM %s") % instance.name)
+ suspend_task = self._session._call_method(
+ self._session._get_vim(),
+ "PowerOnVM_Task", vm_ref)
+ self._session._wait_for_task(instance['uuid'], suspend_task)
+ LOG.debug(_("Resumed the VM %s ") % instance.name)
+ else:
+ reason = _("instance is not in a suspended state")
+ raise exception.InstanceResumeFailure(reason=reason)
+
+ def get_info(self, instance_name):
+ """Return data about the VM instance."""
+ vm_ref = self._get_vm_ref_from_the_name(instance_name)
+ if vm_ref is None:
+ raise exception.InstanceNotFound(instance_id=instance_name)
+
+ lst_properties = ["summary.config.numCpu",
+ "summary.config.memorySizeMB",
+ "runtime.powerState"]
+ vm_props = self._session._call_method(vim_util,
+ "get_object_properties", None, vm_ref, "VirtualMachine",
+ lst_properties)
+ max_mem = None
+ pwr_state = None
+ num_cpu = None
+ for elem in vm_props:
+ for prop in elem.propSet:
+ if prop.name == "summary.config.numCpu":
+ num_cpu = int(prop.val)
+ elif prop.name == "summary.config.memorySizeMB":
+ # In MB, but we want in KB
+ max_mem = int(prop.val) * 1024
+ elif prop.name == "runtime.powerState":
+ pwr_state = VMWARE_POWER_STATES[prop.val]
+
+ return {'state': pwr_state,
+ 'max_mem': max_mem,
+ 'mem': max_mem,
+ 'num_cpu': num_cpu,
+ 'cpu_time': 0}
+
+ def get_diagnostics(self, instance):
+ """Return data about VM diagnostics."""
+ raise exception.ApiError("get_diagnostics not implemented for "
+ "vmwareapi")
+
+ def get_console_output(self, instance):
+ """Return snapshot of console."""
+ vm_ref = self._get_vm_ref_from_the_name(instance.name)
+ if vm_ref is None:
+ raise exception.InstanceNotFound(instance_id=instance.id)
+ param_list = {"id": str(vm_ref)}
+ base_url = "%s://%s/screen?%s" % (self._session._scheme,
+ self._session._host_ip,
+ urllib.urlencode(param_list))
+ request = urllib2.Request(base_url)
+ base64string = base64.encodestring(
+ '%s:%s' % (
+ self._session._host_username,
+ self._session._host_password)).replace('\n', '')
+ request.add_header("Authorization", "Basic %s" % base64string)
+ result = urllib2.urlopen(request)
+ if result.code == 200:
+ return result.read()
+ else:
+ return ""
+
+ def get_ajax_console(self, instance):
+ """Return link to instance's ajax console."""
+ return 'http://fakeajaxconsole/fake_url'
+
+ def _set_machine_id(self, client_factory, instance, network_info):
+ """
+ Set the machine id of the VM for guest tools to pick up and reconfigure
+ the network interfaces.
+ """
+ vm_ref = self._get_vm_ref_from_the_name(instance.name)
+ if vm_ref is None:
+ raise exception.InstanceNotFound(instance_id=instance.id)
+
+ machine_id_str = ''
+ for (network, info) in network_info:
+ # TODO(vish): add support for dns2
+ # TODO(sateesh): add support for injection of ipv6 configuration
+ ip_v4 = ip_v6 = None
+ if 'ips' in info and len(info['ips']) > 0:
+ ip_v4 = info['ips'][0]
+ if 'ip6s' in info and len(info['ip6s']) > 0:
+ ip_v6 = info['ip6s'][0]
+ if len(info['dns']) > 0:
+ dns = info['dns'][0]
+ else:
+ dns = ''
+
+ interface_str = "%s;%s;%s;%s;%s;%s" % \
+ (info['mac'],
+ ip_v4 and ip_v4['ip'] or '',
+ ip_v4 and ip_v4['netmask'] or '',
+ info['gateway'],
+ info['broadcast'],
+ dns)
+ machine_id_str = machine_id_str + interface_str + '#'
+
+ machine_id_change_spec = \
+ vm_util.get_machine_id_change_spec(client_factory, machine_id_str)
+
+ LOG.debug(_("Reconfiguring VM instance %(name)s to set the machine id "
+ "with ip - %(ip_addr)s") %
+ ({'name': instance.name,
+ 'ip_addr': ip_v4['ip']}))
+ reconfig_task = self._session._call_method(self._session._get_vim(),
+ "ReconfigVM_Task", vm_ref,
+ spec=machine_id_change_spec)
+ self._session._wait_for_task(instance['uuid'], reconfig_task)
+ LOG.debug(_("Reconfigured VM instance %(name)s to set the machine id "
+ "with ip - %(ip_addr)s") %
+ ({'name': instance.name,
+ 'ip_addr': ip_v4['ip']}))
+
+ def _get_datacenter_name_and_ref(self):
+ """Get the datacenter name and the reference."""
+ dc_obj = self._session._call_method(vim_util, "get_objects",
+ "Datacenter", ["name"])
+ return dc_obj[0].obj, dc_obj[0].propSet[0].val
+
+ def _path_exists(self, ds_browser, ds_path):
+ """Check if the path exists on the datastore."""
+ search_task = self._session._call_method(self._session._get_vim(),
+ "SearchDatastore_Task",
+ ds_browser,
+ datastorePath=ds_path)
+ # Wait till the state changes from queued or running.
+ # If an error state is returned, it means that the path doesn't exist.
+ while True:
+ task_info = self._session._call_method(vim_util,
+ "get_dynamic_property",
+ search_task, "Task", "info")
+ if task_info.state in ['queued', 'running']:
+ time.sleep(2)
+ continue
+ break
+ if task_info.state == "error":
+ return False
+ return True
+
+ def _mkdir(self, ds_path):
+ """
+ Creates a directory at the path specified. If it is just "NAME",
+ then a directory with this name is created at the topmost level of the
+ DataStore.
+ """
+ LOG.debug(_("Creating directory with path %s") % ds_path)
+ self._session._call_method(self._session._get_vim(), "MakeDirectory",
+ self._session._get_vim().get_service_content().fileManager,
+ name=ds_path, createParentDirectories=False)
+ LOG.debug(_("Created directory with path %s") % ds_path)
+
+ def _get_vm_ref_from_the_name(self, vm_name):
+ """Get reference to the VM with the name specified."""
+ vms = self._session._call_method(vim_util, "get_objects",
+ "VirtualMachine", ["name"])
+ for vm in vms:
+ if vm.propSet[0].val == vm_name:
+ return vm.obj
+ return None
+
+ def plug_vifs(self, instance, network_info):
+ """Plug VIFs into networks."""
+ for (network, mapping) in network_info:
+ self._vif_driver.plug(instance, network, mapping)
+
+ def _unplug_vifs(self, instance, network_info):
+ """Unplug VIFs from networks."""
+ for (network, mapping) in network_info:
+ self._vif_driver.unplug(instance, network, mapping)
diff --git a/nova/virt/vmwareapi/vmware_images.py b/nova/virt/vmwareapi/vmware_images.py
index b03ccae25..89f84d0f6 100644
--- a/nova/virt/vmwareapi/vmware_images.py
+++ b/nova/virt/vmwareapi/vmware_images.py
@@ -1,145 +1,145 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Citrix Systems, Inc.
-# Copyright 2011 OpenStack LLC.
-#
-# 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.
-"""
-Utility functions for Image transfer.
-"""
-
-from nova import exception
-from nova.image import glance
-from nova import log as logging
-from nova.virt.vmwareapi import io_util
-from nova.virt.vmwareapi import read_write_util
-
-LOG = logging.getLogger("nova.virt.vmwareapi.vmware_images")
-
-QUEUE_BUFFER_SIZE = 10
-
-
-def start_transfer(read_file_handle, data_size, write_file_handle=None,
- glance_client=None, image_id=None, image_meta=None):
- """Start the data transfer from the reader to the writer.
- Reader writes to the pipe and the writer reads from the pipe. This means
- that the total transfer time boils down to the slower of the read/write
- and not the addition of the two times."""
-
- if not image_meta:
- image_meta = {}
-
- # The pipe that acts as an intermediate store of data for reader to write
- # to and writer to grab from.
- thread_safe_pipe = io_util.ThreadSafePipe(QUEUE_BUFFER_SIZE, data_size)
- # The read thread. In case of glance it is the instance of the
- # GlanceFileRead class. The glance client read returns an iterator
- # and this class wraps that iterator to provide datachunks in calls
- # to read.
- read_thread = io_util.IOThread(read_file_handle, thread_safe_pipe)
-
- # In case of Glance - VMWare transfer, we just need a handle to the
- # HTTP Connection that is to send transfer data to the VMWare datastore.
- if write_file_handle:
- write_thread = io_util.IOThread(thread_safe_pipe, write_file_handle)
- # In case of VMWare - Glance transfer, we relinquish VMWare HTTP file read
- # handle to Glance Client instance, but to be sure of the transfer we need
- # to be sure of the status of the image on glnace changing to active.
- # The GlanceWriteThread handles the same for us.
- elif glance_client and image_id:
- write_thread = io_util.GlanceWriteThread(thread_safe_pipe,
- glance_client, image_id, image_meta)
- # Start the read and write threads.
- read_event = read_thread.start()
- write_event = write_thread.start()
- try:
- # Wait on the read and write events to signal their end
- read_event.wait()
- write_event.wait()
- except Exception, exc:
- # In case of any of the reads or writes raising an exception,
- # stop the threads so that we un-necessarily don't keep the other one
- # waiting.
- read_thread.stop()
- write_thread.stop()
-
- # Log and raise the exception.
- LOG.exception(exc)
- raise exception.Error(exc)
- finally:
- # No matter what, try closing the read and write handles, if it so
- # applies.
- read_file_handle.close()
- if write_file_handle:
- write_file_handle.close()
-
-
-def fetch_image(context, image, instance, **kwargs):
- """Download image from the glance image server."""
- LOG.debug(_("Downloading image %s from glance image server") % image)
- (glance_client, image_id) = glance.get_glance_client(context, image)
- metadata, read_iter = glance_client.get_image(image_id)
- read_file_handle = read_write_util.GlanceFileRead(read_iter)
- file_size = int(metadata['size'])
- write_file_handle = read_write_util.VMWareHTTPWriteFile(
- kwargs.get("host"),
- kwargs.get("data_center_name"),
- kwargs.get("datastore_name"),
- kwargs.get("cookies"),
- kwargs.get("file_path"),
- file_size)
- start_transfer(read_file_handle, file_size,
- write_file_handle=write_file_handle)
- LOG.debug(_("Downloaded image %s from glance image server") % image)
-
-
-def upload_image(context, image, instance, **kwargs):
- """Upload the snapshotted vm disk file to Glance image server."""
- LOG.debug(_("Uploading image %s to the Glance image server") % image)
- read_file_handle = read_write_util.VmWareHTTPReadFile(
- kwargs.get("host"),
- kwargs.get("data_center_name"),
- kwargs.get("datastore_name"),
- kwargs.get("cookies"),
- kwargs.get("file_path"))
- file_size = read_file_handle.get_size()
- (glance_client, image_id) = glance.get_glance_client(context, image)
- # The properties and other fields that we need to set for the image.
- image_metadata = {"is_public": True,
- "disk_format": "vmdk",
- "container_format": "bare",
- "type": "vmdk",
- "properties": {"vmware_adaptertype":
- kwargs.get("adapter_type"),
- "vmware_ostype": kwargs.get("os_type"),
- "vmware_image_version":
- kwargs.get("image_version")}}
- start_transfer(read_file_handle, file_size, glance_client=glance_client,
- image_id=image_id, image_meta=image_metadata)
- LOG.debug(_("Uploaded image %s to the Glance image server") % image)
-
-
-def get_vmdk_size_and_properties(context, image, instance):
- """
- Get size of the vmdk file that is to be downloaded for attach in spawn.
- Need this to create the dummy virtual disk for the meta-data file. The
- geometry of the disk created depends on the size.
- """
-
- LOG.debug(_("Getting image size for the image %s") % image)
- (glance_client, image_id) = glance.get_glance_client(context, image)
- meta_data = glance_client.get_image_meta(image_id)
- size, properties = meta_data["size"], meta_data["properties"]
- LOG.debug(_("Got image size of %(size)s for the image %(image)s") %
- locals())
- return size, properties
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 OpenStack LLC.
+#
+# 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.
+"""
+Utility functions for Image transfer.
+"""
+
+from nova import exception
+from nova.image import glance
+from nova import log as logging
+from nova.virt.vmwareapi import io_util
+from nova.virt.vmwareapi import read_write_util
+
+LOG = logging.getLogger("nova.virt.vmwareapi.vmware_images")
+
+QUEUE_BUFFER_SIZE = 10
+
+
+def start_transfer(read_file_handle, data_size, write_file_handle=None,
+ glance_client=None, image_id=None, image_meta=None):
+ """Start the data transfer from the reader to the writer.
+ Reader writes to the pipe and the writer reads from the pipe. This means
+ that the total transfer time boils down to the slower of the read/write
+ and not the addition of the two times."""
+
+ if not image_meta:
+ image_meta = {}
+
+ # The pipe that acts as an intermediate store of data for reader to write
+ # to and writer to grab from.
+ thread_safe_pipe = io_util.ThreadSafePipe(QUEUE_BUFFER_SIZE, data_size)
+ # The read thread. In case of glance it is the instance of the
+ # GlanceFileRead class. The glance client read returns an iterator
+ # and this class wraps that iterator to provide datachunks in calls
+ # to read.
+ read_thread = io_util.IOThread(read_file_handle, thread_safe_pipe)
+
+ # In case of Glance - VMWare transfer, we just need a handle to the
+ # HTTP Connection that is to send transfer data to the VMWare datastore.
+ if write_file_handle:
+ write_thread = io_util.IOThread(thread_safe_pipe, write_file_handle)
+ # In case of VMWare - Glance transfer, we relinquish VMWare HTTP file read
+ # handle to Glance Client instance, but to be sure of the transfer we need
+ # to be sure of the status of the image on glnace changing to active.
+ # The GlanceWriteThread handles the same for us.
+ elif glance_client and image_id:
+ write_thread = io_util.GlanceWriteThread(thread_safe_pipe,
+ glance_client, image_id, image_meta)
+ # Start the read and write threads.
+ read_event = read_thread.start()
+ write_event = write_thread.start()
+ try:
+ # Wait on the read and write events to signal their end
+ read_event.wait()
+ write_event.wait()
+ except Exception, exc:
+ # In case of any of the reads or writes raising an exception,
+ # stop the threads so that we un-necessarily don't keep the other one
+ # waiting.
+ read_thread.stop()
+ write_thread.stop()
+
+ # Log and raise the exception.
+ LOG.exception(exc)
+ raise exception.Error(exc)
+ finally:
+ # No matter what, try closing the read and write handles, if it so
+ # applies.
+ read_file_handle.close()
+ if write_file_handle:
+ write_file_handle.close()
+
+
+def fetch_image(context, image, instance, **kwargs):
+ """Download image from the glance image server."""
+ LOG.debug(_("Downloading image %s from glance image server") % image)
+ (glance_client, image_id) = glance.get_glance_client(context, image)
+ metadata, read_iter = glance_client.get_image(image_id)
+ read_file_handle = read_write_util.GlanceFileRead(read_iter)
+ file_size = int(metadata['size'])
+ write_file_handle = read_write_util.VMWareHTTPWriteFile(
+ kwargs.get("host"),
+ kwargs.get("data_center_name"),
+ kwargs.get("datastore_name"),
+ kwargs.get("cookies"),
+ kwargs.get("file_path"),
+ file_size)
+ start_transfer(read_file_handle, file_size,
+ write_file_handle=write_file_handle)
+ LOG.debug(_("Downloaded image %s from glance image server") % image)
+
+
+def upload_image(context, image, instance, **kwargs):
+ """Upload the snapshotted vm disk file to Glance image server."""
+ LOG.debug(_("Uploading image %s to the Glance image server") % image)
+ read_file_handle = read_write_util.VmWareHTTPReadFile(
+ kwargs.get("host"),
+ kwargs.get("data_center_name"),
+ kwargs.get("datastore_name"),
+ kwargs.get("cookies"),
+ kwargs.get("file_path"))
+ file_size = read_file_handle.get_size()
+ (glance_client, image_id) = glance.get_glance_client(context, image)
+ # The properties and other fields that we need to set for the image.
+ image_metadata = {"is_public": True,
+ "disk_format": "vmdk",
+ "container_format": "bare",
+ "type": "vmdk",
+ "properties": {"vmware_adaptertype":
+ kwargs.get("adapter_type"),
+ "vmware_ostype": kwargs.get("os_type"),
+ "vmware_image_version":
+ kwargs.get("image_version")}}
+ start_transfer(read_file_handle, file_size, glance_client=glance_client,
+ image_id=image_id, image_meta=image_metadata)
+ LOG.debug(_("Uploaded image %s to the Glance image server") % image)
+
+
+def get_vmdk_size_and_properties(context, image, instance):
+ """
+ Get size of the vmdk file that is to be downloaded for attach in spawn.
+ Need this to create the dummy virtual disk for the meta-data file. The
+ geometry of the disk created depends on the size.
+ """
+
+ LOG.debug(_("Getting image size for the image %s") % image)
+ (glance_client, image_id) = glance.get_glance_client(context, image)
+ meta_data = glance_client.get_image_meta(image_id)
+ size, properties = meta_data["size"], meta_data["properties"]
+ LOG.debug(_("Got image size of %(size)s for the image %(image)s") %
+ locals())
+ return size, properties