From 45ca7b71a8e749cbd9b7729b922190e9aaa53744 Mon Sep 17 00:00:00 2001 From: sateesh Date: Wed, 16 Mar 2011 21:54:02 +0530 Subject: [PATCH] * Updated document vmware_readme.rst to mention VLAN networking * Corrected docstrings as per pep0257 recommentations. * Stream-lined the comments. * Updated code with locals() where ever applicable. * VIM : It stands for VMware Virtual Infrastructure Methodology. We have used the terminology from VMware. we have added a question in FAQ inside vmware_readme.rst in doc/source * New fake db: vmwareapi fake module uses a different set of fields and hence the structures required are different. Ex: bridge : 'xenbr0' does not hold good for VMware environment and bridge : 'vmnic0' is used instead. Also return values varies, hence went for implementing separate fake db. * Now using eventlet library instead and removed io_utils.py from branch. * Now using glance.client.Client instead of homegrown code to talk to Glance server to handle images. * Corrected all mis-spelled function names and corresponding calls. Yeah, an auto-complete side-effect! --- doc/source/vmwareapi_readme.rst | 6 +- nova/console/vmrc.py | 16 ++- nova/console/vmrc_manager.py | 35 ++++-- nova/network/vmwareapi_net.py | 36 +++--- nova/tests/test_vmwareapi.py | 28 +++-- nova/tests/vmwareapi/__init__.py | 5 + nova/tests/vmwareapi/db_fakes.py | 12 +- nova/tests/vmwareapi/stubs.py | 6 +- nova/virt/vmwareapi/__init__.py | 2 +- nova/virt/vmwareapi/error_util.py | 48 +++++--- nova/virt/vmwareapi/fake.py | 122 ++++++++++--------- nova/virt/vmwareapi/network_utils.py | 28 +++-- nova/virt/vmwareapi/read_write_util.py | 145 +++------------------- nova/virt/vmwareapi/vim.py | 59 ++++----- nova/virt/vmwareapi/vim_util.py | 45 +++---- nova/virt/vmwareapi/vm_util.py | 70 ++++++----- nova/virt/vmwareapi/vmops.py | 159 ++++++++++++++----------- nova/virt/vmwareapi/vmware_images.py | 109 ++++++----------- nova/virt/vmwareapi_conn.py | 83 +++++++------ tools/esx/guest_tool.py | 31 ++--- 20 files changed, 500 insertions(+), 545 deletions(-) diff --git a/doc/source/vmwareapi_readme.rst b/doc/source/vmwareapi_readme.rst index b56cae0745ff..fb0e42b80154 100644 --- a/doc/source/vmwareapi_readme.rst +++ b/doc/source/vmwareapi_readme.rst @@ -26,7 +26,7 @@ The basic requirement is to support VMware vSphere 4.1 as a compute provider wit The 'vmwareapi' module is integrated with Glance, so that VM images can be streamed from there for boot on ESXi using Glance server for image storage & retrieval. -Currently supports Nova's flat networking model (Flat Manager). +Currently supports Nova's flat networking model (Flat Manager) & VLAN networking model. .. image:: images/vmwareapi_blockdiagram.jpg @@ -213,3 +213,7 @@ FAQ * VMware VMRC based consoles are supported. There are 2 options for credentials one is OTP (Secure but creates multiple session entries in DB for each OpenStack console create request.) & other is host based credentials (It may not be secure as ESX credentials are transmitted as clear text). +5. What does 'Vim' refer to as far as vmwareapi module is concerned? + +* Vim refers to VMware Virtual Infrastructure Methodology. This is not to be confused with "VIM" editor. + diff --git a/nova/console/vmrc.py b/nova/console/vmrc.py index f448d094b543..521da289f402 100644 --- a/nova/console/vmrc.py +++ b/nova/console/vmrc.py @@ -65,11 +65,13 @@ class VMRCConsole(object): def fix_pool_password(self, password): """Encode password.""" - #TODO:Encrypt pool password + # TODO(sateesh): Encrypt pool password return password def generate_password(self, vim_session, pool, instance_name): - """Returns a VMRC Connection credentials + """ + Returns VMRC Connection credentials. + Return string is of the form ':@'. """ username, password = pool['username'], pool['password'] @@ -98,12 +100,12 @@ class VMRCConsole(object): return base64.b64encode(json_data) def is_otp(self): - """Is one time password.""" + """Is one time password or not.""" return False class VMRCSessionConsole(VMRCConsole): - """VMRC console driver with VMRC One Time Sessions""" + """VMRC console driver with VMRC One Time Sessions.""" def __init__(self): super(VMRCSessionConsole, self).__init__() @@ -113,7 +115,9 @@ class VMRCSessionConsole(VMRCConsole): return 'vmrc+session' def generate_password(self, vim_session, pool, instance_name): - """Returns a VMRC Session + """ + Returns a VMRC Session. + Return string is of the form ':'. """ vms = vim_session._call_method(vim_util, "get_objects", @@ -136,5 +140,5 @@ class VMRCSessionConsole(VMRCConsole): return base64.b64encode(json_data) def is_otp(self): - """Is one time password.""" + """Is one time password or not.""" return True diff --git a/nova/console/vmrc_manager.py b/nova/console/vmrc_manager.py index 24f7f5fe28cc..09beac7a0d9a 100644 --- a/nova/console/vmrc_manager.py +++ b/nova/console/vmrc_manager.py @@ -16,7 +16,7 @@ # under the License. """ -VMRC Console Manager +VMRC Console Manager. """ from nova import exception @@ -25,6 +25,7 @@ from nova import log as logging from nova import manager from nova import rpc from nova import utils +from nova.virt.vmwareapi_conn import VMWareAPISession LOG = logging.getLogger("nova.console.vmrc_manager") @@ -39,8 +40,8 @@ flags.DEFINE_string('console_driver', class ConsoleVMRCManager(manager.Manager): - """Manager to handle VMRC connections needed for accessing - instance consoles + """ + Manager to handle VMRC connections needed for accessing instance consoles. """ def __init__(self, console_driver=None, *args, **kwargs): @@ -48,15 +49,29 @@ class ConsoleVMRCManager(manager.Manager): super(ConsoleVMRCManager, self).__init__(*args, **kwargs) def init_host(self): + self.sessions = {} self.driver.init_host() + def _get_vim_session(self, pool): + """Get VIM session for the pool specified.""" + vim_session = None + if pool['id'] not in self.sessions.keys(): + vim_session = VMWareAPISession(pool['address'], + pool['username'], + pool['password'], + FLAGS.console_vmrc_error_retries) + self.sessions[pool['id']] = vim_session + return self.sessions[pool['id']] + def _generate_console(self, context, pool, name, instance_id, instance): + """Sets up console for the instance.""" LOG.debug(_("Adding console")) + password = self.driver.generate_password( - pool['address'], - pool['username'], - pool['password'], + self._get_vim_session(pool), + pool, instance.name) + console_data = {'instance_name': name, 'instance_id': instance_id, 'password': password, @@ -69,6 +84,10 @@ class ConsoleVMRCManager(manager.Manager): @exception.wrap_exception def add_console(self, context, instance_id, password=None, port=None, **kwargs): + """ + Adds a console for the instance. If it is one time password, then we + generate new console credentials. + """ instance = self.db.instance_get(context, instance_id) host = instance['host'] name = instance['name'] @@ -95,6 +114,7 @@ class ConsoleVMRCManager(manager.Manager): @exception.wrap_exception def remove_console(self, context, console_id, **_kwargs): + """Removes a console entry.""" try: console = self.db.console_get(context, console_id) except exception.NotFound: @@ -109,6 +129,7 @@ class ConsoleVMRCManager(manager.Manager): self.driver.teardown_console(context, console) def get_pool_for_instance_host(self, context, instance_host): + """Gets console pool info for the instance.""" context = context.elevated() console_type = self.driver.console_type try: @@ -126,7 +147,7 @@ class ConsoleVMRCManager(manager.Manager): pool_info['password'] = self.driver.fix_pool_password( pool_info['password']) pool_info['host'] = self.host - #ESX Address or Proxy Address + # ESX Address or Proxy Address public_host_name = pool_info['address'] if FLAGS.console_public_hostname: public_host_name = FLAGS.console_public_hostname diff --git a/nova/network/vmwareapi_net.py b/nova/network/vmwareapi_net.py index 13b619df56b9..f1232dadafe0 100644 --- a/nova/network/vmwareapi_net.py +++ b/nova/network/vmwareapi_net.py @@ -16,7 +16,7 @@ # under the License. """ -Implements vlans for vmwareapi +Implements vlans for vmwareapi. """ from nova import db @@ -36,8 +36,8 @@ flags.DEFINE_string('vlan_interface', 'vmnic0', def ensure_vlan_bridge(vlan_num, bridge, net_attrs=None): - """Create a vlan and bridge unless they already exist""" - #open vmwareapi session + """Create a vlan and bridge unless they already exist.""" + # Open vmwareapi session host_ip = FLAGS.vmwareapi_host_ip host_username = FLAGS.vmwareapi_host_username host_password = FLAGS.vmwareapi_host_password @@ -49,49 +49,43 @@ def ensure_vlan_bridge(vlan_num, bridge, net_attrs=None): session = VMWareAPISession(host_ip, host_username, host_password, FLAGS.vmwareapi_api_retry_count) vlan_interface = FLAGS.vlan_interface - #Check if the vlan_interface physical network adapter exists on the host + # Check if the vlan_interface physical network adapter exists on the host if not NetworkHelper.check_if_vlan_interface_exists(session, vlan_interface): raise exception.NotFound(_("There is no physical network adapter with " "the name %s on the ESX host") % vlan_interface) - #Get the vSwitch associated with the Physical Adapter + # Get the vSwitch associated with the Physical Adapter vswitch_associated = NetworkHelper.get_vswitch_for_vlan_interface( session, vlan_interface) if vswitch_associated is None: raise exception.NotFound(_("There is no virtual switch associated " "with the physical network adapter with name %s") % vlan_interface) - #check whether bridge already exists and retrieve the the ref of the - #network whose name_label is "bridge" + # Check whether bridge already exists and retrieve the the ref of the + # network whose name_label is "bridge" network_ref = NetworkHelper.get_network_with_the_name(session, bridge) if network_ref == None: - #Create a port group on the vSwitch associated with the vlan_interface - #corresponding physical network adapter on the ESX host + # Create a port group on the vSwitch associated with the vlan_interface + # corresponding physical network adapter on the ESX host NetworkHelper.create_port_group(session, bridge, vswitch_associated, vlan_num) else: - #Get the vlan id and vswitch corresponding to the port group + # Get the vlan id and vswitch corresponding to the port group pg_vlanid, pg_vswitch = \ - NetworkHelper.get_vlanid_and_vswicth_for_portgroup(session, bridge) + NetworkHelper.get_vlanid_and_vswitch_for_portgroup(session, bridge) - #Check if the vsiwtch associated is proper + # Check if the vsiwtch associated is proper if pg_vswitch != vswitch_associated: raise exception.Invalid(_("vSwitch which contains the port group " "%(bridge)s is not associated with the desired " "physical adapter. Expected vSwitch is " "%(vswitch_associated)s, but the one associated" - " is %(pg_vswitch)s") %\ - {"bridge": bridge, - "vswitch_associated": vswitch_associated, - "pg_vswitch": pg_vswitch}) + " is %(pg_vswitch)s") % locals()) - #Check if the vlan id is proper for the port group + # Check if the vlan id is proper for the port group if pg_vlanid != vlan_num: raise exception.Invalid(_("VLAN tag is not appropriate for the " "port group %(bridge)s. Expected VLAN tag is " "%(vlan_num)s, but the one associated with the " - "port group is %(pg_vlanid)s") %\ - {"bridge": bridge, - "vlan_num": vlan_num, - "pg_vlanid": pg_vlanid}) + "port group is %(pg_vlanid)s") % locals()) diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py index 65cdd5fcff78..b22d8b7b9956 100644 --- a/nova/tests/test_vmwareapi.py +++ b/nova/tests/test_vmwareapi.py @@ -16,8 +16,9 @@ # under the License. """ -Test suite for VMWareAPI +Test suite for VMWareAPI. """ + import stubout from nova import context @@ -38,9 +39,7 @@ FLAGS = flags.FLAGS class VMWareAPIVMTestCase(test.TestCase): - """ - Unit tests for Vmware API connection calls - """ + """Unit tests for Vmware API connection calls.""" def setUp(self): super(VMWareAPIVMTestCase, self).setUp() @@ -61,7 +60,7 @@ class VMWareAPIVMTestCase(test.TestCase): self.conn = vmwareapi_conn.get_connection(False) def _create_vm(self): - """ Create and spawn the VM """ + """Create and spawn the VM.""" values = {'name': 1, 'id': 1, 'project_id': self.project.id, @@ -78,15 +77,17 @@ class VMWareAPIVMTestCase(test.TestCase): self._check_vm_record() def _check_vm_record(self): - """ Check if the spawned VM's properties corresponds to the instance in - the db """ + """ + Check if the spawned VM's properties correspond to the instance in + the db. + """ instances = self.conn.list_instances() self.assertEquals(len(instances), 1) # Get Nova record for VM vm_info = self.conn.get_info(1) - # Get record for VMs + # Get record for VM vms = vmwareapi_fake._get_objects("VirtualMachine") vm = vms[0] @@ -106,8 +107,10 @@ class VMWareAPIVMTestCase(test.TestCase): self.assertEquals(vm.get("runtime.powerState"), 'poweredOn') def _check_vm_info(self, info, pwr_state=power_state.RUNNING): - """ Check if the get_info returned values correspond to the instance - object in the db """ + """ + Check if the get_info returned values correspond to the instance + object in the db. + """ mem_kib = long(self.type_data['memory_mb']) << 10 self.assertEquals(info["state"], pwr_state) self.assertEquals(info["max_mem"], mem_kib) @@ -194,8 +197,9 @@ class VMWareAPIVMTestCase(test.TestCase): pass def dummy_callback_handler(self, ret): - """ Dummy callback function to be passed to suspend, resume, etc. - calls """ + """ + Dummy callback function to be passed to suspend, resume, etc., calls. + """ pass def tearDown(self): diff --git a/nova/tests/vmwareapi/__init__.py b/nova/tests/vmwareapi/__init__.py index f346c053b401..478ee742b6bb 100644 --- a/nova/tests/vmwareapi/__init__.py +++ b/nova/tests/vmwareapi/__init__.py @@ -14,3 +14,8 @@ # 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 026a2038ee82..0addd5573d66 100644 --- a/nova/tests/vmwareapi/db_fakes.py +++ b/nova/tests/vmwareapi/db_fakes.py @@ -26,7 +26,7 @@ from nova import utils def stub_out_db_instance_api(stubs): - """ Stubs out the db API for creating Instances """ + """Stubs out the db API for creating Instances.""" INSTANCE_TYPES = { 'm1.tiny': dict(memory_mb=512, vcpus=1, local_gb=0, flavorid=1), @@ -38,7 +38,7 @@ def stub_out_db_instance_api(stubs): dict(memory_mb=16384, vcpus=8, local_gb=160, flavorid=5)} class FakeModel(object): - """ Stubs out for model """ + """Stubs out for model.""" def __init__(self, values): self.values = values @@ -53,7 +53,7 @@ def stub_out_db_instance_api(stubs): raise NotImplementedError() def fake_instance_create(values): - """ Stubs out the db.instance_create method """ + """Stubs out the db.instance_create method.""" type_data = INSTANCE_TYPES[values['instance_type']] @@ -77,7 +77,7 @@ def stub_out_db_instance_api(stubs): return FakeModel(base_options) def fake_network_get_by_instance(context, instance_id): - """ Stubs out the db.network_get_by_instance method """ + """Stubs out the db.network_get_by_instance method.""" fields = { 'bridge': 'vmnet0', @@ -87,11 +87,11 @@ def stub_out_db_instance_api(stubs): return FakeModel(fields) def fake_instance_action_create(context, action): - """ Stubs out the db.instance_action_create method """ + """Stubs out the db.instance_action_create method.""" pass def fake_instance_get_fixed_address(context, instance_id): - """ Stubs out the db.instance_get_fixed_address method """ + """Stubs out the db.instance_get_fixed_address method.""" return '10.10.10.10' def fake_instance_type_get_all(context, inactive=0): diff --git a/nova/tests/vmwareapi/stubs.py b/nova/tests/vmwareapi/stubs.py index da2d43c29798..a648efb160d2 100644 --- a/nova/tests/vmwareapi/stubs.py +++ b/nova/tests/vmwareapi/stubs.py @@ -25,17 +25,17 @@ from nova.virt.vmwareapi import vmware_images def fake_get_vim_object(arg): - """ Stubs out the VMWareAPISession's get_vim_object method """ + """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 """ + """Stubs out the VMWareAPISession's is_vim_object method.""" return isinstance(module, fake.FakeVim) def set_stubs(stubs): - """ Set the stubs """ + """Set the stubs.""" 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) diff --git a/nova/virt/vmwareapi/__init__.py b/nova/virt/vmwareapi/__init__.py index 6dbcc157aa63..d9b27de08ba4 100644 --- a/nova/virt/vmwareapi/__init__.py +++ b/nova/virt/vmwareapi/__init__.py @@ -15,5 +15,5 @@ # License for the specific language governing permissions and limitations # under the License. """ -:mod:`vmwareapi` -- Nova support for VMware ESX/ESXi Server through vSphere API +:mod:`vmwareapi` -- Nova support for VMware ESX/ESXi Server through VMware API. """ diff --git a/nova/virt/vmwareapi/error_util.py b/nova/virt/vmwareapi/error_util.py index 3196b5038001..cf92c3493dd6 100644 --- a/nova/virt/vmwareapi/error_util.py +++ b/nova/virt/vmwareapi/error_util.py @@ -16,7 +16,7 @@ # under the License. """ -Exception classes and SOAP response error checking module +Exception classes and SOAP response error checking module. """ FAULT_NOT_AUTHENTICATED = "NotAuthenticated" @@ -24,7 +24,7 @@ FAULT_ALREADY_EXISTS = "AlreadyExists" class VimException(Exception): - """The VIM Exception class""" + """The VIM Exception class.""" def __init__(self, exception_summary, excep): Exception.__init__(self) @@ -36,17 +36,17 @@ class VimException(Exception): class SessionOverLoadException(VimException): - """Session Overload Exception""" + """Session Overload Exception.""" pass class VimAttributeError(VimException): - """VI Attribute Error""" + """VI Attribute Error.""" pass class VimFaultException(Exception): - """The VIM Fault exception class""" + """The VIM Fault exception class.""" def __init__(self, fault_list, excep): Exception.__init__(self) @@ -58,23 +58,37 @@ class VimFaultException(Exception): class FaultCheckers: - """Methods for fault checking of SOAP response. Per Method error handlers + """ + 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 as a property and not as a SOAP fault.""" + embedded in the SOAP messages as properties and not as SOAP faults. + """ @classmethod def retrieveproperties_fault_checker(self, resp_obj): - """Checks the RetrieveProperties response for errors. Certain faults - are sent as a part of the SOAP body as property of missingSet. - For example NotAuthenticated fault""" + """ + 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 = [] - 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 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 " diff --git a/nova/virt/vmwareapi/fake.py b/nova/virt/vmwareapi/fake.py index e03d74cf89e0..38585c714e73 100644 --- a/nova/virt/vmwareapi/fake.py +++ b/nova/virt/vmwareapi/fake.py @@ -39,14 +39,14 @@ LOG = logging.getLogger("nova.virt.vmwareapi.fake") def log_db_contents(msg=None): - """ Log DB Contents""" + """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 """ + """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 @@ -63,18 +63,18 @@ def reset(): def cleanup(): - """ Clear the db contents """ + """Clear the db contents.""" for c in _CLASSES: _db_content[c] = {} def _create_object(table, obj): - """ Create an object in the db """ + """Create an object in the db.""" _db_content[table][obj.obj] = obj def _get_objects(type): - """ Get objects of the type """ + """Get objects of the type.""" lst_objs = [] for key in _db_content[type]: lst_objs.append(_db_content[type][key]) @@ -82,7 +82,7 @@ def _get_objects(type): class Prop(object): - """ Property Object base class """ + """Property Object base class.""" def __init__(self): self.name = None @@ -96,10 +96,10 @@ class Prop(object): class ManagedObject(object): - """ Managed Data Object base class """ + """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""" + """Sets the obj property which acts as a reference to the object.""" object.__setattr__(self, 'objName', name) if obj_ref is None: obj_ref = str(uuid.uuid4()) @@ -107,14 +107,18 @@ class ManagedObject(object): object.__setattr__(self, 'propSet', []) def set(self, attr, val): - """ Sets an attribute value. Not using the __setattr__ directly for we + """ + 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 """ + 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 """ + """ + 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): @@ -138,7 +142,7 @@ class ManagedObject(object): class DataObject(object): - """ Data object base class """ + """Data object base class.""" def __init__(self): pass @@ -151,30 +155,32 @@ class DataObject(object): class VirtualDisk(DataObject): - """ Virtual Disk class. Does nothing special except setting + """ + Virtual Disk class. Does nothing special except setting __class__.__name__ to 'VirtualDisk'. Refer place where __class__.__name__ - is used in the code """ + is used in the code. + """ def __init__(self): DataObject.__init__(self) class VirtualDiskFlatVer2BackingInfo(DataObject): - """ VirtualDiskFlatVer2BackingInfo class """ + """VirtualDiskFlatVer2BackingInfo class.""" def __init__(self): DataObject.__init__(self) class VirtualLsiLogicController(DataObject): - """ VirtualLsiLogicController class """ + """VirtualLsiLogicController class.""" def __init__(self): DataObject.__init__(self) class VirtualMachine(ManagedObject): - """ Virtual Machine class """ + """Virtual Machine class.""" def __init__(self, **kwargs): ManagedObject.__init__(self, "VirtualMachine") @@ -195,8 +201,10 @@ class VirtualMachine(ManagedObject): 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 """ + """ + 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 @@ -220,7 +228,7 @@ class VirtualMachine(ManagedObject): class Network(ManagedObject): - """ Network class """ + """Network class.""" def __init__(self): ManagedObject.__init__(self, "Network") @@ -228,7 +236,7 @@ class Network(ManagedObject): class ResourcePool(ManagedObject): - """ Resource Pool class """ + """Resource Pool class.""" def __init__(self): ManagedObject.__init__(self, "ResourcePool") @@ -236,7 +244,7 @@ class ResourcePool(ManagedObject): class Datastore(ManagedObject): - """ Datastore class """ + """Datastore class.""" def __init__(self): ManagedObject.__init__(self, "Datastore") @@ -245,7 +253,7 @@ class Datastore(ManagedObject): class HostNetworkSystem(ManagedObject): - """ HostNetworkSystem class """ + """HostNetworkSystem class.""" def __init__(self): ManagedObject.__init__(self, "HostNetworkSystem") @@ -261,7 +269,7 @@ class HostNetworkSystem(ManagedObject): class HostSystem(ManagedObject): - """ Host System class """ + """Host System class.""" def __init__(self): ManagedObject.__init__(self, "HostSystem") @@ -302,7 +310,7 @@ class HostSystem(ManagedObject): 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 """ + """Adds a port group to the host system object in the db.""" pg_name = spec.name vswitch_name = spec.vswitchName vlanid = spec.vlanId @@ -328,7 +336,7 @@ class HostSystem(ManagedObject): class Datacenter(ManagedObject): - """ Datacenter class """ + """Datacenter class.""" def __init__(self): ManagedObject.__init__(self, "Datacenter") @@ -343,7 +351,7 @@ class Datacenter(ManagedObject): class Task(ManagedObject): - """ Task class """ + """Task class.""" def __init__(self, task_name, state="running"): ManagedObject.__init__(self, "Task") @@ -390,12 +398,12 @@ def create_task(task_name, state="running"): def _add_file(file_path): - """ Adds a file reference to the db """ + """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 """ + """Removes a file reference from the db.""" if _db_content.get("files", None) is None: raise exception.NotFound(_("No files have been added yet")) #Check if the remove is for a single file object or for a folder @@ -415,7 +423,7 @@ def _remove_file(file_path): def fake_fetch_image(image, instance, **kwargs): - """Fakes fetch image call. Just adds a reference to the db for the file """ + """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 @@ -423,19 +431,19 @@ def fake_fetch_image(image, instance, **kwargs): def fake_upload_image(image, instance, **kwargs): - """Fakes the upload of an image """ + """Fakes the upload of an image.""" pass def fake_get_vmdk_size_and_properties(image_id, instance): - """ Fakes the file size and properties fetch for the image file """ + """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 """ + """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"): @@ -445,22 +453,24 @@ def _get_vm_mdo(vm_ref): class FakeFactory(object): - """ Fake factory class for the suds client """ + """Fake factory class for the suds client.""" def __init__(self): pass def create(self, obj_name): - """ Creates a namespace object """ + """Creates a namespace object.""" return DataObject() class FakeVim(object): - """Fake VIM Class""" + """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 """ + """ + 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() @@ -490,7 +500,7 @@ class FakeVim(object): return "Fake VIM Object" def _login(self): - """ Logs in and sets the session object in the db """ + """Logs in and sets the session object in the db.""" self._session = str(uuid.uuid4()) session = DataObject() session.key = self._session @@ -498,7 +508,7 @@ class FakeVim(object): return session def _logout(self): - """ Logs out and remove the session object ref from the db """ + """Logs out and remove the session object ref from the db.""" s = self._session self._session = None if s not in _db_content['session']: @@ -508,14 +518,14 @@ class FakeVim(object): del _db_content['session'][s] def _terminate_session(self, *args, **kwargs): - """ Terminates a session """ + """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 """ + """Checks if the session is active.""" if (self._session is None or self._session not in _db_content['session']): LOG.debug(_("Session is faulty")) @@ -524,7 +534,7 @@ class FakeVim(object): _("Session Invalid")) def _create_vm(self, method, *args, **kwargs): - """ Creates and registers a VM object with the Host System """ + """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, @@ -539,7 +549,7 @@ class FakeVim(object): return task_mdo.obj def _reconfig_vm(self, method, *args, **kwargs): - """ Reconfigures a VM and sets the properties supplied """ + """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")) @@ -547,7 +557,7 @@ class FakeVim(object): return task_mdo.obj def _create_copy_disk(self, method, vmdk_file_path): - """ Creates/copies a vmdk file object in the datastore """ + """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") @@ -557,12 +567,12 @@ class FakeVim(object): return task_mdo.obj def _snapshot_vm(self, method): - """ Snapshots a VM. Here we do nothing for faking sake """ + """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 """ + """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") @@ -572,23 +582,23 @@ class FakeVim(object): return task_mdo.obj def _delete_file(self, method, *args, **kwargs): - """ Deletes a file from the datastore """ + """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 """ + """Fakes a return.""" return def _unregister_vm(self, method, *args, **kwargs): - """ Unregisters a VM from the Host System """ + """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 """ + """Searches the datastore for a file.""" ds_path = kwargs.get("datastorePath") if _db_content.get("files", None) is None: raise exception.NotFound(_("No files have been added yet")) @@ -600,14 +610,14 @@ class FakeVim(object): return task_mdo.obj def _make_dir(self, method, *args, **kwargs): - """ Creates a directory in the datastore """ + """Creates a directory in the datastore.""" ds_path = kwargs.get("name") if _db_content.get("files", None) is None: raise exception.NotFound(_("No files have been added yet")) _db_content["files"].append(ds_path) def _set_power_state(self, method, vm_ref, pwr_state="poweredOn"): - """ Sets power state for the VM """ + """Sets power state for the VM.""" if _db_content.get("VirtualMachine", None) is None: raise exception.NotFound(_(" No Virtual Machine has been " "registered yet")) @@ -620,7 +630,7 @@ class FakeVim(object): return task_mdo.obj def _retrieve_properties(self, method, *args, **kwargs): - """ Retrieves properties based on the type """ + """Retrieves properties based on the type.""" spec_set = kwargs.get("specSet")[0] type = spec_set.propSet[0].type properties = spec_set.propSet[0].pathSet @@ -654,7 +664,7 @@ class FakeVim(object): return lst_ret_objs def _add_port_group(self, method, *args, **kwargs): - """ Adds a port group to the host system """ + """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")) diff --git a/nova/virt/vmwareapi/network_utils.py b/nova/virt/vmwareapi/network_utils.py index 36fa989968db..8d023d5803c7 100644 --- a/nova/virt/vmwareapi/network_utils.py +++ b/nova/virt/vmwareapi/network_utils.py @@ -16,7 +16,7 @@ # under the License. """ -Utility functions for ESX Networking +Utility functions for ESX Networking. """ from nova import exception @@ -32,8 +32,10 @@ class NetworkHelper: @classmethod def get_network_with_the_name(cls, session, network_name="vmnet0"): - """ Gets reference to the network whose name is passed as the - argument. """ + """ + 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 @@ -44,7 +46,7 @@ class NetworkHelper: return None vm_networks = vm_networks_ret.ManagedObjectReference networks = session._call_method(vim_util, - "get_properites_for_a_collection_of_objects", + "get_properties_for_a_collection_of_objects", "Network", vm_networks, ["summary.name"]) for network in networks: if network.propSet[0].val == network_name: @@ -53,8 +55,10 @@ class NetworkHelper: @classmethod def get_vswitch_for_vlan_interface(cls, session, vlan_interface): - """ Gets the vswitch associated with the physical - network adapter with the name supplied""" + """ + 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 @@ -77,7 +81,7 @@ class NetworkHelper: @classmethod def check_if_vlan_interface_exists(cls, session, vlan_interface): - """ Checks if the vlan_inteface exists on the esx host """ + """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, @@ -93,8 +97,8 @@ class NetworkHelper: return False @classmethod - def get_vlanid_and_vswicth_for_portgroup(cls, session, pg_name): - """ Get the vlan id and vswicth associated with the port group """ + def get_vlanid_and_vswitch_for_portgroup(cls, 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, @@ -113,8 +117,10 @@ class NetworkHelper: @classmethod def create_port_group(cls, 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 """ + """ + 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, diff --git a/nova/virt/vmwareapi/read_write_util.py b/nova/virt/vmwareapi/read_write_util.py index 37f80c133fc0..52ed6f9ac690 100644 --- a/nova/virt/vmwareapi/read_write_util.py +++ b/nova/virt/vmwareapi/read_write_util.py @@ -15,7 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. -""" Classes to handle image files +"""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. @@ -29,8 +29,6 @@ import urlparse from nova import flags from nova import log as logging -from nova import utils -from nova.auth.manager import AuthManager FLAGS = flags.FLAGS @@ -41,145 +39,34 @@ USER_AGENT = "OpenStack-ESX-Adapter" LOG = logging.getLogger("nova.virt.vmwareapi.read_write_util") -class ImageServiceFile: - """The base image service class""" - - def __init__(self, file_handle): - self.eof = False - self.file_handle = file_handle - - def write(self, data): - """Write data to the file""" - raise NotImplementedError - - def read(self, chunk_size=READ_CHUNKSIZE): - """Read a chunk of data from the file""" - raise NotImplementedError - - def get_size(self): - """Get the size of the file whose data is to be read""" - raise NotImplementedError - - def set_eof(self, eof): - """Set the end of file marker""" - self.eof = eof - - def get_eof(self): - """Check if the file end has been reached or not""" - return self.eof - - def close(self): - """Close the file handle""" - try: - self.file_handle.close() - except Exception: - pass - - def get_image_properties(self): - """Get the image properties""" - raise NotImplementedError - - def __del__(self): - """Close the file handle on garbage collection""" - self.close() - - -class GlanceHTTPWriteFile(ImageServiceFile): - """Glance file write handler class""" - - def __init__(self, host, port, image_id, file_size, os_type, adapter_type, - version=1, scheme="http"): - base_url = "%s://%s:%s/images/%s" % (scheme, host, port, image_id) - (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) - conn.putheader("User-Agent", USER_AGENT) - conn.putheader("Content-Length", file_size) - conn.putheader("Content-Type", "application/octet-stream") - conn.putheader("x-image-meta-store", "file") - conn.putheader("x-image-meta-is_public", "True") - conn.putheader("x-image-meta-type", "raw") - conn.putheader("x-image-meta-size", file_size) - conn.putheader("x-image-meta-property-kernel_id", "") - conn.putheader("x-image-meta-property-ramdisk_id", "") - conn.putheader("x-image-meta-property-vmware_ostype", os_type) - conn.putheader("x-image-meta-property-vmware_adaptertype", - adapter_type) - conn.putheader("x-image-meta-property-vmware_image_version", version) - conn.endheaders() - ImageServiceFile.__init__(self, conn) - - def write(self, data): - """Write data to the file""" - self.file_handle.send(data) - - -class GlanceHTTPReadFile(ImageServiceFile): - """Glance file read handler class""" - - def __init__(self, host, port, image_id, scheme="http"): - base_url = "%s://%s:%s/images/%s" % (scheme, host, port, - urllib.pathname2url(image_id)) - headers = {'User-Agent': USER_AGENT} - request = urllib2.Request(base_url, None, headers) - conn = urllib2.urlopen(request) - ImageServiceFile.__init__(self, conn) - - def read(self, chunk_size=READ_CHUNKSIZE): - """Read a chunk of data""" - return self.file_handle.read(chunk_size) - - def get_size(self): - """Get the size of the file to be read""" - return self.file_handle.headers.get("X-Image-Meta-Size", -1) - - def get_image_properties(self): - """Get the image properties like say OS Type and the - Adapter Type - """ - return {"vmware_ostype": - self.file_handle.headers.get( - "X-Image-Meta-Property-Vmware_ostype"), - "vmware_adaptertype": - self.file_handle.headers.get( - "X-Image-Meta-Property-Vmware_adaptertype"), - "vmware_image_version": - self.file_handle.headers.get( - "X-Image-Meta-Property-Vmware_image_version")} - - class VMwareHTTPFile(object): - """Base class for HTTP file""" + """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""" + """Set the end of file marker.""" self.eof = eof def get_eof(self): - """Check if the end of file has been reached""" + """Check if the end of file has been reached.""" return self.eof def close(self): - """Close the file handle""" + """Close the file handle.""" try: self.file_handle.close() except Exception: pass def __del__(self): - """Close the file handle on garbage collection""" + """Close the file handle on garbage collection.""" self.close() def _build_vim_cookie_headers(self, vim_cookies): - """Build ESX host session cookie headers""" + """Build ESX host session cookie headers.""" cookie_header = "" for vim_cookie in vim_cookies: cookie_header = vim_cookie.name + "=" + vim_cookie.value @@ -187,20 +74,20 @@ class VMwareHTTPFile(object): return cookie_header def write(self, data): - """Write data to the file""" + """Write data to the file.""" raise NotImplementedError def read(self, chunk_size=READ_CHUNKSIZE): - """Read a chunk of data""" + """Read a chunk of data.""" raise NotImplementedError def get_size(self): - """Get size of the file to be read""" + """Get size of the file to be read.""" raise NotImplementedError class VMWareHTTPWriteFile(VMwareHTTPFile): - """VMWare file write handler class""" + """VMWare file write handler class.""" def __init__(self, host, data_center_name, datastore_name, cookies, file_path, file_size, scheme="https"): @@ -222,11 +109,11 @@ class VMWareHTTPWriteFile(VMwareHTTPFile): VMwareHTTPFile.__init__(self, conn) def write(self, data): - """Write to the file""" + """Write to the file.""" self.file_handle.send(data) def close(self): - """Get the response and close the connection""" + """Get the response and close the connection.""" try: self.conn.getresponse() except Exception, excep: @@ -236,7 +123,7 @@ class VMWareHTTPWriteFile(VMwareHTTPFile): class VmWareHTTPReadFile(VMwareHTTPFile): - """VMWare file read handler class""" + """VMWare file read handler class.""" def __init__(self, host, data_center_name, datastore_name, cookies, file_path, scheme="https"): @@ -251,9 +138,9 @@ class VmWareHTTPReadFile(VMwareHTTPFile): VMwareHTTPFile.__init__(self, conn) def read(self, chunk_size=READ_CHUNKSIZE): - """Read a chunk of data""" + """Read a chunk of data.""" return self.file_handle.read(chunk_size) def get_size(self): - """Get size of the file to be read""" + """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 cea65e1984fa..3430822e1001 100644 --- a/nova/virt/vmwareapi/vim.py +++ b/nova/virt/vmwareapi/vim.py @@ -16,7 +16,7 @@ # under the License. """ -Classes for making VMware VI SOAP calls +Classes for making VMware VI SOAP calls. """ import httplib @@ -37,49 +37,50 @@ FLAGS = flags.FLAGS flags.DEFINE_string('vmwareapi_wsdl_loc', None, 'VIM Service WSDL Location' - 'E.g http:///vimService.wsdl' + 'e.g http:///vimService.wsdl' 'Due to a bug in vSphere ESX 4.1 default wsdl' - 'Read the readme for vmware to setup') + 'Refer readme-vmware to setup') class VIMMessagePlugin(MessagePlugin): def addAttributeForValue(self, node): - #suds does not handle AnyType properly - #VI SDK requires type attribute to be set when AnyType is used + # 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. + """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 + 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 as opposed to test + # 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. as opposed to test context.envelope.prune() context.envelope.walk(self.addAttributeForValue) class Vim: - """The VIM Object""" + """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] - Creates the necessary Communication interfaces, Gets the - ServiceContent for initiating SOAP transactions """ 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")) - #Use this when VMware fixes their faulty wsdl + # 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) @@ -89,37 +90,41 @@ class Vim: self.RetrieveServiceContent("ServiceInstance") def get_service_content(self): - """Gets the service content object""" + """Gets the service content object.""" return self._service_content def __getattr__(self, attr_name): - """Makes the API calls and gets the result""" + """Makes the API calls and gets the result.""" try: return object.__getattr__(self, attr_name) except AttributeError: def vim_request_handler(managed_object, **kwargs): - """managed_object : Managed Object Reference or Managed - Object Name - **kw : Keyword arguments of the call """ - #Dynamic handler for VI SDK Calls + 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 + # 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 + # Catch the VimFaultException that is raised by the fault + # check of the SOAP response except error_util.VimFaultException, excep: raise except WebFault, excep: @@ -155,8 +160,8 @@ class Vim: return vim_request_handler def _request_managed_object_builder(self, managed_object): - """Builds the request managed object""" - #Request Managed Object Builder + """Builds the request managed object.""" + # Request Managed Object Builder if type(managed_object) == type(""): mo = Property(managed_object) mo._type = managed_object diff --git a/nova/virt/vmwareapi/vim_util.py b/nova/virt/vmwareapi/vim_util.py index 20117b04c35d..709b54e12bb4 100644 --- a/nova/virt/vmwareapi/vim_util.py +++ b/nova/virt/vmwareapi/vim_util.py @@ -16,19 +16,19 @@ # under the License. """ -The VMware API utility module +The VMware API utility module. """ -def build_selcetion_spec(client_factory, name): - """ Builds the selection spec """ +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, type, path, skip, select_set): - """ Builds the traversal spec object """ + """Builds the traversal spec object.""" traversal_spec = client_factory.create('ns0:TraversalSpec') traversal_spec.name = name traversal_spec.type = type @@ -39,9 +39,11 @@ def build_traversal_spec(client_factory, name, type, path, skip, select_set): def build_recursive_traversal_spec(client_factory): - """ Builds the Recursive Traversal Spec to traverse the object managed - object hierarchy """ - visit_folders_select_spec = build_selcetion_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 datacnetr dc_to_hf = build_traversal_spec(client_factory, "dc_to_hf", "Datacenter", @@ -64,8 +66,8 @@ def build_recursive_traversal_spec(client_factory): cr_to_ds = build_traversal_spec(client_factory, "cr_to_ds", "ComputeResource", "datastore", False, []) - rp_to_rp_select_spec = build_selcetion_spec(client_factory, "rp_to_rp") - rp_to_vm_select_spec = build_selcetion_spec(client_factory, "rp_to_vm") + 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, @@ -94,7 +96,7 @@ def build_recursive_traversal_spec(client_factory): def build_property_spec(client_factory, type="VirtualMachine", properties_to_collect=["name"], all_properties=False): - """Builds the Property Spec""" + """Builds the Property Spec.""" property_spec = client_factory.create('ns0:PropertySpec') property_spec.all = all_properties property_spec.pathSet = properties_to_collect @@ -103,7 +105,7 @@ def build_property_spec(client_factory, type="VirtualMachine", def build_object_spec(client_factory, root_folder, traversal_specs): - """Builds the object Spec""" + """Builds the object Spec.""" object_spec = client_factory.create('ns0:ObjectSpec') object_spec.obj = root_folder object_spec.skip = False @@ -112,7 +114,7 @@ def build_object_spec(client_factory, root_folder, traversal_specs): def build_property_filter_spec(client_factory, property_specs, object_specs): - """Builds the Property Filter Spec""" + """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 @@ -120,7 +122,7 @@ def build_property_filter_spec(client_factory, property_specs, object_specs): def get_object_properties(vim, collector, mobj, type, properties): - """Gets the properties of the Managed object specified""" + """Gets the properties of the Managed object specified.""" client_factory = vim.client.factory if mobj is None: return None @@ -141,7 +143,7 @@ def get_object_properties(vim, collector, mobj, type, properties): def get_dynamic_property(vim, mobj, type, property_name): - """Gets a particular property of the Managed Object""" + """Gets a particular property of the Managed Object.""" obj_content = \ get_object_properties(vim, None, mobj, type, [property_name]) property_value = None @@ -153,7 +155,7 @@ def get_dynamic_property(vim, mobj, type, property_name): def get_objects(vim, type, properties_to_collect=["name"], all=False): - """Gets the list of objects of the type specified""" + """Gets the list of objects of the type specified.""" client_factory = vim.client.factory object_spec = build_object_spec(client_factory, vim.get_service_content().rootFolder, @@ -169,7 +171,7 @@ def get_objects(vim, type, properties_to_collect=["name"], all=False): def get_prop_spec(client_factory, type, properties): - """Builds the Property Spec Object""" + """Builds the Property Spec Object.""" prop_spec = client_factory.create('ns0:PropertySpec') prop_spec.type = type prop_spec.pathSet = properties @@ -177,7 +179,7 @@ def get_prop_spec(client_factory, type, properties): def get_obj_spec(client_factory, obj, select_set=None): - """Builds the Object Spec object""" + """Builds the Object Spec object.""" obj_spec = client_factory.create('ns0:ObjectSpec') obj_spec.obj = obj obj_spec.skip = False @@ -187,7 +189,7 @@ def get_obj_spec(client_factory, obj, select_set=None): def get_prop_filter_spec(client_factory, obj_spec, prop_spec): - """Builds the Property Filter Spec Object""" + """Builds the Property Filter Spec Object.""" prop_filter_spec = \ client_factory.create('ns0:PropertyFilterSpec') prop_filter_spec.propSet = prop_spec @@ -195,10 +197,11 @@ def get_prop_filter_spec(client_factory, obj_spec, prop_spec): return prop_filter_spec -def get_properites_for_a_collection_of_objects(vim, type, +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 + """ + Gets the list of properties for the collection of + objects of the type specified. """ client_factory = vim.client.factory if len(obj_list) == 0: diff --git a/nova/virt/vmwareapi/vm_util.py b/nova/virt/vmwareapi/vm_util.py index a46b4d10c90b..f2ef8d2d7798 100644 --- a/nova/virt/vmwareapi/vm_util.py +++ b/nova/virt/vmwareapi/vm_util.py @@ -15,18 +15,19 @@ # License for the specific language governing permissions and limitations # under the License. """ -The VMware API VM utility module to build SOAP object specs +The VMware API VM utility module to build SOAP object specs. """ def build_datastore_path(datastore_name, path): - """Build the datastore compliant 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 + """ + Split the VMWare style datastore path to get the Datastore + name and the entity path. """ spl = datastore_path.split('[', 1)[1].split(']', 1) path = "" @@ -40,7 +41,7 @@ def split_datastore_path(datastore_path): def get_vm_create_spec(client_factory, instance, data_store_name, network_name="vmnet0", os_type="otherGuest"): - """Builds the VM Create spec""" + """Builds the VM Create spec.""" config_spec = client_factory.create('ns0:VirtualMachineConfigSpec') config_spec.name = instance.name config_spec.guestId = os_type @@ -70,11 +71,12 @@ def get_vm_create_spec(client_factory, instance, data_store_name, 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 + 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" @@ -88,13 +90,15 @@ def create_controller_spec(client_factory, key): def create_network_spec(client_factory, network_name, mac_address): - """Builds a config spec for the addition of a new network - adapter to the VM""" + """ + 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 + # Get the recommended card type for the VM based on the guest OS of the VM net_device = client_factory.create('ns0:VirtualPCNet32') backing = \ @@ -110,9 +114,9 @@ def create_network_spec(client_factory, network_name, mac_address): 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 + # 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 @@ -124,14 +128,14 @@ def create_network_spec(client_factory, network_name, mac_address): def get_vmdk_attach_config_spec(client_factory, disksize, file_path, adapter_type="lsiLogic"): - """Builds the vmdk attach config spec""" + """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 + # 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 + # 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: @@ -149,7 +153,7 @@ def get_vmdk_attach_config_spec(client_factory, def get_vmdk_file_path_and_adapter_type(client_factory, hardware_devices): - """Gets the vmdk file path and the storage adapter type""" + """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 @@ -177,7 +181,7 @@ def get_vmdk_file_path_and_adapter_type(client_factory, hardware_devices): def get_copy_virtual_disk_spec(client_factory, adapter_type="lsilogic"): - """Builds the Virtual Disk copy spec""" + """Builds the Virtual Disk copy spec.""" dest_spec = client_factory.create('ns0:VirtualDiskSpec') dest_spec.adapterType = adapter_type dest_spec.diskType = "thick" @@ -185,7 +189,7 @@ def get_copy_virtual_disk_spec(client_factory, adapter_type="lsilogic"): def get_vmdk_create_spec(client_factory, size_in_kb, adapter_type="lsiLogic"): - """Builds the virtual disk create spec""" + """Builds the virtual disk create spec.""" create_vmdk_spec = \ client_factory.create('ns0:FileBackedVirtualDiskSpec') create_vmdk_spec.adapterType = adapter_type @@ -196,8 +200,10 @@ def get_vmdk_create_spec(client_factory, size_in_kb, adapter_type="lsiLogic"): def create_virtual_disk_spec(client_factory, disksize, controller_key, file_path=None): - """Creates a Spec for the addition/attaching of a - Virtual Disk to the VM""" + """ + 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" @@ -223,9 +229,9 @@ def create_virtual_disk_spec(client_factory, virtual_disk.backing = disk_file_backing virtual_disk.connectable = connectable_spec - #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 + # 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 @@ -237,7 +243,7 @@ def create_virtual_disk_spec(client_factory, def get_dummy_vm_create_spec(client_factory, name, data_store_name): - """Builds the dummy VM create spec""" + """Builds the dummy VM create spec.""" config_spec = client_factory.create('ns0:VirtualMachineConfigSpec') config_spec.name = name @@ -269,7 +275,7 @@ def get_dummy_vm_create_spec(client_factory, name, data_store_name): def get_machine_id_change_spec(client_factory, mac, ip_addr, netmask, gateway): - """Builds the machine id change config spec""" + """Builds the machine id change config spec.""" machine_id_str = "%s;%s;%s;%s" % (mac, ip_addr, netmask, gateway) virtual_machine_config_spec = \ client_factory.create('ns0:VirtualMachineConfigSpec') @@ -283,12 +289,12 @@ def get_machine_id_change_spec(client_factory, mac, ip_addr, netmask, gateway): def get_add_vswitch_port_group_spec(client_factory, vswitch_name, port_group_name, vlan_id): - """Builds the virtual switch port group add spec""" + """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. + # 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') diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index 2d87a627d741..4b3c8adcade6 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -47,14 +47,14 @@ VMWARE_POWER_STATES = { class VMWareVMOps(object): - """ Management class for VM-related tasks """ + """Management class for VM-related tasks.""" def __init__(self, session): - """ Initializer """ + """Initializer.""" self._session = session def _wait_with_callback(self, instance_id, task, callback): - """ Waits for the task to finish and does a callback after """ + """Waits for the task to finish and does a callback after.""" ret = None try: ret = self._session._wait_for_task(instance_id, task) @@ -63,7 +63,7 @@ class VMWareVMOps(object): callback(ret) def list_instances(self): - """ Lists the VM instances that are registered with the ESX host """ + """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", @@ -96,7 +96,7 @@ class VMWareVMOps(object): 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 + 6. Power on the VM. """ vm_ref = self._get_vm_ref_from_the_name(instance.name) if vm_ref: @@ -122,7 +122,7 @@ class VMWareVMOps(object): _check_if_network_bridge_exists() def _get_datastore_ref(): - # Get the datastore list and choose the first local storage + """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: @@ -133,7 +133,7 @@ class VMWareVMOps(object): ds_type = prop.val elif prop.name == "summary.name": ds_name = prop.val - #Local storage identifier + # Local storage identifier if ds_type == "VMFS": data_store_name = ds_name return data_store_name @@ -146,8 +146,10 @@ class VMWareVMOps(object): 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. + """ + 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( instance.image_id, instance) @@ -160,28 +162,29 @@ class VMWareVMOps(object): 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 + """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 + # 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. + # 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() - #Get the create vm config spec + # Get the create vm config spec config_spec = vm_util.get_vm_create_spec(client_factory, instance, data_store_name, net_name, 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 + # Create the VM on the ESX host vm_create_task = self._session._call_method( self._session._get_vim(), "CreateVM_Task", vm_folder_mor, @@ -196,11 +199,11 @@ class VMWareVMOps(object): # Set the machine id for the VM for setting the IP self._set_machine_id(client_factory, instance) - #Naming the VM files in correspondence with the VM instance name + # 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 + # 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) @@ -208,12 +211,13 @@ class VMWareVMOps(object): uploaded_vmdk_name) def _create_virtual_disk(): - #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 + """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" @@ -245,7 +249,7 @@ class VMWareVMOps(object): "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. + # Delete the -flat.vmdk file created. .vmdk file is retained. vmdk_delete_task = self._session._call_method( self._session._get_vim(), "DeleteDatastoreFile_Task", @@ -262,12 +266,13 @@ class VMWareVMOps(object): 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_id)s to the ESX " "data store %(data_store_name)s") % ({'image_id': instance.image_id, 'data_store_name': data_store_name})) - #Upload the -flat.vmdk file whose meta-data file we just created - #above + # Upload the -flat.vmdk file whose meta-data file we just created + # above vmware_images.fetch_image( instance.image_id, instance, @@ -285,8 +290,10 @@ class VMWareVMOps(object): 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. + """ + 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, @@ -304,8 +311,9 @@ class VMWareVMOps(object): _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 the VM power_on_task = self._session._call_method( self._session._get_vim(), "PowerOnVM_Task", vm_ref) @@ -325,7 +333,7 @@ class VMWareVMOps(object): 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 + 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: @@ -336,7 +344,7 @@ class VMWareVMOps(object): 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 + # 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") @@ -355,7 +363,7 @@ class VMWareVMOps(object): os_type = _get_vm_and_vmdk_attribs() def _create_vm_snapshot(): - #Create a snapshot of the VM + # Create a snapshot of the VM LOG.debug(_("Creating Snapshot of the VM instance %s ") % instance.name) snapshot_task = self._session._call_method( @@ -372,8 +380,8 @@ class VMWareVMOps(object): _create_vm_snapshot() def _check_if_tmp_folder_exists(): - #Copy the contents of the VM that were there just before the - #snapshot was taken + # 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, @@ -388,7 +396,7 @@ class VMWareVMOps(object): ds_ref, "Datastore", "browser") - #Check if the vmware-tmp folder exists or not. If not, create one + # 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): @@ -397,17 +405,17 @@ class VMWareVMOps(object): _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. + # 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 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 " @@ -431,7 +439,7 @@ class VMWareVMOps(object): 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. + # Upload the contents of -flat.vmdk file which has the disk data. LOG.debug(_("Uploading image %s") % snapshot_name) vmware_images.upload_image( snapshot_name, @@ -449,7 +457,11 @@ class VMWareVMOps(object): _upload_vmdk_to_image_repository() def _clean_temp_data(): - #Delete the temporary vmdk created above. + """ + 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( @@ -465,7 +477,7 @@ class VMWareVMOps(object): _clean_temp_data() def reboot(self, instance): - """ Reboot a VM instance """ + """Reboot a VM instance.""" vm_ref = self._get_vm_ref_from_the_name(instance.name) if vm_ref is None: raise exception.NotFound(_("instance - %s not present") % @@ -483,13 +495,13 @@ class VMWareVMOps(object): elif prop.name == "summary.guest.toolsStatus": tools_status = prop.val - #Raise an exception if the VM is not powered On. + # Raise an exception if the VM is not powered On. if pwr_state not in ["poweredOn"]: raise exception.Invalid(_("instance - %s not poweredOn. So can't " "be rebooted.") % instance.name) - #If vmware tools are installed in the VM, then do a guest reboot. - #Otherwise do a hard reset. + # If vmware tools are installed in the VM, then do a guest reboot. + # Otherwise do a hard reset. if tools_status not in ['toolsNotInstalled', 'toolsNotRunning']: LOG.debug(_("Rebooting guest OS of VM %s") % instance.name) self._session._call_method(self._session._get_vim(), "RebootGuest", @@ -507,7 +519,7 @@ class VMWareVMOps(object): 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 + 3. Delete the contents of the folder holding the VM related data. """ try: vm_ref = self._get_vm_ref_from_the_name(instance.name) @@ -529,7 +541,7 @@ class VMWareVMOps(object): 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. + # 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( @@ -538,7 +550,7 @@ class VMWareVMOps(object): self._session._wait_for_task(instance.id, poweroff_task) LOG.debug(_("Powered off the VM %s") % instance.name) - #Un-register the VM + # Un-register the VM try: LOG.debug(_("Unregistering the VM %s") % instance.name) self._session._call_method(self._session._get_vim(), @@ -548,7 +560,8 @@ class VMWareVMOps(object): LOG.warn(_("In vmwareapi:vmops:destroy, got this exception" " while un-registering the VM: %s") % str(excep)) - #Delete the folder holding the VM related content on the datastore. + # Delete the folder holding the VM related content on + # the datastore. try: dir_ds_compliant_path = vm_util.build_datastore_path( datastore_name, @@ -564,7 +577,7 @@ class VMWareVMOps(object): name=dir_ds_compliant_path) self._session._wait_for_task(instance.id, delete_task) LOG.debug(_("Deleted contents of the VM %(name)s from " - "datastore %(datastore_name)s") + "datastore %(datastore_name)s") % ({'name': instance.name, 'datastore_name': datastore_name})) except Exception, excep: @@ -576,15 +589,15 @@ class VMWareVMOps(object): LOG.exception(e) def pause(self, instance, callback): - """ Pause a VM instance """ + """Pause a VM instance.""" raise exception.APIError("pause not supported for vmwareapi") def unpause(self, instance, callback): - """ Un-Pause a VM instance """ + """Un-Pause a VM instance.""" raise exception.APIError("unpause not supported for vmwareapi") def suspend(self, instance, callback): - """ Suspend the specified instance """ + """Suspend the specified instance.""" vm_ref = self._get_vm_ref_from_the_name(instance.name) if vm_ref is None: raise exception.NotFound(_("instance - %s not present") % @@ -593,14 +606,14 @@ class VMWareVMOps(object): pwr_state = self._session._call_method(vim_util, "get_dynamic_property", vm_ref, "VirtualMachine", "runtime.powerState") - #Only PoweredOn VMs can be suspended. + # 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._wait_with_callback(instance.id, suspend_task, callback) LOG.debug(_("Suspended the VM %s ") % instance.name) - #Raise Exception if VM is poweredOff + # Raise Exception if VM is poweredOff elif pwr_state == "poweredOff": raise exception.Invalid(_("instance - %s is poweredOff and hence " " can't be suspended.") % instance.name) @@ -608,7 +621,7 @@ class VMWareVMOps(object): "without doing anything") % instance.name) def resume(self, instance, callback): - """ Resume the specified instance """ + """Resume the specified instance.""" vm_ref = self._get_vm_ref_from_the_name(instance.name) if vm_ref is None: raise exception.NotFound(_("instance - %s not present") % @@ -629,7 +642,7 @@ class VMWareVMOps(object): "and hence can't be Resumed.") % instance.name) def get_info(self, instance_name): - """ Return data about the VM instance """ + """Return data about the VM instance.""" vm_ref = self._get_vm_ref_from_the_name(instance_name) if vm_ref is None: raise exception.NotFound(_("instance - %s not present") % @@ -661,12 +674,12 @@ class VMWareVMOps(object): 'cpu_time': 0} def get_diagnostics(self, instance): - """ Return data about VM diagnostics """ + """Return data about VM diagnostics.""" raise exception.APIError("get_diagnostics not implemented for " "vmwareapi") def get_console_output(self, instance): - """ Return snapshot of console """ + """Return snapshot of console.""" vm_ref = self._get_vm_ref_from_the_name(instance.name) if vm_ref is None: raise exception.NotFound(_("instance - %s not present") % @@ -688,12 +701,14 @@ class VMWareVMOps(object): return "" def get_ajax_console(self, instance): - """ Return link to instance's ajax console """ + """Return link to instance's ajax console.""" return 'http://fakeajaxconsole/fake_url' def _set_machine_id(self, client_factory, instance): - """ Set the machine id of the VM for guest tools to pick up and change - the IP """ + """ + Set the machine id of the VM for guest tools to pick up and change + the IP. + """ vm_ref = self._get_vm_ref_from_the_name(instance.name) if vm_ref is None: raise exception.NotFound(_("instance - %s not present") % @@ -722,19 +737,19 @@ class VMWareVMOps(object): 'ip_addr': ip_addr})) def _get_datacenter_name_and_ref(self): - """ Get the datacenter name and the reference. """ + """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""" + """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. + # 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", @@ -748,9 +763,11 @@ class VMWareVMOps(object): 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 formed at the topmost level of the - DataStore. """ + """ + 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, @@ -758,7 +775,7 @@ class VMWareVMOps(object): 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. """ + """Get reference to the VM with the name specified.""" vms = self._session._call_method(vim_util, "get_objects", "VirtualMachine", ["name"]) for vm in vms: diff --git a/nova/virt/vmwareapi/vmware_images.py b/nova/virt/vmwareapi/vmware_images.py index 2b389987ebb2..d9c7f52e573b 100644 --- a/nova/virt/vmwareapi/vmware_images.py +++ b/nova/virt/vmwareapi/vmware_images.py @@ -15,15 +15,14 @@ # License for the specific language governing permissions and limitations # under the License. """ -Utility functions for Image transfer +Utility functions for Image transfer. """ -import time +import glance.client from nova import exception from nova import flags from nova import log as logging -from nova.virt.vmwareapi import io_util from nova.virt.vmwareapi import read_write_util FLAGS = flags.FLAGS @@ -35,44 +34,9 @@ WRITE_CHUNKSIZE = 2 * 1024 * 1024 LOG = logging.getLogger("nova.virt.vmwareapi.vmware_images") -def start_transfer(read_file_handle, write_file_handle, data_size): - """ Start the data transfer from the read handle to the write handle. """ - - #The thread safe pipe - thread_safe_pipe = io_util.ThreadSafePipe(QUEUE_BUFFER_SIZE) - #The read thread - read_thread = io_util.IOThread(read_file_handle, thread_safe_pipe, - READ_CHUNKSIZE, long(data_size)) - #The write thread - write_thread = io_util.IOThread(thread_safe_pipe, write_file_handle, - WRITE_CHUNKSIZE, long(data_size)) - read_thread.start() - write_thread.start() - LOG.debug(_("Starting image file transfer")) - #Wait till both the read thread and the write thread are done - while not (read_thread.is_done() and write_thread.is_done()): - if read_thread.get_error() or write_thread.get_error(): - read_thread.stop_io_transfer() - write_thread.stop_io_transfer() - # If there was an exception in reading or writing, raise the same. - read_excep = read_thread.get_exception() - write_excep = write_thread.get_exception() - if read_excep is not None: - LOG.exception(str(read_excep)) - raise exception.Error(read_excep) - if write_excep is not None: - LOG.exception(str(write_excep)) - raise exception.Error(write_excep) - time.sleep(2) - LOG.debug(_("Finished image file transfer and closing the file handles")) - #Close the file handles - read_file_handle.close() - write_file_handle.close() - - def fetch_image(image, instance, **kwargs): - """ Fetch an image for attaching to the newly created VM """ - #Depending upon the image service, make appropriate image service call + """Fetch an image for attaching to the newly created VM.""" + # Depending upon the image service, make appropriate image service call if FLAGS.image_service == "nova.image.glance.GlanceImageService": func = _get_glance_image elif FLAGS.image_service == "nova.image.s3.S3ImageService": @@ -86,8 +50,8 @@ def fetch_image(image, instance, **kwargs): def upload_image(image, instance, **kwargs): - """ Upload the newly snapshotted VM disk file. """ - #Depending upon the image service, make appropriate image service call + """Upload the newly snapshotted VM disk file.""" + # Depending upon the image service, make appropriate image service call if FLAGS.image_service == "nova.image.glance.GlanceImageService": func = _put_glance_image elif FLAGS.image_service == "nova.image.s3.S3ImageService": @@ -101,12 +65,11 @@ def upload_image(image, instance, **kwargs): def _get_glance_image(image, instance, **kwargs): - """ Download image from the glance image server. """ + """Download image from the glance image server.""" LOG.debug(_("Downloading image %s from glance image server") % image) - read_file_handle = read_write_util.GlanceHTTPReadFile(FLAGS.glance_host, - FLAGS.glance_port, - image) - file_size = read_file_handle.get_size() + glance_client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) + metadata, read_file_handle = glance_client.get_image(image) + file_size = int(metadata['size']) write_file_handle = read_write_util.VMWareHTTPWriteFile( kwargs.get("host"), kwargs.get("data_center_name"), @@ -114,22 +77,23 @@ def _get_glance_image(image, instance, **kwargs): kwargs.get("cookies"), kwargs.get("file_path"), file_size) - start_transfer(read_file_handle, write_file_handle, file_size) + for chunk in read_file_handle: + write_file_handle.write(chunk) LOG.debug(_("Downloaded image %s from glance image server") % image) def _get_s3_image(image, instance, **kwargs): - """ Download image from the S3 image server. """ + """Download image from the S3 image server.""" raise NotImplementedError def _get_local_image(image, instance, **kwargs): - """ Download image from the local nova compute node. """ + """Download image from the local nova compute node.""" raise NotImplementedError def _put_glance_image(image, instance, **kwargs): - """ Upload the snapshotted vm disk file to Glance image server """ + """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"), @@ -137,47 +101,48 @@ def _put_glance_image(image, instance, **kwargs): kwargs.get("datastore_name"), kwargs.get("cookies"), kwargs.get("file_path")) - file_size = read_file_handle.get_size() - write_file_handle = read_write_util.GlanceHTTPWriteFile( - FLAGS.glance_host, - FLAGS.glance_port, - image, - file_size, - kwargs.get("os_type"), - kwargs.get("adapter_type"), - kwargs.get("image_version")) - start_transfer(read_file_handle, write_file_handle, file_size) + glance_client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) + 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")}} + glance_client.update_image(image, image_meta=image_metadata, + image_data=read_file_handle) LOG.debug(_("Uploaded image %s to the Glance image server") % image) def _put_local_image(image, instance, **kwargs): - """ Upload the snapshotted vm disk file to the local nova compute node. """ + """Upload the snapshotted vm disk file to the local nova compute node.""" raise NotImplementedError def _put_s3_image(image, instance, **kwargs): - """ Upload the snapshotted vm disk file to S3 image server. """ + """Upload the snapshotted vm disk file to S3 image server.""" raise NotImplementedError def get_vmdk_size_and_properties(image, instance): - """ Get size of the vmdk file that is to be downloaded for attach in spawn. + """ + 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.""" + geometry of the disk created depends on the size. + """ LOG.debug(_("Getting image size for the image %s") % image) if FLAGS.image_service == "nova.image.glance.GlanceImageService": - read_file_handle = read_write_util.GlanceHTTPReadFile( - FLAGS.glance_host, - FLAGS.glance_port, - image) + glance_client = glance.client.Client(FLAGS.glance_host, + FLAGS.glance_port) + meta_data = glance_client.get_image_meta(image) + size, properties = meta_data["size"], meta_data["properties"] elif FLAGS.image_service == "nova.image.s3.S3ImageService": raise NotImplementedError elif FLAGS.image_service == "nova.image.local.LocalImageService": raise NotImplementedError - size = read_file_handle.get_size() - properties = read_file_handle.get_image_properties() - read_file_handle.close() LOG.debug(_("Got image size of %(size)s for the image %(image)s") % locals()) return size, properties diff --git a/nova/virt/vmwareapi_conn.py b/nova/virt/vmwareapi_conn.py index 92cd83ed1c02..bb10c604376c 100644 --- a/nova/virt/vmwareapi_conn.py +++ b/nova/virt/vmwareapi_conn.py @@ -29,6 +29,7 @@ A connection to the VMware ESX platform. :vmwareapi_api_retry_count: The API retry count in case of failure such as network failures (socket errors etc.) (default: 10). + """ import time @@ -78,7 +79,7 @@ TIME_BETWEEN_API_CALL_RETRIES = 2.0 class Failure(Exception): - """Base Exception class for handling task failures""" + """Base Exception class for handling task failures.""" def __init__(self, details): self.details = details @@ -103,7 +104,7 @@ def get_connection(_): class VMWareESXConnection(object): - """The ESX host connection object""" + """The ESX host connection object.""" def __init__(self, host_ip, host_username, host_password, api_retry_count, scheme="https"): @@ -112,80 +113,85 @@ class VMWareESXConnection(object): self._vmops = VMWareVMOps(session) def init_host(self, host): - """Do the initialization that needs to be done""" - #FIXME(sateesh): implement this + """Do the initialization that needs to be done.""" + # FIXME(sateesh): implement this pass def list_instances(self): - """List VM instances""" + """List VM instances.""" return self._vmops.list_instances() def spawn(self, instance): - """Create VM instance""" + """Create VM instance.""" self._vmops.spawn(instance) def snapshot(self, instance, name): - """Create snapshot from a running VM instance""" + """Create snapshot from a running VM instance.""" self._vmops.snapshot(instance, name) def reboot(self, instance): - """Reboot VM instance""" + """Reboot VM instance.""" self._vmops.reboot(instance) def destroy(self, instance): - """Destroy VM instance""" + """Destroy VM instance.""" self._vmops.destroy(instance) def pause(self, instance, callback): - """Pause VM instance""" + """Pause VM instance.""" self._vmops.pause(instance, callback) def unpause(self, instance, callback): - """Unpause paused VM instance""" + """Unpause paused VM instance.""" self._vmops.unpause(instance, callback) def suspend(self, instance, callback): - """Suspend the specified instance""" + """Suspend the specified instance.""" self._vmops.suspend(instance, callback) def resume(self, instance, callback): - """Resume the suspended VM instance""" + """Resume the suspended VM instance.""" self._vmops.resume(instance, callback) def get_info(self, instance_id): - """Return info about the VM instance""" + """Return info about the VM instance.""" return self._vmops.get_info(instance_id) def get_diagnostics(self, instance): - """Return data about VM diagnostics""" + """Return data about VM diagnostics.""" return self._vmops.get_info(instance) def get_console_output(self, instance): - """Return snapshot of console""" + """Return snapshot of console.""" return self._vmops.get_console_output(instance) def get_ajax_console(self, instance): - """Return link to instance's ajax console""" + """Return link to instance's ajax console.""" return self._vmops.get_ajax_console(instance) def attach_volume(self, instance_name, device_path, mountpoint): - """Attach volume storage to VM instance""" + """Attach volume storage to VM instance.""" pass def detach_volume(self, instance_name, mountpoint): - """Detach volume storage to VM instance""" + """Detach volume storage to VM instance.""" pass def get_console_pool_info(self, console_type): - """Get info about the host on which the VM resides""" + """Get info about the host on which the VM resides.""" return {'address': FLAGS.vmwareapi_host_ip, 'username': FLAGS.vmwareapi_host_username, 'password': FLAGS.vmwareapi_host_password} + def update_available_resource(self, ctxt, host): + """This method is supported only by libvirt.""" + return + class VMWareAPISession(object): - """Sets up a session with the ESX host and handles all - the calls made to the host + """ + Sets up a session with the ESX host and handles all + the calls made to the host. """ def __init__(self, host_ip, host_username, host_password, @@ -200,11 +206,11 @@ class VMWareAPISession(object): self._create_session() def _get_vim_object(self): - """Create the VIM Object instance""" + """Create the VIM Object instance.""" return vim.Vim(protocol=self._scheme, host=self._host_ip) def _create_session(self): - """Creates a session with the ESX host""" + """Creates a session with the ESX host.""" while True: try: # Login and setup the session with the ESX host for making @@ -241,12 +247,13 @@ class VMWareAPISession(object): pass def _is_vim_object(self, module): - """Check if the module is a VIM Object instance""" + """Check if the module is a VIM Object instance.""" return isinstance(module, vim.Vim) def _call_method(self, module, method, *args, **kwargs): - """Calls a method within the module specified with - args provided + """ + Calls a method within the module specified with + args provided. """ args = list(args) retry_count = 0 @@ -254,7 +261,8 @@ class VMWareAPISession(object): while True: try: if not self._is_vim_object(module): - #If it is not the first try, then get the latest vim object + # If it is not the first try, then get the latest + # vim object if retry_count > 0: args = args[1:] args = [self.vim] + args @@ -264,8 +272,7 @@ class VMWareAPISession(object): for method_elem in method.split("."): temp_module = getattr(temp_module, method_elem) - ret_val = temp_module(*args, **kwargs) - return ret_val + return temp_module(*args, **kwargs) except error_util.VimFaultException, excep: # If it is a Session Fault Exception, it may point # to a session gone bad. So we try re-creating a session @@ -274,9 +281,9 @@ class VMWareAPISession(object): if error_util.FAULT_NOT_AUTHENTICATED in excep.fault_list: self._create_session() else: - #No re-trying for errors for API call has gone through - #and is the caller's fault. Caller should handle these - #errors. e.g, InvalidArgument fault. + # No re-trying for errors for API call has gone through + # and is the caller's fault. Caller should handle these + # errors. e.g, InvalidArgument fault. break except error_util.SessionOverLoadException, excep: # For exceptions which may come because of session overload, @@ -299,13 +306,14 @@ class VMWareAPISession(object): raise def _get_vim(self): - """Gets the VIM object reference""" + """Gets the VIM object reference.""" if self.vim is None: self._create_session() return self.vim def _wait_for_task(self, instance_id, task_ref): - """Return a Deferred that will give the result of the given task. + """ + Return a Deferred that will give the result of the given task. The task is polled until it completes. """ done = event.Event() @@ -317,7 +325,8 @@ class VMWareAPISession(object): return ret_val def _poll_task(self, instance_id, task_ref, done): - """Poll the given task, and fires the given Deferred if we + """ + Poll the given task, and fires the given Deferred if we get a result. """ try: @@ -331,7 +340,7 @@ class VMWareAPISession(object): if task_info.state in ['queued', 'running']: return elif task_info.state == 'success': - LOG.info(_("Task [%(task_name)s] %(task_ref)s " + LOG.debug(_("Task [%(task_name)s] %(task_ref)s " "status: success") % locals()) done.send("success") else: diff --git a/tools/esx/guest_tool.py b/tools/esx/guest_tool.py index 232ef086bdd1..bbf3ea9087e3 100644 --- a/tools/esx/guest_tool.py +++ b/tools/esx/guest_tool.py @@ -36,7 +36,7 @@ ARCH_32_BIT = '32bit' ARCH_64_BIT = '64bit' NO_MACHINE_ID = 'No machine id' -#Logging +# Logging FORMAT = "%(asctime)s - %(levelname)s - %(message)s" if sys.platform == PLATFORM_WIN: LOG_DIR = os.path.join(os.environ.get('ALLUSERSPROFILE'), 'openstack') @@ -56,7 +56,7 @@ else: class ProcessExecutionError: - """Process Execution Error Class""" + """Process Execution Error Class.""" def __init__(self, exit_code, stdout, stderr, cmd): self.exit_code = exit_code @@ -77,7 +77,8 @@ def _bytes2int(bytes): def _parse_network_details(machine_id): - """Parse the machine.id field to get MAC, IP, Netmask and Gateway fields + """ + Parse the machine.id field to get MAC, IP, Netmask and Gateway fields machine.id is of the form MAC;IP;Netmask;Gateway;Broadcast;DNS1,DNS2 where ';' is the separator. """ @@ -103,7 +104,7 @@ def _parse_network_details(machine_id): def _get_windows_network_adapters(): - """Get the list of windows network adapters""" + """Get the list of windows network adapters.""" import win32com.client wbem_locator = win32com.client.Dispatch('WbemScripting.SWbemLocator') wbem_service = wbem_locator.ConnectServer('.', 'root\cimv2') @@ -132,7 +133,7 @@ def _get_windows_network_adapters(): def _get_linux_network_adapters(): - """Get the list of Linux network adapters""" + """Get the list of Linux network adapters.""" import fcntl max_bytes = 8096 arch = platform.architecture()[0] @@ -177,7 +178,7 @@ def _get_linux_network_adapters(): def _get_adapter_name_and_ip_address(network_adapters, mac_address): - """Get the adapter name based on the MAC address""" + """Get the adapter name based on the MAC address.""" adapter_name = None ip_address = None for network_adapter in network_adapters: @@ -189,19 +190,19 @@ def _get_adapter_name_and_ip_address(network_adapters, mac_address): def _get_win_adapter_name_and_ip_address(mac_address): - """Get Windows network adapter name""" + """Get Windows network adapter name.""" network_adapters = _get_windows_network_adapters() return _get_adapter_name_and_ip_address(network_adapters, mac_address) def _get_linux_adapter_name_and_ip_address(mac_address): - """Get Linux network adapter name""" + """Get Linux network adapter name.""" network_adapters = _get_linux_network_adapters() return _get_adapter_name_and_ip_address(network_adapters, mac_address) def _execute(cmd_list, process_input=None, check_exit_code=True): - """Executes the command with the list of arguments specified""" + """Executes the command with the list of arguments specified.""" cmd = ' '.join(cmd_list) logging.debug(_("Executing command: '%s'") % cmd) env = os.environ.copy() @@ -226,7 +227,7 @@ def _execute(cmd_list, process_input=None, check_exit_code=True): def _windows_set_networking(): - """Set IP address for the windows VM""" + """Set IP address for the windows VM.""" program_files = os.environ.get('PROGRAMFILES') program_files_x86 = os.environ.get('PROGRAMFILES(X86)') vmware_tools_bin = None @@ -256,7 +257,7 @@ def _windows_set_networking(): 'name="%s"' % adapter_name, 'source=static', ip_address, subnet_mask, gateway, '1'] _execute(cmd) - #Windows doesn't let you manually set the broadcast address + # Windows doesn't let you manually set the broadcast address for dns_server in dns_servers: if dns_server: cmd = ['netsh', 'interface', 'ip', 'add', 'dns', @@ -285,9 +286,9 @@ def _set_rhel_networking(network_details=[]): if adapter_name and not ip_address == current_ip_address: interface_file_name = \ '/etc/sysconfig/network-scripts/ifcfg-%s' % adapter_name - #Remove file + # Remove file os.remove(interface_file_name) - #Touch file + # Touch file _execute(['touch', interface_file_name]) interface_file = open(interface_file_name, 'w') interface_file.write('\nDEVICE=%s' % adapter_name) @@ -315,7 +316,7 @@ def _set_rhel_networking(network_details=[]): def _linux_set_networking(): - """Set IP address for the Linux VM""" + """Set IP address for the Linux VM.""" vmware_tools_bin = None if os.path.exists('/usr/sbin/vmtoolsd'): vmware_tools_bin = '/usr/sbin/vmtoolsd' @@ -329,7 +330,7 @@ def _linux_set_networking(): cmd = [vmware_tools_bin, '--cmd', 'machine.id.get'] network_details = _parse_network_details(_execute(cmd, check_exit_code=False)) - #TODO: For other distros like ubuntu, suse, debian, BSD, etc. + # TODO(sateesh): For other distros like ubuntu, suse, debian, BSD, etc. _set_rhel_networking(network_details) else: logging.warn(_("VMware Tools is not installed"))