Convert vmwareapi code to UNIX style line endings

It's the only code in the codebase using evil CRLF line endings.

Change-Id: I8b1a2b12a5707fbd4d32588c081599beaa34aca5
This commit is contained in:
Mark McLoughlin 2012-01-25 11:57:25 +00:00
parent 99daaea663
commit 50f3198477
13 changed files with 3212 additions and 3212 deletions

View File

@ -1,21 +1,21 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
:mod:`vmwareapi` -- Stubs for VMware API
=======================================
"""
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
:mod:`vmwareapi` -- Stubs for VMware API
=======================================
"""

View File

@ -1,109 +1,109 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Stubouts, mocks and fixtures for the test suite
"""
import time
from nova import db
from nova import utils
from nova.compute import task_states
from nova.compute import vm_states
def stub_out_db_instance_api(stubs):
"""Stubs out the db API for creating Instances."""
INSTANCE_TYPES = {
'm1.tiny': dict(memory_mb=512, vcpus=1, root_gb=0, flavorid=1),
'm1.small': dict(memory_mb=2048, vcpus=1, root_gb=20, flavorid=2),
'm1.medium':
dict(memory_mb=4096, vcpus=2, root_gb=40, flavorid=3),
'm1.large': dict(memory_mb=8192, vcpus=4, root_gb=80, flavorid=4),
'm1.xlarge':
dict(memory_mb=16384, vcpus=8, root_gb=160, flavorid=5)}
class FakeModel(object):
"""Stubs out for model."""
def __init__(self, values):
self.values = values
def __getattr__(self, name):
return self.values[name]
def __getitem__(self, key):
if key in self.values:
return self.values[key]
else:
raise NotImplementedError()
def fake_instance_create(context, values):
"""Stubs out the db.instance_create method."""
type_data = INSTANCE_TYPES[values['instance_type']]
base_options = {
'name': values['name'],
'id': values['id'],
'uuid': utils.gen_uuid(),
'reservation_id': utils.generate_uid('r'),
'image_ref': values['image_ref'],
'kernel_id': values['kernel_id'],
'ramdisk_id': values['ramdisk_id'],
'vm_state': vm_states.BUILDING,
'task_state': task_states.SCHEDULING,
'user_id': values['user_id'],
'project_id': values['project_id'],
'launch_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
'instance_type': values['instance_type'],
'memory_mb': type_data['memory_mb'],
'vcpus': type_data['vcpus'],
'mac_addresses': [{'address': values['mac_address']}],
'root_gb': type_data['root_gb'],
}
return FakeModel(base_options)
def fake_network_get_by_instance(context, instance_id):
"""Stubs out the db.network_get_by_instance method."""
fields = {
'bridge': 'vmnet0',
'netmask': '255.255.255.0',
'gateway': '10.10.10.1',
'broadcast': '10.10.10.255',
'dns1': 'fake',
'vlan': 100}
return FakeModel(fields)
def fake_instance_action_create(context, action):
"""Stubs out the db.instance_action_create method."""
pass
def fake_instance_type_get_all(context, inactive=0, filters=None):
return INSTANCE_TYPES.values()
def fake_instance_type_get_by_name(context, name):
return INSTANCE_TYPES[name]
stubs.Set(db, 'instance_create', fake_instance_create)
stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance)
stubs.Set(db, 'instance_action_create', fake_instance_action_create)
stubs.Set(db, 'instance_type_get_all', fake_instance_type_get_all)
stubs.Set(db, 'instance_type_get_by_name', fake_instance_type_get_by_name)
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Stubouts, mocks and fixtures for the test suite
"""
import time
from nova import db
from nova import utils
from nova.compute import task_states
from nova.compute import vm_states
def stub_out_db_instance_api(stubs):
"""Stubs out the db API for creating Instances."""
INSTANCE_TYPES = {
'm1.tiny': dict(memory_mb=512, vcpus=1, root_gb=0, flavorid=1),
'm1.small': dict(memory_mb=2048, vcpus=1, root_gb=20, flavorid=2),
'm1.medium':
dict(memory_mb=4096, vcpus=2, root_gb=40, flavorid=3),
'm1.large': dict(memory_mb=8192, vcpus=4, root_gb=80, flavorid=4),
'm1.xlarge':
dict(memory_mb=16384, vcpus=8, root_gb=160, flavorid=5)}
class FakeModel(object):
"""Stubs out for model."""
def __init__(self, values):
self.values = values
def __getattr__(self, name):
return self.values[name]
def __getitem__(self, key):
if key in self.values:
return self.values[key]
else:
raise NotImplementedError()
def fake_instance_create(context, values):
"""Stubs out the db.instance_create method."""
type_data = INSTANCE_TYPES[values['instance_type']]
base_options = {
'name': values['name'],
'id': values['id'],
'uuid': utils.gen_uuid(),
'reservation_id': utils.generate_uid('r'),
'image_ref': values['image_ref'],
'kernel_id': values['kernel_id'],
'ramdisk_id': values['ramdisk_id'],
'vm_state': vm_states.BUILDING,
'task_state': task_states.SCHEDULING,
'user_id': values['user_id'],
'project_id': values['project_id'],
'launch_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
'instance_type': values['instance_type'],
'memory_mb': type_data['memory_mb'],
'vcpus': type_data['vcpus'],
'mac_addresses': [{'address': values['mac_address']}],
'root_gb': type_data['root_gb'],
}
return FakeModel(base_options)
def fake_network_get_by_instance(context, instance_id):
"""Stubs out the db.network_get_by_instance method."""
fields = {
'bridge': 'vmnet0',
'netmask': '255.255.255.0',
'gateway': '10.10.10.1',
'broadcast': '10.10.10.255',
'dns1': 'fake',
'vlan': 100}
return FakeModel(fields)
def fake_instance_action_create(context, action):
"""Stubs out the db.instance_action_create method."""
pass
def fake_instance_type_get_all(context, inactive=0, filters=None):
return INSTANCE_TYPES.values()
def fake_instance_type_get_by_name(context, name):
return INSTANCE_TYPES[name]
stubs.Set(db, 'instance_create', fake_instance_create)
stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance)
stubs.Set(db, 'instance_action_create', fake_instance_action_create)
stubs.Set(db, 'instance_type_get_all', fake_instance_type_get_all)
stubs.Set(db, 'instance_type_get_by_name', fake_instance_type_get_by_name)

View File

@ -1,51 +1,51 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Stubouts for the test suite
"""
from nova.virt import vmwareapi_conn
from nova.virt.vmwareapi import fake
from nova.virt.vmwareapi import vmware_images
from nova.virt.vmwareapi import vmops
from nova.virt.vmwareapi import network_utils
def fake_get_vim_object(arg):
"""Stubs out the VMWareAPISession's get_vim_object method."""
return fake.FakeVim()
def fake_is_vim_object(arg, module):
"""Stubs out the VMWareAPISession's is_vim_object method."""
return isinstance(module, fake.FakeVim)
def set_stubs(stubs):
"""Set the stubs."""
stubs.Set(vmops.VMWareVMOps, 'plug_vifs', fake.fake_plug_vifs)
stubs.Set(network_utils, 'get_network_with_the_name',
fake.fake_get_network)
stubs.Set(vmware_images, 'fetch_image', fake.fake_fetch_image)
stubs.Set(vmware_images, 'get_vmdk_size_and_properties',
fake.fake_get_vmdk_size_and_properties)
stubs.Set(vmware_images, 'upload_image', fake.fake_upload_image)
stubs.Set(vmwareapi_conn.VMWareAPISession, "_get_vim_object",
fake_get_vim_object)
stubs.Set(vmwareapi_conn.VMWareAPISession, "_is_vim_object",
fake_is_vim_object)
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Stubouts for the test suite
"""
from nova.virt import vmwareapi_conn
from nova.virt.vmwareapi import fake
from nova.virt.vmwareapi import vmware_images
from nova.virt.vmwareapi import vmops
from nova.virt.vmwareapi import network_utils
def fake_get_vim_object(arg):
"""Stubs out the VMWareAPISession's get_vim_object method."""
return fake.FakeVim()
def fake_is_vim_object(arg, module):
"""Stubs out the VMWareAPISession's is_vim_object method."""
return isinstance(module, fake.FakeVim)
def set_stubs(stubs):
"""Set the stubs."""
stubs.Set(vmops.VMWareVMOps, 'plug_vifs', fake.fake_plug_vifs)
stubs.Set(network_utils, 'get_network_with_the_name',
fake.fake_get_network)
stubs.Set(vmware_images, 'fetch_image', fake.fake_fetch_image)
stubs.Set(vmware_images, 'get_vmdk_size_and_properties',
fake.fake_get_vmdk_size_and_properties)
stubs.Set(vmware_images, 'upload_image', fake.fake_upload_image)
stubs.Set(vmwareapi_conn.VMWareAPISession, "_get_vim_object",
fake_get_vim_object)
stubs.Set(vmwareapi_conn.VMWareAPISession, "_is_vim_object",
fake_is_vim_object)

View File

@ -1,96 +1,96 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Exception classes and SOAP response error checking module.
"""
FAULT_NOT_AUTHENTICATED = "NotAuthenticated"
FAULT_ALREADY_EXISTS = "AlreadyExists"
class VimException(Exception):
"""The VIM Exception class."""
def __init__(self, exception_summary, excep):
Exception.__init__(self)
self.exception_summary = exception_summary
self.exception_obj = excep
def __str__(self):
return self.exception_summary + str(self.exception_obj)
class SessionOverLoadException(VimException):
"""Session Overload Exception."""
pass
class VimAttributeError(VimException):
"""VI Attribute Error."""
pass
class VimFaultException(Exception):
"""The VIM Fault exception class."""
def __init__(self, fault_list, excep):
Exception.__init__(self)
self.fault_list = fault_list
self.exception_obj = excep
def __str__(self):
return str(self.exception_obj)
class FaultCheckers(object):
"""
Methods for fault checking of SOAP response. Per Method error handlers
for which we desire error checking are defined. SOAP faults are
embedded in the SOAP messages as properties and not as SOAP faults.
"""
@staticmethod
def retrieveproperties_fault_checker(resp_obj):
"""
Checks the RetrieveProperties response for errors. Certain faults
are sent as part of the SOAP body as property of missingSet.
For example NotAuthenticated fault.
"""
fault_list = []
if not resp_obj:
# This is the case when the session has timed out. ESX SOAP server
# sends an empty RetrievePropertiesResponse. Normally missingSet in
# the returnval field has the specifics about the error, but that's
# not the case with a timed out idle session. It is as bad as a
# terminated session for we cannot use the session. So setting
# fault to NotAuthenticated fault.
fault_list = ["NotAuthenticated"]
else:
for obj_cont in resp_obj:
if hasattr(obj_cont, "missingSet"):
for missing_elem in obj_cont.missingSet:
fault_type = \
missing_elem.fault.fault.__class__.__name__
# Fault needs to be added to the type of fault for
# uniformity in error checking as SOAP faults define
fault_list.append(fault_type)
if fault_list:
exc_msg_list = ', '.join(fault_list)
raise VimFaultException(fault_list, Exception(_("Error(s) %s "
"occurred in the call to RetrieveProperties") %
exc_msg_list))
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Exception classes and SOAP response error checking module.
"""
FAULT_NOT_AUTHENTICATED = "NotAuthenticated"
FAULT_ALREADY_EXISTS = "AlreadyExists"
class VimException(Exception):
"""The VIM Exception class."""
def __init__(self, exception_summary, excep):
Exception.__init__(self)
self.exception_summary = exception_summary
self.exception_obj = excep
def __str__(self):
return self.exception_summary + str(self.exception_obj)
class SessionOverLoadException(VimException):
"""Session Overload Exception."""
pass
class VimAttributeError(VimException):
"""VI Attribute Error."""
pass
class VimFaultException(Exception):
"""The VIM Fault exception class."""
def __init__(self, fault_list, excep):
Exception.__init__(self)
self.fault_list = fault_list
self.exception_obj = excep
def __str__(self):
return str(self.exception_obj)
class FaultCheckers(object):
"""
Methods for fault checking of SOAP response. Per Method error handlers
for which we desire error checking are defined. SOAP faults are
embedded in the SOAP messages as properties and not as SOAP faults.
"""
@staticmethod
def retrieveproperties_fault_checker(resp_obj):
"""
Checks the RetrieveProperties response for errors. Certain faults
are sent as part of the SOAP body as property of missingSet.
For example NotAuthenticated fault.
"""
fault_list = []
if not resp_obj:
# This is the case when the session has timed out. ESX SOAP server
# sends an empty RetrievePropertiesResponse. Normally missingSet in
# the returnval field has the specifics about the error, but that's
# not the case with a timed out idle session. It is as bad as a
# terminated session for we cannot use the session. So setting
# fault to NotAuthenticated fault.
fault_list = ["NotAuthenticated"]
else:
for obj_cont in resp_obj:
if hasattr(obj_cont, "missingSet"):
for missing_elem in obj_cont.missingSet:
fault_type = \
missing_elem.fault.fault.__class__.__name__
# Fault needs to be added to the type of fault for
# uniformity in error checking as SOAP faults define
fault_list.append(fault_type)
if fault_list:
exc_msg_list = ', '.join(fault_list)
raise VimFaultException(fault_list, Exception(_("Error(s) %s "
"occurred in the call to RetrieveProperties") %
exc_msg_list))

