* 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!
This commit is contained in:
parent
cd381ae3e1
commit
45ca7b71a8
@ -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.
|
||||
|
||||
|
@ -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 '<VM PATH>:<ESX Username>@<ESX Password>'.
|
||||
"""
|
||||
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 '<VM MOID>:<VMRC Ticket>'.
|
||||
"""
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
=======================================
|
||||
"""
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
"""
|
||||
|
@ -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 "
|
||||
|
@ -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"))
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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://<server>/vimService.wsdl'
|
||||
'e.g http://<server>/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 <test/> as opposed to <test>test</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. <test/> as opposed to <test>test</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
|
||||
|
@ -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:
|
||||
|
@ -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')
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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"))
|
||||
|
Loading…
Reference in New Issue
Block a user