File diff suppressed because it is too large Load Diff

View File

@ -1,169 +1,169 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Utility classes for defining the time saving transfer of data from the reader
to the write using a LightQueue as a Pipe between the reader and the writer.
"""
from eventlet import event
from eventlet import greenthread
from eventlet.queue import LightQueue
from nova import exception
from nova import log as logging
LOG = logging.getLogger("nova.virt.vmwareapi.io_util")
IO_THREAD_SLEEP_TIME = .01
GLANCE_POLL_INTERVAL = 5
class ThreadSafePipe(LightQueue):
"""The pipe to hold the data which the reader writes to and the writer
reads from."""
def __init__(self, maxsize, transfer_size):
LightQueue.__init__(self, maxsize)
self.transfer_size = transfer_size
self.transferred = 0
def read(self, chunk_size):
"""Read data from the pipe. Chunksize if ignored for we have ensured
that the data chunks written to the pipe by readers is the same as the
chunks asked for by the Writer."""
if self.transferred < self.transfer_size:
data_item = self.get()
self.transferred += len(data_item)
return data_item
else:
return ""
def write(self, data):
"""Put a data item in the pipe."""
self.put(data)
def close(self):
"""A place-holder to maintain consistency."""
pass
class GlanceWriteThread(object):
"""Ensures that image data is written to in the glance client and that
it is in correct ('active')state."""
def __init__(self, input, glance_client, image_id, image_meta=None):
if not image_meta:
image_meta = {}
self.input = input
self.glance_client = glance_client
self.image_id = image_id
self.image_meta = image_meta
self._running = False
def start(self):
self.done = event.Event()
def _inner():
"""Function to do the image data transfer through an update
and thereon checks if the state is 'active'."""
self.glance_client.update_image(self.image_id,
image_meta=self.image_meta,
image_data=self.input)
self._running = True
while self._running:
try:
image_status = \
self.glance_client.get_image_meta(self.image_id).get(
"status")
if image_status == "active":
self.stop()
self.done.send(True)
# If the state is killed, then raise an exception.
elif image_status == "killed":
self.stop()
exc_msg = _("Glance image %s is in killed state") %\
self.image_id
LOG.exception(exc_msg)
self.done.send_exception(exception.Error(exc_msg))
elif image_status in ["saving", "queued"]:
greenthread.sleep(GLANCE_POLL_INTERVAL)
else:
self.stop()
exc_msg = _("Glance image "
"%(image_id)s is in unknown state "
"- %(state)s") % {
"image_id": self.image_id,
"state": image_status}
LOG.exception(exc_msg)
self.done.send_exception(exception.Error(exc_msg))
except Exception, exc:
self.stop()
self.done.send_exception(exc)
greenthread.spawn(_inner)
return self.done
def stop(self):
self._running = False
def wait(self):
return self.done.wait()
def close(self):
pass
class IOThread(object):
"""Class that reads chunks from the input file and writes them to the
output file till the transfer is completely done."""
def __init__(self, input, output):
self.input = input
self.output = output
self._running = False
self.got_exception = False
def start(self):
self.done = event.Event()
def _inner():
"""Read data from the input and write the same to the output
until the transfer completes."""
self._running = True
while self._running:
try:
data = self.input.read(None)
if not data:
self.stop()
self.done.send(True)
self.output.write(data)
greenthread.sleep(IO_THREAD_SLEEP_TIME)
except Exception, exc:
self.stop()
LOG.exception(exc)
self.done.send_exception(exc)
greenthread.spawn(_inner)
return self.done
def stop(self):
self._running = False
def wait(self):
return self.done.wait()
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Utility classes for defining the time saving transfer of data from the reader
to the write using a LightQueue as a Pipe between the reader and the writer.
"""
from eventlet import event
from eventlet import greenthread
from eventlet.queue import LightQueue
from nova import exception
from nova import log as logging
LOG = logging.getLogger("nova.virt.vmwareapi.io_util")
IO_THREAD_SLEEP_TIME = .01
GLANCE_POLL_INTERVAL = 5
class ThreadSafePipe(LightQueue):
"""The pipe to hold the data which the reader writes to and the writer
reads from."""
def __init__(self, maxsize, transfer_size):
LightQueue.__init__(self, maxsize)
self.transfer_size = transfer_size
self.transferred = 0
def read(self, chunk_size):
"""Read data from the pipe. Chunksize if ignored for we have ensured
that the data chunks written to the pipe by readers is the same as the
chunks asked for by the Writer."""
if self.transferred < self.transfer_size:
data_item = self.get()
self.transferred += len(data_item)
return data_item
else:
return ""
def write(self, data):
"""Put a data item in the pipe."""
self.put(data)
def close(self):
"""A place-holder to maintain consistency."""
pass
class GlanceWriteThread(object):
"""Ensures that image data is written to in the glance client and that
it is in correct ('active')state."""
def __init__(self, input, glance_client, image_id, image_meta=None):
if not image_meta:
image_meta = {}
self.input = input
self.glance_client = glance_client
self.image_id = image_id
self.image_meta = image_meta
self._running = False
def start(self):
self.done = event.Event()
def _inner():
"""Function to do the image data transfer through an update
and thereon checks if the state is 'active'."""
self.glance_client.update_image(self.image_id,
image_meta=self.image_meta,
image_data=self.input)
self._running = True
while self._running:
try:
image_status = \
self.glance_client.get_image_meta(self.image_id).get(
"status")
if image_status == "active":
self.stop()
self.done.send(True)
# If the state is killed, then raise an exception.
elif image_status == "killed":
self.stop()
exc_msg = _("Glance image %s is in killed state") %\
self.image_id
LOG.exception(exc_msg)
self.done.send_exception(exception.Error(exc_msg))
elif image_status in ["saving", "queued"]:
greenthread.sleep(GLANCE_POLL_INTERVAL)
else:
self.stop()
exc_msg = _("Glance image "
"%(image_id)s is in unknown state "
"- %(state)s") % {
"image_id": self.image_id,
"state": image_status}
LOG.exception(exc_msg)
self.done.send_exception(exception.Error(exc_msg))
except Exception, exc:
self.stop()
self.done.send_exception(exc)
greenthread.spawn(_inner)
return self.done
def stop(self):
self._running = False
def wait(self):
return self.done.wait()
def close(self):
pass
class IOThread(object):
"""Class that reads chunks from the input file and writes them to the
output file till the transfer is completely done."""
def __init__(self, input, output):
self.input = input
self.output = output
self._running = False
self.got_exception = False
def start(self):
self.done = event.Event()
def _inner():
"""Read data from the input and write the same to the output
until the transfer completes."""
self._running = True
while self._running:
try:
data = self.input.read(None)
if not data:
self.stop()
self.done.send(True)
self.output.write(data)
greenthread.sleep(IO_THREAD_SLEEP_TIME)
except Exception, exc:
self.stop()
LOG.exception(exc)
self.done.send_exception(exc)
greenthread.spawn(_inner)
return self.done
def stop(self):
self._running = False
def wait(self):
return self.done.wait()

View File

@ -1,170 +1,170 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Utility functions for ESX Networking.
"""
from nova import exception
from nova import log as logging
from nova.virt.vmwareapi import error_util
from nova.virt.vmwareapi import vim_util
from nova.virt.vmwareapi import vm_util
LOG = logging.getLogger("nova.virt.vmwareapi.network_utils")
def get_network_with_the_name(session, network_name="vmnet0"):
"""
Gets reference to the network whose name is passed as the
argument.
"""
hostsystems = session._call_method(vim_util, "get_objects",
"HostSystem", ["network"])
vm_networks_ret = hostsystems[0].propSet[0].val
# Meaning there are no networks on the host. suds responds with a ""
# in the parent property field rather than a [] in the
# ManagedObjectRefernce property field of the parent
if not vm_networks_ret:
return None
vm_networks = vm_networks_ret.ManagedObjectReference
networks = session._call_method(vim_util,
"get_properties_for_a_collection_of_objects",
"Network", vm_networks, ["summary.name"])
network_obj = {}
LOG.warn(vm_networks)
for network in vm_networks:
# Get network properties
if network._type == 'DistributedVirtualPortgroup':
props = session._call_method(vim_util,
"get_dynamic_property", network,
"DistributedVirtualPortgroup", "config")
# NOTE(asomya): This only works on ESXi if the port binding is
# set to ephemeral
if props.name == network_name:
network_obj['type'] = 'DistributedVirtualPortgroup'
network_obj['dvpg'] = props.key
network_obj['dvsw'] = props.distributedVirtualSwitch.value
else:
props = session._call_method(vim_util,
"get_dynamic_property", network,
"Network", "summary.name")
if props == network_name:
network_obj['type'] = 'Network'
network_obj['name'] = network_name
if (len(network_obj) > 0):
return network_obj
else:
return None
def get_vswitch_for_vlan_interface(session, vlan_interface):
"""
Gets the vswitch associated with the physical network adapter
with the name supplied.
"""
# Get the list of vSwicthes on the Host System
host_mor = session._call_method(vim_util, "get_objects",
"HostSystem")[0].obj
vswitches_ret = session._call_method(vim_util,
"get_dynamic_property", host_mor,
"HostSystem", "config.network.vswitch")
# Meaning there are no vSwitches on the host. Shouldn't be the case,
# but just doing code check
if not vswitches_ret:
return
vswitches = vswitches_ret.HostVirtualSwitch
# Get the vSwitch associated with the network adapter
for elem in vswitches:
try:
for nic_elem in elem.pnic:
if str(nic_elem).split('-')[-1].find(vlan_interface) != -1:
return elem.name
# Catching Attribute error as a vSwitch may not be associated with a
# physical NIC.
except AttributeError:
pass
def check_if_vlan_interface_exists(session, vlan_interface):
"""Checks if the vlan_inteface exists on the esx host."""
host_net_system_mor = session._call_method(vim_util, "get_objects",
"HostSystem", ["configManager.networkSystem"])[0].propSet[0].val
physical_nics_ret = session._call_method(vim_util,
"get_dynamic_property", host_net_system_mor,
"HostNetworkSystem", "networkInfo.pnic")
# Meaning there are no physical nics on the host
if not physical_nics_ret:
return False
physical_nics = physical_nics_ret.PhysicalNic
for pnic in physical_nics:
if vlan_interface == pnic.device:
return True
return False
def get_vlanid_and_vswitch_for_portgroup(session, pg_name):
"""Get the vlan id and vswicth associated with the port group."""
host_mor = session._call_method(vim_util, "get_objects",
"HostSystem")[0].obj
port_grps_on_host_ret = session._call_method(vim_util,
"get_dynamic_property", host_mor,
"HostSystem", "config.network.portgroup")
if not port_grps_on_host_ret:
excep = ("ESX SOAP server returned an empty port group "
"for the host system in its response")
LOG.exception(excep)
raise exception.Error(_(excep))
port_grps_on_host = port_grps_on_host_ret.HostPortGroup
for p_gp in port_grps_on_host:
if p_gp.spec.name == pg_name:
p_grp_vswitch_name = p_gp.vswitch.split("-")[-1]
return p_gp.spec.vlanId, p_grp_vswitch_name
def create_port_group(session, pg_name, vswitch_name, vlan_id=0):
"""
Creates a port group on the host system with the vlan tags
supplied. VLAN id 0 means no vlan id association.
"""
client_factory = session._get_vim().client.factory
add_prt_grp_spec = vm_util.get_add_vswitch_port_group_spec(
client_factory,
vswitch_name,
pg_name,
vlan_id)
host_mor = session._call_method(vim_util, "get_objects",
"HostSystem")[0].obj
network_system_mor = session._call_method(vim_util,
"get_dynamic_property", host_mor,
"HostSystem", "configManager.networkSystem")
LOG.debug(_("Creating Port Group with name %s on "
"the ESX host") % pg_name)
try:
session._call_method(session._get_vim(),
"AddPortGroup", network_system_mor,
portgrp=add_prt_grp_spec)
except error_util.VimFaultException, exc:
# There can be a race condition when two instances try
# adding port groups at the same time. One succeeds, then
# the other one will get an exception. Since we are
# concerned with the port group being created, which is done
# by the other call, we can ignore the exception.
if error_util.FAULT_ALREADY_EXISTS not in exc.fault_list:
raise exception.Error(exc)
LOG.debug(_("Created Port Group with name %s on "
"the ESX host") % pg_name)
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Utility functions for ESX Networking.
"""
from nova import exception
from nova import log as logging
from nova.virt.vmwareapi import error_util
from nova.virt.vmwareapi import vim_util
from nova.virt.vmwareapi import vm_util
LOG = logging.getLogger("nova.virt.vmwareapi.network_utils")
def get_network_with_the_name(session, network_name="vmnet0"):
"""
Gets reference to the network whose name is passed as the
argument.
"""
hostsystems = session._call_method(vim_util, "get_objects",
"HostSystem", ["network"])
vm_networks_ret = hostsystems[0].propSet[0].val
# Meaning there are no networks on the host. suds responds with a ""
# in the parent property field rather than a [] in the
# ManagedObjectRefernce property field of the parent
if not vm_networks_ret:
return None
vm_networks = vm_networks_ret.ManagedObjectReference
networks = session._call_method(vim_util,
"get_properties_for_a_collection_of_objects",
"Network", vm_networks, ["summary.name"])
network_obj = {}
LOG.warn(vm_networks)
for network in vm_networks:
# Get network properties
if network._type == 'DistributedVirtualPortgroup':
props = session._call_method(vim_util,
"get_dynamic_property", network,
"DistributedVirtualPortgroup", "config")
# NOTE(asomya): This only works on ESXi if the port binding is
# set to ephemeral
if props.name == network_name:
network_obj['type'] = 'DistributedVirtualPortgroup'
network_obj['dvpg'] = props.key
network_obj['dvsw'] = props.distributedVirtualSwitch.value
else:
props = session._call_method(vim_util,
"get_dynamic_property", network,
"Network", "summary.name")
if props == network_name:
network_obj['type'] = 'Network'
network_obj['name'] = network_name
if (len(network_obj) > 0):
return network_obj
else:
return None
def get_vswitch_for_vlan_interface(session, vlan_interface):
"""
Gets the vswitch associated with the physical network adapter
with the name supplied.
"""
# Get the list of vSwicthes on the Host System
host_mor = session._call_method(vim_util, "get_objects",
"HostSystem")[0].obj
vswitches_ret = session._call_method(vim_util,
"get_dynamic_property", host_mor,
"HostSystem", "config.network.vswitch")
# Meaning there are no vSwitches on the host. Shouldn't be the case,
# but just doing code check
if not vswitches_ret:
return
vswitches = vswitches_ret.HostVirtualSwitch
# Get the vSwitch associated with the network adapter
for elem in vswitches:
try:
for nic_elem in elem.pnic:
if str(nic_elem).split('-')[-1].find(vlan_interface) != -1:
return elem.name
# Catching Attribute error as a vSwitch may not be associated with a
# physical NIC.
except AttributeError:
pass
def check_if_vlan_interface_exists(session, vlan_interface):
"""Checks if the vlan_inteface exists on the esx host."""
host_net_system_mor = session._call_method(vim_util, "get_objects",
"HostSystem", ["configManager.networkSystem"])[0].propSet[0].val
physical_nics_ret = session._call_method(vim_util,
"get_dynamic_property", host_net_system_mor,
"HostNetworkSystem", "networkInfo.pnic")
# Meaning there are no physical nics on the host
if not physical_nics_ret:
return False
physical_nics = physical_nics_ret.PhysicalNic
for pnic in physical_nics:
if vlan_interface == pnic.device:
return True
return False
def get_vlanid_and_vswitch_for_portgroup(session, pg_name):
"""Get the vlan id and vswicth associated with the port group."""
host_mor = session._call_method(vim_util, "get_objects",
"HostSystem")[0].obj
port_grps_on_host_ret = session._call_method(vim_util,
"get_dynamic_property", host_mor,
"HostSystem", "config.network.portgroup")
if not port_grps_on_host_ret:
excep = ("ESX SOAP server returned an empty port group "
"for the host system in its response")
LOG.exception(excep)
raise exception.Error(_(excep))
port_grps_on_host = port_grps_on_host_ret.HostPortGroup
for p_gp in port_grps_on_host:
if p_gp.spec.name == pg_name:
p_grp_vswitch_name = p_gp.vswitch.split("-")[-1]
return p_gp.spec.vlanId, p_grp_vswitch_name
def create_port_group(session, pg_name, vswitch_name, vlan_id=0):
"""
Creates a port group on the host system with the vlan tags
supplied. VLAN id 0 means no vlan id association.
"""
client_factory = session._get_vim().client.factory
add_prt_grp_spec = vm_util.get_add_vswitch_port_group_spec(
client_factory,
vswitch_name,
pg_name,
vlan_id)
host_mor = session._call_method(vim_util, "get_objects",
"HostSystem")[0].obj
network_system_mor = session._call_method(vim_util,
"get_dynamic_property", host_mor,
"HostSystem", "configManager.networkSystem")
LOG.debug(_("Creating Port Group with name %s on "
"the ESX host") % pg_name)
try:
session._call_method(session._get_vim(),
"AddPortGroup", network_system_mor,
portgrp=add_prt_grp_spec)
except error_util.VimFaultException, exc:
# There can be a race condition when two instances try
# adding port groups at the same time. One succeeds, then
# the other one will get an exception. Since we are
# concerned with the port group being created, which is done
# by the other call, we can ignore the exception.
if error_util.FAULT_ALREADY_EXISTS not in exc.fault_list:
raise exception.Error(exc)
LOG.debug(_("Created Port Group with name %s on "
"the ESX host") % pg_name)

View File

@ -1,179 +1,179 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Classes to handle image files
Collection of classes to handle image upload/download to/from Image service
(like Glance image storage and retrieval service) from/to ESX/ESXi server.
"""
import httplib
import urllib
import urllib2
import urlparse
from glance import client
from nova import flags
from nova import log as logging
LOG = logging.getLogger("nova.virt.vmwareapi.read_write_util")
FLAGS = flags.FLAGS
USER_AGENT = "OpenStack-ESX-Adapter"
try:
READ_CHUNKSIZE = client.BaseClient.CHUNKSIZE
except AttributeError:
READ_CHUNKSIZE = 65536
class GlanceFileRead(object):
"""Glance file read handler class."""
def __init__(self, glance_read_iter):
self.glance_read_iter = glance_read_iter
self.iter = self.get_next()
def read(self, chunk_size):
"""Read an item from the queue. The chunk size is ignored for the
Client ImageBodyIterator uses its own CHUNKSIZE."""
try:
return self.iter.next()
except StopIteration:
return ""
def get_next(self):
"""Get the next item from the image iterator."""
for data in self.glance_read_iter:
yield data
def close(self):
"""A dummy close just to maintain consistency."""
pass
class VMwareHTTPFile(object):
"""Base class for HTTP file."""
def __init__(self, file_handle):
self.eof = False
self.file_handle = file_handle
def set_eof(self, eof):
"""Set the end of file marker."""
self.eof = eof
def get_eof(self):
"""Check if the end of file has been reached."""
return self.eof
def close(self):
"""Close the file handle."""
try:
self.file_handle.close()
except Exception, exc:
LOG.exception(exc)
def __del__(self):
"""Close the file handle on garbage collection."""
self.close()
def _build_vim_cookie_headers(self, vim_cookies):
"""Build ESX host session cookie headers."""
cookie_header = ""
for vim_cookie in vim_cookies:
cookie_header = vim_cookie.name + "=" + vim_cookie.value
break
return cookie_header
def write(self, data):
"""Write data to the file."""
raise NotImplementedError
def read(self, chunk_size):
"""Read a chunk of data."""
raise NotImplementedError
def get_size(self):
"""Get size of the file to be read."""
raise NotImplementedError
class VMWareHTTPWriteFile(VMwareHTTPFile):
"""VMWare file write handler class."""
def __init__(self, host, data_center_name, datastore_name, cookies,
file_path, file_size, scheme="https"):
base_url = "%s://%s/folder/%s" % (scheme, host, file_path)
param_list = {"dcPath": data_center_name, "dsName": datastore_name}
base_url = base_url + "?" + urllib.urlencode(param_list)
(scheme, netloc, path, params, query, fragment) = \
urlparse.urlparse(base_url)
if scheme == "http":
conn = httplib.HTTPConnection(netloc)
elif scheme == "https":
conn = httplib.HTTPSConnection(netloc)
conn.putrequest("PUT", path + "?" + query)
conn.putheader("User-Agent", USER_AGENT)
conn.putheader("Content-Length", file_size)
conn.putheader("Cookie", self._build_vim_cookie_headers(cookies))
conn.endheaders()
self.conn = conn
VMwareHTTPFile.__init__(self, conn)
def write(self, data):
"""Write to the file."""
self.file_handle.send(data)
def close(self):
"""Get the response and close the connection."""
try:
self.conn.getresponse()
except Exception, excep:
LOG.debug(_("Exception during HTTP connection close in "
"VMWareHTTpWrite. Exception is %s") % excep)
super(VMWareHTTPWriteFile, self).close()
class VmWareHTTPReadFile(VMwareHTTPFile):
"""VMWare file read handler class."""
def __init__(self, host, data_center_name, datastore_name, cookies,
file_path, scheme="https"):
base_url = "%s://%s/folder/%s" % (scheme, host,
urllib.pathname2url(file_path))
param_list = {"dcPath": data_center_name, "dsName": datastore_name}
base_url = base_url + "?" + urllib.urlencode(param_list)
headers = {'User-Agent': USER_AGENT,
'Cookie': self._build_vim_cookie_headers(cookies)}
request = urllib2.Request(base_url, None, headers)
conn = urllib2.urlopen(request)
VMwareHTTPFile.__init__(self, conn)
def read(self, chunk_size):
"""Read a chunk of data."""
# We are ignoring the chunk size passed for we want the pipe to hold
# data items of the chunk-size that Glance Client uses for read
# while writing.
return self.file_handle.read(READ_CHUNKSIZE)
def get_size(self):
"""Get size of the file to be read."""
return self.file_handle.headers.get("Content-Length", -1)
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Classes to handle image files
Collection of classes to handle image upload/download to/from Image service
(like Glance image storage and retrieval service) from/to ESX/ESXi server.
"""
import httplib
import urllib
import urllib2
import urlparse
from glance import client
from nova import flags
from nova import log as logging
LOG = logging.getLogger("nova.virt.vmwareapi.read_write_util")
FLAGS = flags.FLAGS
USER_AGENT = "OpenStack-ESX-Adapter"
try:
READ_CHUNKSIZE = client.BaseClient.CHUNKSIZE
except AttributeError:
READ_CHUNKSIZE = 65536
class GlanceFileRead(object):
"""Glance file read handler class."""
def __init__(self, glance_read_iter):
self.glance_read_iter = glance_read_iter
self.iter = self.get_next()
def read(self, chunk_size):
"""Read an item from the queue. The chunk size is ignored for the
Client ImageBodyIterator uses its own CHUNKSIZE."""
try:
return self.iter.next()
except StopIteration:
return ""
def get_next(self):
"""Get the next item from the image iterator."""
for data in self.glance_read_iter:
yield data
def close(self):
"""A dummy close just to maintain consistency."""
pass
class VMwareHTTPFile(object):
"""Base class for HTTP file."""
def __init__(self, file_handle):
self.eof = False
self.file_handle = file_handle
def set_eof(self, eof):
"""Set the end of file marker."""
self.eof = eof
def get_eof(self):
"""Check if the end of file has been reached."""
return self.eof
def close(self):
"""Close the file handle."""
try:
self.file_handle.close()
except Exception, exc:
LOG.exception(exc)
def __del__(self):
"""Close the file handle on garbage collection."""
self.close()
def _build_vim_cookie_headers(self, vim_cookies):
"""Build ESX host session cookie headers."""
cookie_header = ""
for vim_cookie in vim_cookies:
cookie_header = vim_cookie.name + "=" + vim_cookie.value
break
return cookie_header
def write(self, data):
"""Write data to the file."""
raise NotImplementedError
def read(self, chunk_size):
"""Read a chunk of data."""
raise NotImplementedError
def get_size(self):
"""Get size of the file to be read."""
raise NotImplementedError
class VMWareHTTPWriteFile(VMwareHTTPFile):
"""VMWare file write handler class."""
def __init__(self, host, data_center_name, datastore_name, cookies,
file_path, file_size, scheme="https"):
base_url = "%s://%s/folder/%s" % (scheme, host, file_path)
param_list = {"dcPath": data_center_name, "dsName": datastore_name}
base_url = base_url + "?" + urllib.urlencode(param_list)
(scheme, netloc, path, params, query, fragment) = \
urlparse.urlparse(base_url)
if scheme == "http":
conn = httplib.HTTPConnection(netloc)
elif scheme == "https":
conn = httplib.HTTPSConnection(netloc)
conn.putrequest("PUT", path + "?" + query)
conn.putheader("User-Agent", USER_AGENT)
conn.putheader("Content-Length", file_size)
conn.putheader("Cookie", self._build_vim_cookie_headers(cookies))
conn.endheaders()
self.conn = conn
VMwareHTTPFile.__init__(self, conn)
def write(self, data):
"""Write to the file."""
self.file_handle.send(data)
def close(self):
"""Get the response and close the connection."""
try:
self.conn.getresponse()
except Exception, excep:
LOG.debug(_("Exception during HTTP connection close in "
"VMWareHTTpWrite. Exception is %s") % excep)
super(VMWareHTTPWriteFile, self).close()
class VmWareHTTPReadFile(VMwareHTTPFile):
"""VMWare file read handler class."""
def __init__(self, host, data_center_name, datastore_name, cookies,
file_path, scheme="https"):
base_url = "%s://%s/folder/%s" % (scheme, host,
urllib.pathname2url(file_path))
param_list = {"dcPath": data_center_name, "dsName": datastore_name}
base_url = base_url + "?" + urllib.urlencode(param_list)
headers = {'User-Agent': USER_AGENT,
'Cookie': self._build_vim_cookie_headers(cookies)}
request = urllib2.Request(base_url, None, headers)
conn = urllib2.urlopen(request)
VMwareHTTPFile.__init__(self, conn)
def read(self, chunk_size):
"""Read a chunk of data."""
# We are ignoring the chunk size passed for we want the pipe to hold
# data items of the chunk-size that Glance Client uses for read
# while writing.
return self.file_handle.read(READ_CHUNKSIZE)
def get_size(self):
"""Get size of the file to be read."""
return self.file_handle.headers.get("Content-Length", -1)

View File

@ -1,181 +1,181 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Classes for making VMware VI SOAP calls.
"""
import httplib
try:
import suds
except ImportError:
suds = None
from nova import flags
from nova.virt.vmwareapi import error_util
RESP_NOT_XML_ERROR = 'Response is "text/html", not "text/xml"'
CONN_ABORT_ERROR = 'Software caused connection abort'
ADDRESS_IN_USE_ERROR = 'Address already in use'
FLAGS = flags.FLAGS
flags.DEFINE_string('vmwareapi_wsdl_loc',
None,
'VIM Service WSDL Location'
'e.g http://<server>/vimService.wsdl'
'Due to a bug in vSphere ESX 4.1 default wsdl'
'Refer readme-vmware to setup')
if suds:
class VIMMessagePlugin(suds.plugin.MessagePlugin):
def addAttributeForValue(self, node):
# suds does not handle AnyType properly.
# VI SDK requires type attribute to be set when AnyType is used
if node.name == 'value':
node.set('xsi:type', 'xsd:string')
def marshalled(self, context):
"""suds will send the specified soap envelope.
Provides the plugin with the opportunity to prune empty
nodes and fixup nodes before sending it to the server.
"""
# suds builds the entire request object based on the wsdl schema.
# VI SDK throws server errors if optional SOAP nodes are sent
# without values, e.g. <test/> as opposed to <test>test</test>
context.envelope.prune()
context.envelope.walk(self.addAttributeForValue)
class Vim:
"""The VIM Object."""
def __init__(self,
protocol="https",
host="localhost"):
"""
Creates the necessary Communication interfaces and gets the
ServiceContent for initiating SOAP transactions.
protocol: http or https
host : ESX IPAddress[:port] or ESX Hostname[:port]
"""
if not suds:
raise Exception(_("Unable to import suds."))
self._protocol = protocol
self._host_name = host
wsdl_url = FLAGS.vmwareapi_wsdl_loc
if wsdl_url is None:
raise Exception(_("Must specify vmwareapi_wsdl_loc"))
# TODO(sateesh): Use this when VMware fixes their faulty wsdl
#wsdl_url = '%s://%s/sdk/vimService.wsdl' % (self._protocol,
# self._host_name)
url = '%s://%s/sdk' % (self._protocol, self._host_name)
self.client = suds.client.Client(wsdl_url, location=url,
plugins=[VIMMessagePlugin()])
self._service_content = \
self.RetrieveServiceContent("ServiceInstance")
def get_service_content(self):
"""Gets the service content object."""
return self._service_content
def __getattr__(self, attr_name):
"""Makes the API calls and gets the result."""
try:
return object.__getattr__(self, attr_name)
except AttributeError:
def vim_request_handler(managed_object, **kwargs):
"""
Builds the SOAP message and parses the response for fault
checking and other errors.
managed_object : Managed Object Reference or Managed
Object Name
**kwargs : Keyword arguments of the call
"""
# Dynamic handler for VI SDK Calls
try:
request_mo = \
self._request_managed_object_builder(managed_object)
request = getattr(self.client.service, attr_name)
response = request(request_mo, **kwargs)
# To check for the faults that are part of the message body
# and not returned as Fault object response from the ESX
# SOAP server
if hasattr(error_util.FaultCheckers,
attr_name.lower() + "_fault_checker"):
fault_checker = getattr(error_util.FaultCheckers,
attr_name.lower() + "_fault_checker")
fault_checker(response)
return response
# Catch the VimFaultException that is raised by the fault
# check of the SOAP response
except error_util.VimFaultException, excep:
raise
except suds.WebFault, excep:
doc = excep.document
detail = doc.childAtPath("/Envelope/Body/Fault/detail")
fault_list = []
for child in detail.getChildren():
fault_list.append(child.get("type"))
raise error_util.VimFaultException(fault_list, excep)
except AttributeError, excep:
raise error_util.VimAttributeError(_("No such SOAP method "
"'%s' provided by VI SDK") % (attr_name), excep)
except (httplib.CannotSendRequest,
httplib.ResponseNotReady,
httplib.CannotSendHeader), excep:
raise error_util.SessionOverLoadException(_("httplib "
"error in %s: ") % (attr_name), excep)
except Exception, excep:
# Socket errors which need special handling for they
# might be caused by ESX API call overload
if (str(excep).find(ADDRESS_IN_USE_ERROR) != -1 or
str(excep).find(CONN_ABORT_ERROR)) != -1:
raise error_util.SessionOverLoadException(_("Socket "
"error in %s: ") % (attr_name), excep)
# Type error that needs special handling for it might be
# caused by ESX host API call overload
elif str(excep).find(RESP_NOT_XML_ERROR) != -1:
raise error_util.SessionOverLoadException(_("Type "
"error in %s: ") % (attr_name), excep)
else:
raise error_util.VimException(
_("Exception in %s ") % (attr_name), excep)
return vim_request_handler
def _request_managed_object_builder(self, managed_object):
"""Builds the request managed object."""
# Request Managed Object Builder
if isinstance(managed_object, str):
mo = suds.sudsobject.Property(managed_object)
mo._type = managed_object
else:
mo = managed_object
return mo
def __repr__(self):
return "VIM Object"
def __str__(self):
return "VIM Object"
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Classes for making VMware VI SOAP calls.
"""
import httplib
try:
import suds
except ImportError:
suds = None
from nova import flags
from nova.virt.vmwareapi import error_util
RESP_NOT_XML_ERROR = 'Response is "text/html", not "text/xml"'
CONN_ABORT_ERROR = 'Software caused connection abort'
ADDRESS_IN_USE_ERROR = 'Address already in use'
FLAGS = flags.FLAGS
flags.DEFINE_string('vmwareapi_wsdl_loc',
None,
'VIM Service WSDL Location'
'e.g http://<server>/vimService.wsdl'
'Due to a bug in vSphere ESX 4.1 default wsdl'
'Refer readme-vmware to setup')
if suds:
class VIMMessagePlugin(suds.plugin.MessagePlugin):
def addAttributeForValue(self, node):
# suds does not handle AnyType properly.
# VI SDK requires type attribute to be set when AnyType is used
if node.name == 'value':
node.set('xsi:type', 'xsd:string')
def marshalled(self, context):
"""suds will send the specified soap envelope.
Provides the plugin with the opportunity to prune empty
nodes and fixup nodes before sending it to the server.
"""
# suds builds the entire request object based on the wsdl schema.
# VI SDK throws server errors if optional SOAP nodes are sent
# without values, e.g. <test/> as opposed to <test>test</test>
context.envelope.prune()
context.envelope.walk(self.addAttributeForValue)
class Vim:
"""The VIM Object."""
def __init__(self,
protocol="https",
host="localhost"):
"""
Creates the necessary Communication interfaces and gets the
ServiceContent for initiating SOAP transactions.
protocol: http or https
host : ESX IPAddress[:port] or ESX Hostname[:port]
"""
if not suds:
raise Exception(_("Unable to import suds."))
self._protocol = protocol
self._host_name = host
wsdl_url = FLAGS.vmwareapi_wsdl_loc
if wsdl_url is None:
raise Exception(_("Must specify vmwareapi_wsdl_loc"))
# TODO(sateesh): Use this when VMware fixes their faulty wsdl
#wsdl_url = '%s://%s/sdk/vimService.wsdl' % (self._protocol,
# self._host_name)
url = '%s://%s/sdk' % (self._protocol, self._host_name)
self.client = suds.client.Client(wsdl_url, location=url,
plugins=[VIMMessagePlugin()])
self._service_content = \
self.RetrieveServiceContent("ServiceInstance")
def get_service_content(self):
"""Gets the service content object."""
return self._service_content
def __getattr__(self, attr_name):
"""Makes the API calls and gets the result."""
try:
return object.__getattr__(self, attr_name)
except AttributeError:
def vim_request_handler(managed_object, **kwargs):
"""
Builds the SOAP message and parses the response for fault
checking and other errors.
managed_object : Managed Object Reference or Managed
Object Name
**kwargs : Keyword arguments of the call
"""
# Dynamic handler for VI SDK Calls
try:
request_mo = \
self._request_managed_object_builder(managed_object)
request = getattr(self.client.service, attr_name)
response = request(request_mo, **kwargs)
# To check for the faults that are part of the message body
# and not returned as Fault object response from the ESX
# SOAP server
if hasattr(error_util.FaultCheckers,
attr_name.lower() + "_fault_checker"):
fault_checker = getattr(error_util.FaultCheckers,
attr_name.lower() + "_fault_checker")
fault_checker(response)
return response
# Catch the VimFaultException that is raised by the fault
# check of the SOAP response
except error_util.VimFaultException, excep:
raise
except suds.WebFault, excep:
doc = excep.document
detail = doc.childAtPath("/Envelope/Body/Fault/detail")
fault_list = []
for child in detail.getChildren():
fault_list.append(child.get("type"))
raise error_util.VimFaultException(fault_list, excep)
except AttributeError, excep:
raise error_util.VimAttributeError(_("No such SOAP method "
"'%s' provided by VI SDK") % (attr_name), excep)
except (httplib.CannotSendRequest,
httplib.ResponseNotReady,
httplib.CannotSendHeader), excep:
raise error_util.SessionOverLoadException(_("httplib "
"error in %s: ") % (attr_name), excep)
except Exception, excep:
# Socket errors which need special handling for they
# might be caused by ESX API call overload
if (str(excep).find(ADDRESS_IN_USE_ERROR) != -1 or
str(excep).find(CONN_ABORT_ERROR)) != -1:
raise error_util.SessionOverLoadException(_("Socket "
"error in %s: ") % (attr_name), excep)
# Type error that needs special handling for it might be
# caused by ESX host API call overload
elif str(excep).find(RESP_NOT_XML_ERROR) != -1:
raise error_util.SessionOverLoadException(_("Type "
"error in %s: ") % (attr_name), excep)
else:
raise error_util.VimException(
_("Exception in %s ") % (attr_name), excep)
return vim_request_handler
def _request_managed_object_builder(self, managed_object):
"""Builds the request managed object."""
# Request Managed Object Builder
if isinstance(managed_object, str):
mo = suds.sudsobject.Property(managed_object)
mo._type = managed_object
else:
mo = managed_object
return mo
def __repr__(self):
return "VIM Object"
def __str__(self):
return "VIM Object"

View File

@ -1,223 +1,223 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
The VMware API utility module.
"""
def build_selection_spec(client_factory, name):
"""Builds the selection spec."""
sel_spec = client_factory.create('ns0:SelectionSpec')
sel_spec.name = name
return sel_spec
def build_traversal_spec(client_factory, name, spec_type, path, skip,
select_set):
"""Builds the traversal spec object."""
traversal_spec = client_factory.create('ns0:TraversalSpec')
traversal_spec.name = name
traversal_spec.type = spec_type
traversal_spec.path = path
traversal_spec.skip = skip
traversal_spec.selectSet = select_set
return traversal_spec
def build_recursive_traversal_spec(client_factory):
"""
Builds the Recursive Traversal Spec to traverse the object managed
object hierarchy.
"""
visit_folders_select_spec = build_selection_spec(client_factory,
"visitFolders")
# For getting to hostFolder from datacenter
dc_to_hf = build_traversal_spec(client_factory, "dc_to_hf", "Datacenter",
"hostFolder", False,
[visit_folders_select_spec])
# For getting to vmFolder from datacenter
dc_to_vmf = build_traversal_spec(client_factory, "dc_to_vmf", "Datacenter",
"vmFolder", False,
[visit_folders_select_spec])
# For getting Host System to virtual machine
h_to_vm = build_traversal_spec(client_factory, "h_to_vm", "HostSystem",
"vm", False,
[visit_folders_select_spec])
# For getting to Host System from Compute Resource
cr_to_h = build_traversal_spec(client_factory, "cr_to_h",
"ComputeResource", "host", False, [])
# For getting to datastore from Compute Resource
cr_to_ds = build_traversal_spec(client_factory, "cr_to_ds",
"ComputeResource", "datastore", False, [])
rp_to_rp_select_spec = build_selection_spec(client_factory, "rp_to_rp")
rp_to_vm_select_spec = build_selection_spec(client_factory, "rp_to_vm")
# For getting to resource pool from Compute Resource
cr_to_rp = build_traversal_spec(client_factory, "cr_to_rp",
"ComputeResource", "resourcePool", False,
[rp_to_rp_select_spec, rp_to_vm_select_spec])
# For getting to child res pool from the parent res pool
rp_to_rp = build_traversal_spec(client_factory, "rp_to_rp", "ResourcePool",
"resourcePool", False,
[rp_to_rp_select_spec, rp_to_vm_select_spec])
# For getting to Virtual Machine from the Resource Pool
rp_to_vm = build_traversal_spec(client_factory, "rp_to_vm", "ResourcePool",
"vm", False,
[rp_to_rp_select_spec, rp_to_vm_select_spec])
# Get the assorted traversal spec which takes care of the objects to
# be searched for from the root folder
traversal_spec = build_traversal_spec(client_factory, "visitFolders",
"Folder", "childEntity", False,
[visit_folders_select_spec, dc_to_hf,
dc_to_vmf, cr_to_ds, cr_to_h, cr_to_rp,
rp_to_rp, h_to_vm, rp_to_vm])
return traversal_spec
def build_property_spec(client_factory, type="VirtualMachine",
properties_to_collect=None,
all_properties=False):
"""Builds the Property Spec."""
if not properties_to_collect:
properties_to_collect = ["name"]
property_spec = client_factory.create('ns0:PropertySpec')
property_spec.all = all_properties
property_spec.pathSet = properties_to_collect
property_spec.type = type
return property_spec
def build_object_spec(client_factory, root_folder, traversal_specs):
"""Builds the object Spec."""
object_spec = client_factory.create('ns0:ObjectSpec')
object_spec.obj = root_folder
object_spec.skip = False
object_spec.selectSet = traversal_specs
return object_spec
def build_property_filter_spec(client_factory, property_specs, object_specs):
"""Builds the Property Filter Spec."""
property_filter_spec = client_factory.create('ns0:PropertyFilterSpec')
property_filter_spec.propSet = property_specs
property_filter_spec.objectSet = object_specs
return property_filter_spec
def get_object_properties(vim, collector, mobj, type, properties):
"""Gets the properties of the Managed object specified."""
client_factory = vim.client.factory
if mobj is None:
return None
usecoll = collector
if usecoll is None:
usecoll = vim.get_service_content().propertyCollector
property_filter_spec = client_factory.create('ns0:PropertyFilterSpec')
property_spec = client_factory.create('ns0:PropertySpec')
property_spec.all = (properties is None or len(properties) == 0)
property_spec.pathSet = properties
property_spec.type = type
object_spec = client_factory.create('ns0:ObjectSpec')
object_spec.obj = mobj
object_spec.skip = False
property_filter_spec.propSet = [property_spec]
property_filter_spec.objectSet = [object_spec]
return vim.RetrieveProperties(usecoll, specSet=[property_filter_spec])
def get_dynamic_property(vim, mobj, type, property_name):
"""Gets a particular property of the Managed Object."""
obj_content = \
get_object_properties(vim, None, mobj, type, [property_name])
property_value = None
if obj_content:
dynamic_property = obj_content[0].propSet
if dynamic_property:
property_value = dynamic_property[0].val
return property_value
def get_objects(vim, type, properties_to_collect=None, all=False):
"""Gets the list of objects of the type specified."""
if not properties_to_collect:
properties_to_collect = ["name"]
client_factory = vim.client.factory
object_spec = build_object_spec(client_factory,
vim.get_service_content().rootFolder,
[build_recursive_traversal_spec(client_factory)])
property_spec = build_property_spec(client_factory, type=type,
properties_to_collect=properties_to_collect,
all_properties=all)
property_filter_spec = build_property_filter_spec(client_factory,
[property_spec],
[object_spec])
return vim.RetrieveProperties(vim.get_service_content().propertyCollector,
specSet=[property_filter_spec])
def get_prop_spec(client_factory, spec_type, properties):
"""Builds the Property Spec Object."""
prop_spec = client_factory.create('ns0:PropertySpec')
prop_spec.type = spec_type
prop_spec.pathSet = properties
return prop_spec
def get_obj_spec(client_factory, obj, select_set=None):
"""Builds the Object Spec object."""
obj_spec = client_factory.create('ns0:ObjectSpec')
obj_spec.obj = obj
obj_spec.skip = False
if select_set is not None:
obj_spec.selectSet = select_set
return obj_spec
def get_prop_filter_spec(client_factory, obj_spec, prop_spec):
"""Builds the Property Filter Spec Object."""
prop_filter_spec = \
client_factory.create('ns0:PropertyFilterSpec')
prop_filter_spec.propSet = prop_spec
prop_filter_spec.objectSet = obj_spec
return prop_filter_spec
def get_properties_for_a_collection_of_objects(vim, type,
obj_list, properties):
"""
Gets the list of properties for the collection of
objects of the type specified.
"""
client_factory = vim.client.factory
if len(obj_list) == 0:
return []
prop_spec = get_prop_spec(client_factory, type, properties)
lst_obj_specs = []
for obj in obj_list:
lst_obj_specs.append(get_obj_spec(client_factory, obj))
prop_filter_spec = get_prop_filter_spec(client_factory,
lst_obj_specs, [prop_spec])
return vim.RetrieveProperties(vim.get_service_content().propertyCollector,
specSet=[prop_filter_spec])
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
The VMware API utility module.
"""
def build_selection_spec(client_factory, name):
"""Builds the selection spec."""
sel_spec = client_factory.create('ns0:SelectionSpec')
sel_spec.name = name
return sel_spec
def build_traversal_spec(client_factory, name, spec_type, path, skip,
select_set):
"""Builds the traversal spec object."""
traversal_spec = client_factory.create('ns0:TraversalSpec')
traversal_spec.name = name
traversal_spec.type = spec_type
traversal_spec.path = path
traversal_spec.skip = skip
traversal_spec.selectSet = select_set
return traversal_spec
def build_recursive_traversal_spec(client_factory):
"""
Builds the Recursive Traversal Spec to traverse the object managed
object hierarchy.
"""
visit_folders_select_spec = build_selection_spec(client_factory,
"visitFolders")
# For getting to hostFolder from datacenter
dc_to_hf = build_traversal_spec(client_factory, "dc_to_hf", "Datacenter",
"hostFolder", False,
[visit_folders_select_spec])
# For getting to vmFolder from datacenter
dc_to_vmf = build_traversal_spec(client_factory, "dc_to_vmf", "Datacenter",
"vmFolder", False,
[visit_folders_select_spec])
# For getting Host System to virtual machine
h_to_vm = build_traversal_spec(client_factory, "h_to_vm", "HostSystem",
"vm", False,
[visit_folders_select_spec])
# For getting to Host System from Compute Resource
cr_to_h = build_traversal_spec(client_factory, "cr_to_h",
"ComputeResource", "host", False, [])
# For getting to datastore from Compute Resource
cr_to_ds = build_traversal_spec(client_factory, "cr_to_ds",
"ComputeResource", "datastore", False, [])
rp_to_rp_select_spec = build_selection_spec(client_factory, "rp_to_rp")
rp_to_vm_select_spec = build_selection_spec(client_factory, "rp_to_vm")
# For getting to resource pool from Compute Resource
cr_to_rp = build_traversal_spec(client_factory, "cr_to_rp",
"ComputeResource", "resourcePool", False,
[rp_to_rp_select_spec, rp_to_vm_select_spec])
# For getting to child res pool from the parent res pool
rp_to_rp = build_traversal_spec(client_factory, "rp_to_rp", "ResourcePool",
"resourcePool", False,
[rp_to_rp_select_spec, rp_to_vm_select_spec])
# For getting to Virtual Machine from the Resource Pool
rp_to_vm = build_traversal_spec(client_factory, "rp_to_vm", "ResourcePool",
"vm", False,
[rp_to_rp_select_spec, rp_to_vm_select_spec])
# Get the assorted traversal spec which takes care of the objects to
# be searched for from the root folder
traversal_spec = build_traversal_spec(client_factory, "visitFolders",
"Folder", "childEntity", False,
[visit_folders_select_spec, dc_to_hf,
dc_to_vmf, cr_to_ds, cr_to_h, cr_to_rp,
rp_to_rp, h_to_vm, rp_to_vm])
return traversal_spec
def build_property_spec(client_factory, type="VirtualMachine",
properties_to_collect=None,
all_properties=False):
"""Builds the Property Spec."""
if not properties_to_collect:
properties_to_collect = ["name"]
property_spec = client_factory.create('ns0:PropertySpec')
property_spec.all = all_properties
property_spec.pathSet = properties_to_collect
property_spec.type = type
return property_spec
def build_object_spec(client_factory, root_folder, traversal_specs):
"""Builds the object Spec."""
object_spec = client_factory.create('ns0:ObjectSpec')
object_spec.obj = root_folder
object_spec.skip = False
object_spec.selectSet = traversal_specs
return object_spec
def build_property_filter_spec(client_factory, property_specs, object_specs):
"""Builds the Property Filter Spec."""
property_filter_spec = client_factory.create('ns0:PropertyFilterSpec')
property_filter_spec.propSet = property_specs
property_filter_spec.objectSet = object_specs
return property_filter_spec
def get_object_properties(vim, collector, mobj, type, properties):
"""Gets the properties of the Managed object specified."""
client_factory = vim.client.factory
if mobj is None:
return None
usecoll = collector
if usecoll is None:
usecoll = vim.get_service_content().propertyCollector
property_filter_spec = client_factory.create('ns0:PropertyFilterSpec')
property_spec = client_factory.create('ns0:PropertySpec')
property_spec.all = (properties is None or len(properties) == 0)
property_spec.pathSet = properties
property_spec.type = type
object_spec = client_factory.create('ns0:ObjectSpec')
object_spec.obj = mobj
object_spec.skip = False
property_filter_spec.propSet = [property_spec]
property_filter_spec.objectSet = [object_spec]
return vim.RetrieveProperties(usecoll, specSet=[property_filter_spec])
def get_dynamic_property(vim, mobj, type, property_name):
"""Gets a particular property of the Managed Object."""
obj_content = \
get_object_properties(vim, None, mobj, type, [property_name])
property_value = None
if obj_content:
dynamic_property = obj_content[0].propSet
if dynamic_property:
property_value = dynamic_property[0].val
return property_value
def get_objects(vim, type, properties_to_collect=None, all=False):
"""Gets the list of objects of the type specified."""
if not properties_to_collect:
properties_to_collect = ["name"]
client_factory = vim.client.factory
object_spec = build_object_spec(client_factory,
vim.get_service_content().rootFolder,
[build_recursive_traversal_spec(client_factory)])
property_spec = build_property_spec(client_factory, type=type,
properties_to_collect=properties_to_collect,
all_properties=all)
property_filter_spec = build_property_filter_spec(client_factory,
[property_spec],
[object_spec])
return vim.RetrieveProperties(vim.get_service_content().propertyCollector,
specSet=[property_filter_spec])
def get_prop_spec(client_factory, spec_type, properties):
"""Builds the Property Spec Object."""
prop_spec = client_factory.create('ns0:PropertySpec')
prop_spec.type = spec_type
prop_spec.pathSet = properties
return prop_spec
def get_obj_spec(client_factory, obj, select_set=None):
"""Builds the Object Spec object."""
obj_spec = client_factory.create('ns0:ObjectSpec')
obj_spec.obj = obj
obj_spec.skip = False
if select_set is not None:
obj_spec.selectSet = select_set
return obj_spec
def get_prop_filter_spec(client_factory, obj_spec, prop_spec):
"""Builds the Property Filter Spec Object."""
prop_filter_spec = \
client_factory.create('ns0:PropertyFilterSpec')
prop_filter_spec.propSet = prop_spec
prop_filter_spec.objectSet = obj_spec
return prop_filter_spec
def get_properties_for_a_collection_of_objects(vim, type,
obj_list, properties):
"""
Gets the list of properties for the collection of
objects of the type specified.
"""
client_factory = vim.client.factory
if len(obj_list) == 0:
return []
prop_spec = get_prop_spec(client_factory, type, properties)
lst_obj_specs = []
for obj in obj_list:
lst_obj_specs.append(get_obj_spec(client_factory, obj))
prop_filter_spec = get_prop_filter_spec(client_factory,
lst_obj_specs, [prop_spec])
return vim.RetrieveProperties(vim.get_service_content().propertyCollector,
specSet=[prop_filter_spec])

View File

@ -1,325 +1,325 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
The VMware API VM utility module to build SOAP object specs.
"""
def build_datastore_path(datastore_name, path):
"""Build the datastore compliant path."""
return "[%s] %s" % (datastore_name, path)
def split_datastore_path(datastore_path):
"""
Split the VMWare style datastore path to get the Datastore
name and the entity path.
"""
spl = datastore_path.split('[', 1)[1].split(']', 1)
path = ""
if len(spl) == 1:
datastore_url = spl[0]
else:
datastore_url, path = spl
return datastore_url, path.strip()
def get_vm_create_spec(client_factory, instance, data_store_name,
vif_infos, os_type="otherGuest"):
"""Builds the VM Create spec."""
config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
config_spec.name = instance.name
config_spec.guestId = os_type
vm_file_info = client_factory.create('ns0:VirtualMachineFileInfo')
vm_file_info.vmPathName = "[" + data_store_name + "]"
config_spec.files = vm_file_info
tools_info = client_factory.create('ns0:ToolsConfigInfo')
tools_info.afterPowerOn = True
tools_info.afterResume = True
tools_info.beforeGuestStandby = True
tools_info.beforeGuestShutdown = True
tools_info.beforeGuestReboot = True
config_spec.tools = tools_info
config_spec.numCPUs = int(instance.vcpus)
config_spec.memoryMB = int(instance.memory_mb)
vif_spec_list = []
for vif_info in vif_infos:
vif_spec = create_network_spec(client_factory, vif_info)
vif_spec_list.append(vif_spec)
device_config_spec = vif_spec_list
config_spec.deviceChange = device_config_spec
return config_spec
def create_controller_spec(client_factory, key):
"""
Builds a Config Spec for the LSI Logic Controller's addition
which acts as the controller for the virtual hard disk to be attached
to the VM.
"""
# Create a controller for the Virtual Hard Disk
virtual_device_config = \
client_factory.create('ns0:VirtualDeviceConfigSpec')
virtual_device_config.operation = "add"
virtual_lsi = \
client_factory.create('ns0:VirtualLsiLogicController')
virtual_lsi.key = key
virtual_lsi.busNumber = 0
virtual_lsi.sharedBus = "noSharing"
virtual_device_config.device = virtual_lsi
return virtual_device_config
def create_network_spec(client_factory, vif_info):
"""
Builds a config spec for the addition of a new network
adapter to the VM.
"""
network_spec = \
client_factory.create('ns0:VirtualDeviceConfigSpec')
network_spec.operation = "add"
# Get the recommended card type for the VM based on the guest OS of the VM
net_device = client_factory.create('ns0:VirtualPCNet32')
# NOTE(asomya): Only works on ESXi if the portgroup binding is set to
# ephemeral. Invalid configuration if set to static and the NIC does
# not come up on boot if set to dynamic.
network_ref = vif_info['network_ref']
network_name = vif_info['network_name']
mac_address = vif_info['mac_address']
backing = None
if (network_ref and
network_ref['type'] == "DistributedVirtualPortgroup"):
backing_name = \
'ns0:VirtualEthernetCardDistributedVirtualPortBackingInfo'
backing = \
client_factory.create(backing_name)
portgroup = \
client_factory.create('ns0:DistributedVirtualSwitchPortConnection')
portgroup.switchUuid = network_ref['dvsw']
portgroup.portgroupKey = network_ref['dvpg']
backing.port = portgroup
else:
backing = \
client_factory.create('ns0:VirtualEthernetCardNetworkBackingInfo')
backing.deviceName = network_name
connectable_spec = \
client_factory.create('ns0:VirtualDeviceConnectInfo')
connectable_spec.startConnected = True
connectable_spec.allowGuestControl = True
connectable_spec.connected = True
net_device.connectable = connectable_spec
net_device.backing = backing
# The Server assigns a Key to the device. Here we pass a -ve temporary key.
# -ve because actual keys are +ve numbers and we don't
# want a clash with the key that server might associate with the device
net_device.key = -47
net_device.addressType = "manual"
net_device.macAddress = mac_address
net_device.wakeOnLanEnabled = True
network_spec.device = net_device
return network_spec
def get_vmdk_attach_config_spec(client_factory, disksize, file_path,
adapter_type="lsiLogic"):
"""Builds the vmdk attach config spec."""
config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
# The controller Key pertains to the Key of the LSI Logic Controller, which
# controls this Hard Disk
device_config_spec = []
# For IDE devices, there are these two default controllers created in the
# VM having keys 200 and 201
if adapter_type == "ide":
controller_key = 200
else:
controller_key = -101
controller_spec = create_controller_spec(client_factory,
controller_key)
device_config_spec.append(controller_spec)
virtual_device_config_spec = create_virtual_disk_spec(client_factory,
disksize, controller_key, file_path)
device_config_spec.append(virtual_device_config_spec)
config_spec.deviceChange = device_config_spec
return config_spec
def get_vmdk_file_path_and_adapter_type(client_factory, hardware_devices):
"""Gets the vmdk file path and the storage adapter type."""
if hardware_devices.__class__.__name__ == "ArrayOfVirtualDevice":
hardware_devices = hardware_devices.VirtualDevice
vmdk_file_path = None
vmdk_controler_key = None
adapter_type_dict = {}
for device in hardware_devices:
if device.__class__.__name__ == "VirtualDisk" and \
device.backing.__class__.__name__ \
== "VirtualDiskFlatVer2BackingInfo":
vmdk_file_path = device.backing.fileName
vmdk_controler_key = device.controllerKey
elif device.__class__.__name__ == "VirtualLsiLogicController":
adapter_type_dict[device.key] = "lsiLogic"
elif device.__class__.__name__ == "VirtualBusLogicController":
adapter_type_dict[device.key] = "busLogic"
elif device.__class__.__name__ == "VirtualIDEController":
adapter_type_dict[device.key] = "ide"
elif device.__class__.__name__ == "VirtualLsiLogicSASController":
adapter_type_dict[device.key] = "lsiLogic"
adapter_type = adapter_type_dict.get(vmdk_controler_key, "")
return vmdk_file_path, adapter_type
def get_copy_virtual_disk_spec(client_factory, adapter_type="lsilogic"):
"""Builds the Virtual Disk copy spec."""
dest_spec = client_factory.create('ns0:VirtualDiskSpec')
dest_spec.adapterType = adapter_type
dest_spec.diskType = "thick"
return dest_spec
def get_vmdk_create_spec(client_factory, size_in_kb, adapter_type="lsiLogic"):
"""Builds the virtual disk create spec."""
create_vmdk_spec = \
client_factory.create('ns0:FileBackedVirtualDiskSpec')
create_vmdk_spec.adapterType = adapter_type
create_vmdk_spec.diskType = "thick"
create_vmdk_spec.capacityKb = size_in_kb
return create_vmdk_spec
def create_virtual_disk_spec(client_factory, disksize, controller_key,
file_path=None):
"""
Builds spec for the creation of a new/ attaching of an already existing
Virtual Disk to the VM.
"""
virtual_device_config = \
client_factory.create('ns0:VirtualDeviceConfigSpec')
virtual_device_config.operation = "add"
if file_path is None:
virtual_device_config.fileOperation = "create"
virtual_disk = client_factory.create('ns0:VirtualDisk')
disk_file_backing = \
client_factory.create('ns0:VirtualDiskFlatVer2BackingInfo')
disk_file_backing.diskMode = "persistent"
disk_file_backing.thinProvisioned = False
if file_path is not None:
disk_file_backing.fileName = file_path
else:
disk_file_backing.fileName = ""
connectable_spec = client_factory.create('ns0:VirtualDeviceConnectInfo')
connectable_spec.startConnected = True
connectable_spec.allowGuestControl = False
connectable_spec.connected = True
virtual_disk.backing = disk_file_backing
virtual_disk.connectable = connectable_spec
# The Server assigns a Key to the device. Here we pass a -ve random key.
# -ve because actual keys are +ve numbers and we don't
# want a clash with the key that server might associate with the device
virtual_disk.key = -100
virtual_disk.controllerKey = controller_key
virtual_disk.unitNumber = 0
virtual_disk.capacityInKB = disksize
virtual_device_config.device = virtual_disk
return virtual_device_config
def get_dummy_vm_create_spec(client_factory, name, data_store_name):
"""Builds the dummy VM create spec."""
config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
config_spec.name = name
config_spec.guestId = "otherGuest"
vm_file_info = client_factory.create('ns0:VirtualMachineFileInfo')
vm_file_info.vmPathName = "[" + data_store_name + "]"
config_spec.files = vm_file_info
tools_info = client_factory.create('ns0:ToolsConfigInfo')
tools_info.afterPowerOn = True
tools_info.afterResume = True
tools_info.beforeGuestStandby = True
tools_info.beforeGuestShutdown = True
tools_info.beforeGuestReboot = True
config_spec.tools = tools_info
config_spec.numCPUs = 1
config_spec.memoryMB = 4
controller_key = -101
controller_spec = create_controller_spec(client_factory, controller_key)
disk_spec = create_virtual_disk_spec(client_factory, 1024, controller_key)
device_config_spec = [controller_spec, disk_spec]
config_spec.deviceChange = device_config_spec
return config_spec
def get_machine_id_change_spec(client_factory, machine_id_str):
"""Builds the machine id change config spec."""
virtual_machine_config_spec = \
client_factory.create('ns0:VirtualMachineConfigSpec')
opt = client_factory.create('ns0:OptionValue')
opt.key = "machine.id"
opt.value = machine_id_str
virtual_machine_config_spec.extraConfig = [opt]
return virtual_machine_config_spec
def get_add_vswitch_port_group_spec(client_factory, vswitch_name,
port_group_name, vlan_id):
"""Builds the virtual switch port group add spec."""
vswitch_port_group_spec = client_factory.create('ns0:HostPortGroupSpec')
vswitch_port_group_spec.name = port_group_name
vswitch_port_group_spec.vswitchName = vswitch_name
# VLAN ID of 0 means that VLAN tagging is not to be done for the network.
vswitch_port_group_spec.vlanId = int(vlan_id)
policy = client_factory.create('ns0:HostNetworkPolicy')
nicteaming = client_factory.create('ns0:HostNicTeamingPolicy')
nicteaming.notifySwitches = True
policy.nicTeaming = nicteaming
vswitch_port_group_spec.policy = policy
return vswitch_port_group_spec
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
The VMware API VM utility module to build SOAP object specs.
"""
def build_datastore_path(datastore_name, path):
"""Build the datastore compliant path."""
return "[%s] %s" % (datastore_name, path)
def split_datastore_path(datastore_path):
"""
Split the VMWare style datastore path to get the Datastore
name and the entity path.
"""
spl = datastore_path.split('[', 1)[1].split(']', 1)
path = ""
if len(spl) == 1:
datastore_url = spl[0]
else:
datastore_url, path = spl
return datastore_url, path.strip()
def get_vm_create_spec(client_factory, instance, data_store_name,
vif_infos, os_type="otherGuest"):
"""Builds the VM Create spec."""
config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
config_spec.name = instance.name
config_spec.guestId = os_type
vm_file_info = client_factory.create('ns0:VirtualMachineFileInfo')
vm_file_info.vmPathName = "[" + data_store_name + "]"
config_spec.files = vm_file_info
tools_info = client_factory.create('ns0:ToolsConfigInfo')
tools_info.afterPowerOn = True
tools_info.afterResume = True
tools_info.beforeGuestStandby = True
tools_info.beforeGuestShutdown = True
tools_info.beforeGuestReboot = True
config_spec.tools = tools_info
config_spec.numCPUs = int(instance.vcpus)
config_spec.memoryMB = int(instance.memory_mb)
vif_spec_list = []
for vif_info in vif_infos:
vif_spec = create_network_spec(client_factory, vif_info)
vif_spec_list.append(vif_spec)
device_config_spec = vif_spec_list
config_spec.deviceChange = device_config_spec
return config_spec
def create_controller_spec(client_factory, key):
"""
Builds a Config Spec for the LSI Logic Controller's addition
which acts as the controller for the virtual hard disk to be attached
to the VM.
"""
# Create a controller for the Virtual Hard Disk
virtual_device_config = \
client_factory.create('ns0:VirtualDeviceConfigSpec')
virtual_device_config.operation = "add"
virtual_lsi = \
client_factory.create('ns0:VirtualLsiLogicController')
virtual_lsi.key = key
virtual_lsi.busNumber = 0
virtual_lsi.sharedBus = "noSharing"
virtual_device_config.device = virtual_lsi
return virtual_device_config
def create_network_spec(client_factory, vif_info):
"""
Builds a config spec for the addition of a new network
adapter to the VM.
"""
network_spec = \
client_factory.create('ns0:VirtualDeviceConfigSpec')
network_spec.operation = "add"
# Get the recommended card type for the VM based on the guest OS of the VM
net_device = client_factory.create('ns0:VirtualPCNet32')
# NOTE(asomya): Only works on ESXi if the portgroup binding is set to
# ephemeral. Invalid configuration if set to static and the NIC does
# not come up on boot if set to dynamic.
network_ref = vif_info['network_ref']
network_name = vif_info['network_name']
mac_address = vif_info['mac_address']
backing = None
if (network_ref and
network_ref['type'] == "DistributedVirtualPortgroup"):
backing_name = \
'ns0:VirtualEthernetCardDistributedVirtualPortBackingInfo'
backing = \
client_factory.create(backing_name)
portgroup = \
client_factory.create('ns0:DistributedVirtualSwitchPortConnection')
portgroup.switchUuid = network_ref['dvsw']
portgroup.portgroupKey = network_ref['dvpg']
backing.port = portgroup
else:
backing = \
client_factory.create('ns0:VirtualEthernetCardNetworkBackingInfo')
backing.deviceName = network_name
connectable_spec = \
client_factory.create('ns0:VirtualDeviceConnectInfo')
connectable_spec.startConnected = True
connectable_spec.allowGuestControl = True
connectable_spec.connected = True
net_device.connectable = connectable_spec
net_device.backing = backing
# The Server assigns a Key to the device. Here we pass a -ve temporary key.
# -ve because actual keys are +ve numbers and we don't
# want a clash with the key that server might associate with the device
net_device.key = -47
net_device.addressType = "manual"
net_device.macAddress = mac_address
net_device.wakeOnLanEnabled = True
network_spec.device = net_device
return network_spec
def get_vmdk_attach_config_spec(client_factory, disksize, file_path,
adapter_type="lsiLogic"):
"""Builds the vmdk attach config spec."""
config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
# The controller Key pertains to the Key of the LSI Logic Controller, which
# controls this Hard Disk
device_config_spec = []
# For IDE devices, there are these two default controllers created in the
# VM having keys 200 and 201
if adapter_type == "ide":
controller_key = 200
else:
controller_key = -101
controller_spec = create_controller_spec(client_factory,
controller_key)
device_config_spec.append(controller_spec)
virtual_device_config_spec = create_virtual_disk_spec(client_factory,
disksize, controller_key, file_path)
device_config_spec.append(virtual_device_config_spec)
config_spec.deviceChange = device_config_spec
return config_spec
def get_vmdk_file_path_and_adapter_type(client_factory, hardware_devices):
"""Gets the vmdk file path and the storage adapter type."""
if hardware_devices.__class__.__name__ == "ArrayOfVirtualDevice":
hardware_devices = hardware_devices.VirtualDevice
vmdk_file_path = None
vmdk_controler_key = None
adapter_type_dict = {}
for device in hardware_devices:
if device.__class__.__name__ == "VirtualDisk" and \
device.backing.__class__.__name__ \
== "VirtualDiskFlatVer2BackingInfo":
vmdk_file_path = device.backing.fileName
vmdk_controler_key = device.controllerKey
elif device.__class__.__name__ == "VirtualLsiLogicController":
adapter_type_dict[device.key] = "lsiLogic"
elif device.__class__.__name__ == "VirtualBusLogicController":
adapter_type_dict[device.key] = "busLogic"
elif device.__class__.__name__ == "VirtualIDEController":
adapter_type_dict[device.key] = "ide"
elif device.__class__.__name__ == "VirtualLsiLogicSASController":
adapter_type_dict[device.key] = "lsiLogic"
adapter_type = adapter_type_dict.get(vmdk_controler_key, "")
return vmdk_file_path, adapter_type
def get_copy_virtual_disk_spec(client_factory, adapter_type="lsilogic"):
"""Builds the Virtual Disk copy spec."""
dest_spec = client_factory.create('ns0:VirtualDiskSpec')
dest_spec.adapterType = adapter_type
dest_spec.diskType = "thick"
return dest_spec
def get_vmdk_create_spec(client_factory, size_in_kb, adapter_type="lsiLogic"):
"""Builds the virtual disk create spec."""
create_vmdk_spec = \
client_factory.create('ns0:FileBackedVirtualDiskSpec')
create_vmdk_spec.adapterType = adapter_type
create_vmdk_spec.diskType = "thick"
create_vmdk_spec.capacityKb = size_in_kb
return create_vmdk_spec
def create_virtual_disk_spec(client_factory, disksize, controller_key,
file_path=None):
"""
Builds spec for the creation of a new/ attaching of an already existing
Virtual Disk to the VM.
"""
virtual_device_config = \
client_factory.create('ns0:VirtualDeviceConfigSpec')
virtual_device_config.operation = "add"
if file_path is None:
virtual_device_config.fileOperation = "create"
virtual_disk = client_factory.create('ns0:VirtualDisk')
disk_file_backing = \
client_factory.create('ns0:VirtualDiskFlatVer2BackingInfo')
disk_file_backing.diskMode = "persistent"
disk_file_backing.thinProvisioned = False
if file_path is not None:
disk_file_backing.fileName = file_path
else:
disk_file_backing.fileName = ""
connectable_spec = client_factory.create('ns0:VirtualDeviceConnectInfo')
connectable_spec.startConnected = True
connectable_spec.allowGuestControl = False
connectable_spec.connected = True
virtual_disk.backing = disk_file_backing
virtual_disk.connectable = connectable_spec
# The Server assigns a Key to the device. Here we pass a -ve random key.
# -ve because actual keys are +ve numbers and we don't
# want a clash with the key that server might associate with the device
virtual_disk.key = -100
virtual_disk.controllerKey = controller_key
virtual_disk.unitNumber = 0
virtual_disk.capacityInKB = disksize
virtual_device_config.device = virtual_disk
return virtual_device_config
def get_dummy_vm_create_spec(client_factory, name, data_store_name):
"""Builds the dummy VM create spec."""
config_spec = client_factory.create('ns0:VirtualMachineConfigSpec')
config_spec.name = name
config_spec.guestId = "otherGuest"
vm_file_info = client_factory.create('ns0:VirtualMachineFileInfo')
vm_file_info.vmPathName = "[" + data_store_name + "]"
config_spec.files = vm_file_info
tools_info = client_factory.create('ns0:ToolsConfigInfo')
tools_info.afterPowerOn = True
tools_info.afterResume = True
tools_info.beforeGuestStandby = True
tools_info.beforeGuestShutdown = True
tools_info.beforeGuestReboot = True
config_spec.tools = tools_info
config_spec.numCPUs = 1
config_spec.memoryMB = 4
controller_key = -101
controller_spec = create_controller_spec(client_factory, controller_key)
disk_spec = create_virtual_disk_spec(client_factory, 1024, controller_key)
device_config_spec = [controller_spec, disk_spec]
config_spec.deviceChange = device_config_spec
return config_spec
def get_machine_id_change_spec(client_factory, machine_id_str):
"""Builds the machine id change config spec."""
virtual_machine_config_spec = \
client_factory.create('ns0:VirtualMachineConfigSpec')
opt = client_factory.create('ns0:OptionValue')
opt.key = "machine.id"
opt.value = machine_id_str
virtual_machine_config_spec.extraConfig = [opt]
return virtual_machine_config_spec
def get_add_vswitch_port_group_spec(client_factory, vswitch_name,
port_group_name, vlan_id):
"""Builds the virtual switch port group add spec."""
vswitch_port_group_spec = client_factory.create('ns0:HostPortGroupSpec')
vswitch_port_group_spec.name = port_group_name
vswitch_port_group_spec.vswitchName = vswitch_name
# VLAN ID of 0 means that VLAN tagging is not to be done for the network.
vswitch_port_group_spec.vlanId = int(vlan_id)
policy = client_factory.create('ns0:HostNetworkPolicy')
nicteaming = client_factory.create('ns0:HostNicTeamingPolicy')
nicteaming.notifySwitches = True
policy.nicTeaming = nicteaming
vswitch_port_group_spec.policy = policy
return vswitch_port_group_spec

File diff suppressed because it is too large Load Diff

View File

@ -1,145 +1,145 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Utility functions for Image transfer.
"""
from nova import exception
from nova.image import glance
from nova import log as logging
from nova.virt.vmwareapi import io_util
from nova.virt.vmwareapi import read_write_util
LOG = logging.getLogger("nova.virt.vmwareapi.vmware_images")
QUEUE_BUFFER_SIZE = 10
def start_transfer(read_file_handle, data_size, write_file_handle=None,
glance_client=None, image_id=None, image_meta=None):
"""Start the data transfer from the reader to the writer.
Reader writes to the pipe and the writer reads from the pipe. This means
that the total transfer time boils down to the slower of the read/write
and not the addition of the two times."""
if not image_meta:
image_meta = {}
# The pipe that acts as an intermediate store of data for reader to write
# to and writer to grab from.
thread_safe_pipe = io_util.ThreadSafePipe(QUEUE_BUFFER_SIZE, data_size)
# The read thread. In case of glance it is the instance of the
# GlanceFileRead class. The glance client read returns an iterator
# and this class wraps that iterator to provide datachunks in calls
# to read.
read_thread = io_util.IOThread(read_file_handle, thread_safe_pipe)
# In case of Glance - VMWare transfer, we just need a handle to the
# HTTP Connection that is to send transfer data to the VMWare datastore.
if write_file_handle:
write_thread = io_util.IOThread(thread_safe_pipe, write_file_handle)
# In case of VMWare - Glance transfer, we relinquish VMWare HTTP file read
# handle to Glance Client instance, but to be sure of the transfer we need
# to be sure of the status of the image on glnace changing to active.
# The GlanceWriteThread handles the same for us.
elif glance_client and image_id:
write_thread = io_util.GlanceWriteThread(thread_safe_pipe,
glance_client, image_id, image_meta)
# Start the read and write threads.
read_event = read_thread.start()
write_event = write_thread.start()
try:
# Wait on the read and write events to signal their end
read_event.wait()
write_event.wait()
except Exception, exc:
# In case of any of the reads or writes raising an exception,
# stop the threads so that we un-necessarily don't keep the other one
# waiting.
read_thread.stop()
write_thread.stop()
# Log and raise the exception.
LOG.exception(exc)
raise exception.Error(exc)
finally:
# No matter what, try closing the read and write handles, if it so
# applies.
read_file_handle.close()
if write_file_handle:
write_file_handle.close()
def fetch_image(context, image, instance, **kwargs):
"""Download image from the glance image server."""
LOG.debug(_("Downloading image %s from glance image server") % image)
(glance_client, image_id) = glance.get_glance_client(context, image)
metadata, read_iter = glance_client.get_image(image_id)
read_file_handle = read_write_util.GlanceFileRead(read_iter)
file_size = int(metadata['size'])
write_file_handle = read_write_util.VMWareHTTPWriteFile(
kwargs.get("host"),
kwargs.get("data_center_name"),
kwargs.get("datastore_name"),
kwargs.get("cookies"),
kwargs.get("file_path"),
file_size)
start_transfer(read_file_handle, file_size,
write_file_handle=write_file_handle)
LOG.debug(_("Downloaded image %s from glance image server") % image)
def upload_image(context, image, instance, **kwargs):
"""Upload the snapshotted vm disk file to Glance image server."""
LOG.debug(_("Uploading image %s to the Glance image server") % image)
read_file_handle = read_write_util.VmWareHTTPReadFile(
kwargs.get("host"),
kwargs.get("data_center_name"),
kwargs.get("datastore_name"),
kwargs.get("cookies"),
kwargs.get("file_path"))
file_size = read_file_handle.get_size()
(glance_client, image_id) = glance.get_glance_client(context, image)
# The properties and other fields that we need to set for the image.
image_metadata = {"is_public": True,
"disk_format": "vmdk",
"container_format": "bare",
"type": "vmdk",
"properties": {"vmware_adaptertype":
kwargs.get("adapter_type"),
"vmware_ostype": kwargs.get("os_type"),
"vmware_image_version":
kwargs.get("image_version")}}
start_transfer(read_file_handle, file_size, glance_client=glance_client,
image_id=image_id, image_meta=image_metadata)
LOG.debug(_("Uploaded image %s to the Glance image server") % image)
def get_vmdk_size_and_properties(context, image, instance):
"""
Get size of the vmdk file that is to be downloaded for attach in spawn.
Need this to create the dummy virtual disk for the meta-data file. The
geometry of the disk created depends on the size.
"""
LOG.debug(_("Getting image size for the image %s") % image)
(glance_client, image_id) = glance.get_glance_client(context, image)
meta_data = glance_client.get_image_meta(image_id)
size, properties = meta_data["size"], meta_data["properties"]
LOG.debug(_("Got image size of %(size)s for the image %(image)s") %
locals())
return size, properties
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 Citrix Systems, Inc.
# Copyright 2011 OpenStack LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Utility functions for Image transfer.
"""
from nova import exception
from nova.image import glance
from nova import log as logging
from nova.virt.vmwareapi import io_util
from nova.virt.vmwareapi import read_write_util
LOG = logging.getLogger("nova.virt.vmwareapi.vmware_images")
QUEUE_BUFFER_SIZE = 10
def start_transfer(read_file_handle, data_size, write_file_handle=None,
glance_client=None, image_id=None, image_meta=None):
"""Start the data transfer from the reader to the writer.
Reader writes to the pipe and the writer reads from the pipe. This means
that the total transfer time boils down to the slower of the read/write
and not the addition of the two times."""
if not image_meta:
image_meta = {}
# The pipe that acts as an intermediate store of data for reader to write
# to and writer to grab from.
thread_safe_pipe = io_util.ThreadSafePipe(QUEUE_BUFFER_SIZE, data_size)
# The read thread. In case of glance it is the instance of the
# GlanceFileRead class. The glance client read returns an iterator
# and this class wraps that iterator to provide datachunks in calls
# to read.
read_thread = io_util.IOThread(read_file_handle, thread_safe_pipe)
# In case of Glance - VMWare transfer, we just need a handle to the
# HTTP Connection that is to send transfer data to the VMWare datastore.
if write_file_handle:
write_thread = io_util.IOThread(thread_safe_pipe, write_file_handle)
# In case of VMWare - Glance transfer, we relinquish VMWare HTTP file read
# handle to Glance Client instance, but to be sure of the transfer we need
# to be sure of the status of the image on glnace changing to active.
# The GlanceWriteThread handles the same for us.
elif glance_client and image_id:
write_thread = io_util.GlanceWriteThread(thread_safe_pipe,
glance_client, image_id, image_meta)
# Start the read and write threads.
read_event = read_thread.start()
write_event = write_thread.start()
try:
# Wait on the read and write events to signal their end
read_event.wait()
write_event.wait()
except Exception, exc:
# In case of any of the reads or writes raising an exception,
# stop the threads so that we un-necessarily don't keep the other one
# waiting.
read_thread.stop()
write_thread.stop()
# Log and raise the exception.
LOG.exception(exc)
raise exception.Error(exc)
finally:
# No matter what, try closing the read and write handles, if it so
# applies.
read_file_handle.close()
if write_file_handle:
write_file_handle.close()
def fetch_image(context, image, instance, **kwargs):
"""Download image from the glance image server."""
LOG.debug(_("Downloading image %s from glance image server") % image)
(glance_client, image_id) = glance.get_glance_client(context, image)
metadata, read_iter = glance_client.get_image(image_id)
read_file_handle = read_write_util.GlanceFileRead(read_iter)
file_size = int(metadata['size'])
write_file_handle = read_write_util.VMWareHTTPWriteFile(
kwargs.get("host"),
kwargs.get("data_center_name"),
kwargs.get("datastore_name"),
kwargs.get("cookies"),
kwargs.get("file_path"),
file_size)
start_transfer(read_file_handle, file_size,
write_file_handle=write_file_handle)
LOG.debug(_("Downloaded image %s from glance image server") % image)
def upload_image(context, image, instance, **kwargs):
"""Upload the snapshotted vm disk file to Glance image server."""
LOG.debug(_("Uploading image %s to the Glance image server") % image)
read_file_handle = read_write_util.VmWareHTTPReadFile(
kwargs.get("host"),
kwargs.get("data_center_name"),
kwargs.get("datastore_name"),
kwargs.get("cookies"),
kwargs.get("file_path"))
file_size = read_file_handle.get_size()
(glance_client, image_id) = glance.get_glance_client(context, image)
# The properties and other fields that we need to set for the image.
image_metadata = {"is_public": True,
"disk_format": "vmdk",
"container_format": "bare",
"type": "vmdk",
"properties": {"vmware_adaptertype":
kwargs.get("adapter_type"),
"vmware_ostype": kwargs.get("os_type"),
"vmware_image_version":
kwargs.get("image_version")}}
start_transfer(read_file_handle, file_size, glance_client=glance_client,
image_id=image_id, image_meta=image_metadata)
LOG.debug(_("Uploaded image %s to the Glance image server") % image)
def get_vmdk_size_and_properties(context, image, instance):
"""
Get size of the vmdk file that is to be downloaded for attach in spawn.
Need this to create the dummy virtual disk for the meta-data file. The
geometry of the disk created depends on the size.
"""
LOG.debug(_("Getting image size for the image %s") % image)
(glance_client, image_id) = glance.get_glance_client(context, image)
meta_data = glance_client.get_image_meta(image_id)
size, properties = meta_data["size"], meta_data["properties"]
LOG.debug(_("Got image size of %(size)s for the image %(image)s") %
locals())
return size, properties