VMware: Integrate VMDK driver with oslo.vmware

The common code between various VMware drivers was moved to
oslo.vmware library during Icehouse release. The VMDK driver
should be updated to use this library. Changes are mostly
replacing import statements and removing redundant modules
and corresponding test cases.

Summary of changes:
* Replace api with oslo.vmware.api
* Replace vim with oslo.vmware.vim
* Replace pbm with oslo.vmware.pbm
* Replace io_util with oslo.vmware.image_transfer
* Replace vmware_images with oslo.vmware.image_transfer
* Replace read_write_util with oslo.vmware.rw_handles
* Remove error_util and use oslo.vmware.exceptions
* Move VMDK driver specific exceptions to a new module
  'exceptions'
* Replace PBM WSDL files with the corresponding files in
  oslo.vmware
* Replace PBM related methods in volumeops with the
  corresponding ones in oslo.vmware.pbm

Implements: blueprint vmdk-oslo.vmware
Change-Id: Ib484fabffb8ef1a56051d7e1bed5218b633306bb
This commit is contained in:
Vipin Balachandran 2014-11-26 15:44:22 +05:30
parent 84855ecda7
commit 960cbb21e3
23 changed files with 340 additions and 4843 deletions

View File

@ -1,259 +0,0 @@
# Copyright (c) 2014 VMware, Inc.
# All Rights Reserved.
#
# 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.
"""
Unit tests for session management and API invocation classes.
"""
from eventlet import greenthread
import mock
from cinder import test
from cinder.volume.drivers.vmware import api
from cinder.volume.drivers.vmware import error_util
class RetryTest(test.TestCase):
"""Tests for retry decorator class."""
def test_retry(self):
result = "RESULT"
@api.Retry()
def func(*args, **kwargs):
return result
self.assertEqual(result, func())
def func2(*args, **kwargs):
return result
retry = api.Retry()
self.assertEqual(result, retry(func2)())
self.assertTrue(retry._retry_count == 0)
def test_retry_with_expected_exceptions(self):
result = "RESULT"
responses = [error_util.SessionOverLoadException(None),
error_util.SessionOverLoadException(None),
result]
def func(*args, **kwargs):
response = responses.pop(0)
if isinstance(response, Exception):
raise response
return response
sleep_time_incr = 0.01
retry_count = 2
retry = api.Retry(10, sleep_time_incr, 10,
(error_util.SessionOverLoadException,))
self.assertEqual(result, retry(func)())
self.assertTrue(retry._retry_count == retry_count)
self.assertEqual(retry_count * sleep_time_incr, retry._sleep_time)
def test_retry_with_max_retries(self):
responses = [error_util.SessionOverLoadException(None),
error_util.SessionOverLoadException(None),
error_util.SessionOverLoadException(None)]
def func(*args, **kwargs):
response = responses.pop(0)
if isinstance(response, Exception):
raise response
return response
retry = api.Retry(2, 0, 0, (error_util.SessionOverLoadException,))
self.assertRaises(error_util.SessionOverLoadException, retry(func))
self.assertTrue(retry._retry_count == 2)
def test_retry_with_unexpected_exception(self):
def func(*args, **kwargs):
raise error_util.VimException(None)
retry = api.Retry()
self.assertRaises(error_util.VimException, retry(func))
self.assertTrue(retry._retry_count == 0)
class VMwareAPISessionTest(test.TestCase):
"""Tests for VMwareAPISession."""
SERVER_IP = '10.1.2.3'
USERNAME = 'admin'
PASSWORD = 'password'
def setUp(self):
super(VMwareAPISessionTest, self).setUp()
patcher = mock.patch('cinder.volume.drivers.vmware.vim.Vim')
self.addCleanup(patcher.stop)
self.VimMock = patcher.start()
self.VimMock.side_effect = lambda *args, **kw: mock.Mock()
def _create_api_session(self, _create_session, retry_count=10,
task_poll_interval=1):
return api.VMwareAPISession(VMwareAPISessionTest.SERVER_IP,
VMwareAPISessionTest.USERNAME,
VMwareAPISessionTest.PASSWORD,
retry_count,
task_poll_interval,
'https',
_create_session)
def test_create_session(self):
session = mock.Mock()
session.key = "12345"
api_session = self._create_api_session(False)
vim_obj = api_session.vim
vim_obj.Login.return_value = session
pbm_client = mock.Mock()
api_session._pbm = pbm_client
api_session.create_session()
session_manager = vim_obj.service_content.sessionManager
vim_obj.Login.assert_called_once_with(
session_manager, userName=VMwareAPISessionTest.USERNAME,
password=VMwareAPISessionTest.PASSWORD)
self.assertFalse(vim_obj.TerminateSession.called)
self.assertEqual(session.key, api_session._session_id)
pbm_client.set_cookie.assert_called_once_with()
def test_create_session_with_existing_session(self):
old_session_key = '12345'
new_session_key = '67890'
session = mock.Mock()
session.key = new_session_key
api_session = self._create_api_session(False)
api_session._session_id = old_session_key
vim_obj = api_session.vim
vim_obj.Login.return_value = session
api_session.create_session()
session_manager = vim_obj.service_content.sessionManager
vim_obj.Login.assert_called_once_with(
session_manager, userName=VMwareAPISessionTest.USERNAME,
password=VMwareAPISessionTest.PASSWORD)
vim_obj.TerminateSession.assert_called_once_with(
session_manager, sessionId=[old_session_key])
self.assertEqual(new_session_key, api_session._session_id)
def test_invoke_api(self):
api_session = self._create_api_session(True)
response = mock.Mock()
def api(*args, **kwargs):
return response
module = mock.Mock()
module.api = api
ret = api_session.invoke_api(module, 'api')
self.assertEqual(response, ret)
def test_invoke_api_with_expected_exception(self):
api_session = self._create_api_session(True)
ret = mock.Mock()
responses = [error_util.VimConnectionException(None), ret]
def api(*args, **kwargs):
response = responses.pop(0)
if isinstance(response, Exception):
raise response
return response
module = mock.Mock()
module.api = api
with mock.patch.object(greenthread, 'sleep'):
self.assertEqual(ret, api_session.invoke_api(module, 'api'))
def test_invoke_api_with_vim_fault_exception(self):
api_session = self._create_api_session(True)
def api(*args, **kwargs):
raise error_util.VimFaultException([], "error")
module = mock.Mock()
module.api = api
self.assertRaises(error_util.VimFaultException,
lambda: api_session.invoke_api(module, 'api'))
def test_invoke_api_with_empty_response(self):
api_session = self._create_api_session(True)
vim_obj = api_session.vim
vim_obj.SessionIsActive.return_value = True
def api(*args, **kwargs):
raise error_util.VimFaultException(
[error_util.NOT_AUTHENTICATED], "error")
module = mock.Mock()
module.api = api
ret = api_session.invoke_api(module, 'api')
self.assertEqual([], ret)
vim_obj.SessionIsActive.assert_called_once_with(
vim_obj.service_content.sessionManager,
sessionID=api_session._session_id,
userName=api_session._session_username)
def test_invoke_api_with_stale_session(self):
api_session = self._create_api_session(True)
api_session.create_session = mock.Mock()
vim_obj = api_session.vim
vim_obj.SessionIsActive.return_value = False
result = mock.Mock()
responses = [error_util.VimFaultException(
[error_util.NOT_AUTHENTICATED], "error"), result]
def api(*args, **kwargs):
response = responses.pop(0)
if isinstance(response, Exception):
raise response
return response
module = mock.Mock()
module.api = api
ret = api_session.invoke_api(module, 'api')
self.assertEqual(result, ret)
vim_obj.SessionIsActive.assert_called_once_with(
vim_obj.service_content.sessionManager,
sessionID=api_session._session_id,
userName=api_session._session_username)
api_session.create_session.assert_called_once_with()
def test_invoke_api_with_session_is_active_error(self):
api_session = self._create_api_session(True)
api_session.create_session = mock.Mock()
vim_obj = api_session.vim
vim_obj.SessionIsActive.side_effect = error_util.VimFaultException(
None, None)
result = mock.Mock()
responses = [error_util.VimFaultException(
[error_util.NOT_AUTHENTICATED], "error"), result]
def api(*args, **kwargs):
response = responses.pop(0)
if isinstance(response, Exception):
raise response
return response
module = mock.Mock()
module.api = api
ret = api_session.invoke_api(module, 'api')
self.assertEqual(result, ret)
vim_obj.SessionIsActive.assert_called_once_with(
vim_obj.service_content.sessionManager,
sessionID=api_session._session_id,
userName=api_session._session_username)
api_session.create_session.assert_called_once_with()

View File

@ -19,10 +19,11 @@ Unit tests for datastore module.
import mock
from oslo_utils import units
from oslo_vmware import exceptions
from cinder import test
from cinder.volume.drivers.vmware import datastore as ds_sel
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import exceptions as vmdk_exceptions
class DatastoreTest(test.TestCase):
@ -34,22 +35,26 @@ class DatastoreTest(test.TestCase):
self._vops = mock.Mock()
self._ds_sel = ds_sel.DatastoreSelector(self._vops, self._session)
def test_get_profile_id(self):
@mock.patch('oslo_vmware.pbm.get_profile_id_by_name')
def test_get_profile_id(self, get_profile_id_by_name):
profile_id = mock.sentinel.profile_id
self._vops.retrieve_profile_id.return_value = profile_id
get_profile_id_by_name.return_value = profile_id
profile_name = mock.sentinel.profile_name
self.assertEqual(profile_id, self._ds_sel.get_profile_id(profile_name))
self._vops.retrieve_profile_id.assert_called_once_with(profile_name)
get_profile_id_by_name.assert_called_once_with(self._session,
profile_name)
def test_get_profile_id_with_invalid_profile(self):
self._vops.retrieve_profile_id.return_value = None
@mock.patch('oslo_vmware.pbm.get_profile_id_by_name')
def test_get_profile_id_with_invalid_profile(self, get_profile_id_by_name):
get_profile_id_by_name.return_value = None
profile_name = mock.sentinel.profile_name
self.assertRaises(error_util.ProfileNotFoundException,
self.assertRaises(vmdk_exceptions.ProfileNotFoundException,
self._ds_sel.get_profile_id,
profile_name)
self._vops.retrieve_profile_id.assert_called_once_with(profile_name)
get_profile_id_by_name.assert_called_once_with(self._session,
profile_name)
def _create_datastore(self, moref):
return mock.Mock(value=moref)
@ -239,7 +244,7 @@ class DatastoreTest(test.TestCase):
self._vops.get_hosts.return_value = mock.Mock(
objects=[mock.Mock(obj=host_1)])
self._vops.continue_retrieval.return_value = None
self._vops.get_dss_rp.side_effect = error_util.VimException('error')
self._vops.get_dss_rp.side_effect = exceptions.VimException('error')
self.assertEqual((), self._ds_sel.select_datastore(req))
self._vops.get_dss_rp.assert_called_once_with(host_1)
@ -254,10 +259,10 @@ class DatastoreTest(test.TestCase):
mock.Mock(obj=host_2),
mock.Mock(obj=host_3)])
self._vops.get_dss_rp.side_effect = [
error_util.VimException('no valid datastores'),
error_util.VimConnectionException('connection error')]
exceptions.VimException('no valid datastores'),
exceptions.VimConnectionException('connection error')]
self.assertRaises(error_util.VimConnectionException,
self.assertRaises(exceptions.VimConnectionException,
self._ds_sel.select_datastore,
req)
get_dss_rp_exp_calls = [mock.call(host_1), mock.call(host_2)]
@ -288,7 +293,7 @@ class DatastoreTest(test.TestCase):
rp_2 = mock.sentinel.rp_2
rp_3 = mock.sentinel.rp_3
self._vops.get_dss_rp.side_effect = [
error_util.VimException('no valid datastores'),
exceptions.VimException('no valid datastores'),
([ds_2a, ds_2b], rp_2),
([ds_3a], rp_3)]
@ -310,7 +315,7 @@ class DatastoreTest(test.TestCase):
# Modify previous case to have a non-empty summary list after filtering
# with preferred utilization threshold unset.
self._vops.get_dss_rp.side_effect = [
error_util.VimException('no valid datastores'),
exceptions.VimException('no valid datastores'),
([ds_2a, ds_2b], rp_2),
([ds_3a], rp_3)]
@ -325,7 +330,7 @@ class DatastoreTest(test.TestCase):
# Modify previous case to have a preferred utilization threshold
# satsified by one datastore.
self._vops.get_dss_rp.side_effect = [
error_util.VimException('no valid datastores'),
exceptions.VimException('no valid datastores'),
([ds_2a, ds_2b], rp_2),
([ds_3a], rp_3)]
@ -340,7 +345,7 @@ class DatastoreTest(test.TestCase):
# Modify previous case to have a preferred utilization threshold
# which cannot be satisfied.
self._vops.get_dss_rp.side_effect = [
error_util.VimException('no valid datastores'),
exceptions.VimException('no valid datastores'),
([ds_2a, ds_2b], rp_2),
([ds_3a], rp_3)]
filter_datastores.side_effect = [[summary_2b], [summary_3a]]
@ -378,9 +383,11 @@ class DatastoreTest(test.TestCase):
self._vops.get_connected_hosts.reset_mock()
self._vops.get_connected_hosts.return_value = None
@mock.patch('oslo_vmware.pbm.get_profile_id_by_name')
@mock.patch('cinder.volume.drivers.vmware.datastore.DatastoreSelector.'
'_filter_by_profile')
def test_is_datastore_compliant(self, filter_by_profile):
def test_is_datastore_compliant(self, filter_by_profile,
get_profile_id_by_name):
# Test with empty profile.
profile_name = None
datastore = mock.sentinel.datastore
@ -389,28 +396,31 @@ class DatastoreTest(test.TestCase):
# Test with invalid profile.
profile_name = mock.sentinel.profile_name
self._vops.retrieve_profile_id.return_value = None
self.assertRaises(error_util.ProfileNotFoundException,
get_profile_id_by_name.return_value = None
self.assertRaises(vmdk_exceptions.ProfileNotFoundException,
self._ds_sel.is_datastore_compliant,
datastore,
profile_name)
self._vops.retrieve_profile_id.assert_called_once_with(profile_name)
get_profile_id_by_name.assert_called_once_with(self._session,
profile_name)
# Test with valid profile and non-compliant datastore.
self._vops.retrieve_profile_id.reset_mock()
get_profile_id_by_name.reset_mock()
profile_id = mock.sentinel.profile_id
self._vops.retrieve_profile_id.return_value = profile_id
get_profile_id_by_name.return_value = profile_id
filter_by_profile.return_value = []
self.assertFalse(self._ds_sel.is_datastore_compliant(datastore,
profile_name))
self._vops.retrieve_profile_id.assert_called_once_with(profile_name)
get_profile_id_by_name.assert_called_once_with(self._session,
profile_name)
filter_by_profile.assert_called_once_with([datastore], profile_id)
# Test with valid profile and compliant datastore.
self._vops.retrieve_profile_id.reset_mock()
get_profile_id_by_name.reset_mock()
filter_by_profile.reset_mock()
filter_by_profile.return_value = [datastore]
self.assertTrue(self._ds_sel.is_datastore_compliant(datastore,
profile_name))
self._vops.retrieve_profile_id.assert_called_once_with(profile_name)
get_profile_id_by_name.assert_called_once_with(self._session,
profile_name)
filter_by_profile.assert_called_once_with([datastore], profile_id)

View File

@ -1,151 +0,0 @@
# Copyright (c) 2014 VMware, Inc.
# All Rights Reserved.
#
# 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.
"""
Unit tests for image transfer utility classes.
"""
import math
from eventlet import greenthread
import mock
from cinder import test
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import io_util
class ThreadSafePipeTest(test.TestCase):
"""Tests for ThreadSafePipe."""
def test_read(self):
max_size = 10
chunk_size = 10
max_transfer_size = 30
queue = io_util.ThreadSafePipe(max_size, max_transfer_size)
def get_side_effect():
return [1] * chunk_size
queue.get = mock.Mock(side_effect=get_side_effect)
while True:
data_item = queue.read(chunk_size)
if not data_item:
break
self.assertEqual(max_transfer_size, queue.transferred)
exp_calls = [mock.call()] * int(math.ceil(float(max_transfer_size) /
chunk_size))
self.assertEqual(exp_calls, queue.get.call_args_list)
def test_write(self):
queue = io_util.ThreadSafePipe(10, 30)
queue.put = mock.Mock()
write_count = 10
for _ in range(0, write_count):
queue.write([1])
exp_calls = [mock.call([1])] * write_count
self.assertEqual(exp_calls, queue.put.call_args_list)
def test_seek(self):
queue = io_util.ThreadSafePipe(10, 30)
self.assertRaises(IOError, queue.seek, 0)
def test_tell(self):
max_transfer_size = 30
queue = io_util.ThreadSafePipe(10, 30)
self.assertEqual(max_transfer_size, queue.tell())
class GlanceWriteThreadTest(test.TestCase):
"""Tests for GlanceWriteThread class."""
def _create_image_writer(self):
self._image_service = mock.Mock()
self._context = mock.Mock()
self._input_file = mock.Mock()
self._image_id = mock.Mock()
return io_util.GlanceWriteThread(self._context, self._input_file,
self._image_service, self._image_id)
@mock.patch.object(greenthread, 'sleep')
def test_start(self, mock_sleep):
writer = self._create_image_writer()
status_list = ['queued', 'saving', 'active']
def image_service_show_side_effect(context, image_id):
status = status_list.pop(0)
return {'status': status}
self._image_service.show.side_effect = image_service_show_side_effect
exp_calls = [mock.call(self._context,
self._image_id)] * len(status_list)
writer.start()
self.assertTrue(writer.wait())
self._image_service.update.assert_called_once_with(
self._context, self._image_id, {}, data=self._input_file)
self.assertEqual(exp_calls, self._image_service.show.call_args_list)
def test_start_with_killed_status(self):
writer = self._create_image_writer()
def image_service_show_side_effect(_context, _image_id):
return {'status': 'killed'}
self._image_service.show.side_effect = image_service_show_side_effect
writer.start()
self.assertRaises(error_util.ImageTransferException, writer.wait)
self._image_service.update.assert_called_once_with(
self._context, self._image_id, {}, data=self._input_file)
self._image_service.show.assert_called_once_with(self._context,
self._image_id)
def test_start_with_unknown_status(self):
writer = self._create_image_writer()
def image_service_show_side_effect(_context, _image_id):
return {'status': 'unknown'}
self._image_service.show.side_effect = image_service_show_side_effect
writer.start()
self.assertRaises(error_util.ImageTransferException, writer.wait)
self._image_service.update.assert_called_once_with(
self._context, self._image_id, {}, data=self._input_file)
self._image_service.show.assert_called_once_with(self._context,
self._image_id)
def test_start_with_image_service_update_exception(self):
writer = self._create_image_writer()
self._image_service.update.side_effect = Exception
writer.start()
self.assertRaises(error_util.ImageTransferException, writer.wait)
self._image_service.update.assert_called_once_with(
self._context, self._image_id, {}, data=self._input_file)
self.assertFalse(self._image_service.show.called)
def test_start_with_image_service_show_exception(self):
writer = self._create_image_writer()
self._image_service.show.side_effect = Exception
writer.start()
self.assertRaises(error_util.ImageTransferException, writer.wait)
self._image_service.update.assert_called_once_with(
self._context, self._image_id, {}, data=self._input_file)
self._image_service.show.assert_called_once_with(self._context,
self._image_id)

View File

@ -18,23 +18,22 @@ Test suite for VMware VMDK driver.
"""
from distutils.version import LooseVersion
import os
import mock
import mox
from oslo_utils import units
from oslo_vmware import api
from oslo_vmware import exceptions
from oslo_vmware import image_transfer
import six
from cinder import exception
from cinder import exception as cinder_exceptions
from cinder.image import glance
from cinder import test
from cinder.volume import configuration
from cinder.volume.drivers.vmware import api
from cinder.volume.drivers.vmware import datastore as hub
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import vim
from cinder.volume.drivers.vmware import vim_util
from cinder.volume.drivers.vmware import exceptions as vmdk_exceptions
from cinder.volume.drivers.vmware import vmdk
from cinder.volume.drivers.vmware import vmware_images
from cinder.volume.drivers.vmware import volumeops
@ -139,6 +138,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
"""Test class for VMwareEsxVmdkDriver."""
IP = 'localhost'
PORT = 443
USERNAME = 'username'
PASSWORD = 'password'
VOLUME_FOLDER = 'cinder-volumes'
@ -176,42 +176,6 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
self.MAX_OBJECTS)
self._vim = FakeVim()
def test_retry(self):
"""Test Retry."""
class TestClass(object):
def __init__(self):
self.counter1 = 0
self.counter2 = 0
@api.Retry(max_retry_count=2, inc_sleep_time=0.001,
exceptions=(Exception))
def fail(self):
self.counter1 += 1
raise exception.CinderException('Fail')
@api.Retry(max_retry_count=2)
def success(self):
self.counter2 += 1
return self.counter2
test_obj = TestClass()
self.assertRaises(exception.CinderException, test_obj.fail)
self.assertEqual(test_obj.counter1, 3)
ret = test_obj.success()
self.assertEqual(1, ret)
def test_create_session(self):
"""Test create_session."""
m = self.mox
m.StubOutWithMock(api.VMwareAPISession, 'vim')
self._session.vim = self._vim
m.ReplayAll()
self._session.create_session()
m.UnsetStubs()
m.VerifyAll()
def test_do_setup(self):
"""Test do_setup."""
m = self.mox
@ -253,49 +217,13 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
driver._select_ds_for_volume.assert_called_once_with(volume)
# test create_volume call when _select_ds_for_volume fails
driver._select_ds_for_volume.side_effect = error_util.VimException('')
self.assertRaises(error_util.VimFaultException, driver.create_volume,
driver._select_ds_for_volume.side_effect = exceptions.VimException('')
self.assertRaises(exceptions.VimFaultException, driver.create_volume,
volume)
# Clear side effects.
driver._select_ds_for_volume.side_effect = None
def test_success_wait_for_task(self):
"""Test successful wait_for_task."""
m = self.mox
m.StubOutWithMock(api.VMwareAPISession, 'vim')
self._session.vim = self._vim
result = FakeMor('VirtualMachine', 'my_vm')
success_task_info = FakeTaskInfo('success', result=result)
m.StubOutWithMock(vim_util, 'get_object_property')
vim_util.get_object_property(self._session.vim,
mox.IgnoreArg(),
'info').AndReturn(success_task_info)
m.ReplayAll()
ret = self._session.wait_for_task(mox.IgnoreArg())
self.assertEqual(ret.result, result)
m.UnsetStubs()
m.VerifyAll()
def test_failed_wait_for_task(self):
"""Test failed wait_for_task."""
m = self.mox
m.StubOutWithMock(api.VMwareAPISession, 'vim')
self._session.vim = self._vim
failed_task_info = FakeTaskInfo('failed')
m.StubOutWithMock(vim_util, 'get_object_property')
vim_util.get_object_property(self._session.vim,
mox.IgnoreArg(),
'info').AndReturn(failed_task_info)
m.ReplayAll()
self.assertRaises(error_util.VimFaultException,
self._session.wait_for_task,
mox.IgnoreArg())
m.UnsetStubs()
m.VerifyAll()
def test_delete_volume_without_backing(self):
"""Test delete_volume without backing."""
m = self.mox
@ -364,7 +292,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
volume['name'] = 'vol_name'
backing = FakeMor('VirtualMachine', 'my_back')
mux = self._driver._create_backing(volume, host1.obj, {})
mux.AndRaise(error_util.VimException('Maintenance mode'))
mux.AndRaise(exceptions.VimException('Maintenance mode'))
mux = self._driver._create_backing(volume, host2.obj, {})
mux.AndReturn(backing)
m.StubOutWithMock(self._volumeops, 'cancel_retrieval')
@ -470,7 +398,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
summary = self._driver._select_datastore_summary(40, datastores)
self.assertEqual(summary, summary4)
self.assertRaises(error_util.VimException,
self.assertRaises(exceptions.VimException,
self._driver._select_datastore_summary,
100, datastores)
m.UnsetStubs()
@ -527,7 +455,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
# Test with invalid vmdk_type.
get_volume_type_extra_specs.return_value = 'sparse'
self.assertRaises(error_util.InvalidDiskTypeException,
self.assertRaises(vmdk_exceptions.InvalidDiskTypeException,
vmdk.VMwareEsxVmdkDriver._get_disk_type,
volume)
@ -643,7 +571,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
snapshot['volume'] = FakeObject()
snapshot['volume']['status'] = 'in-use'
self.assertRaises(exception.InvalidVolume,
self.assertRaises(cinder_exceptions.InvalidVolume,
self._driver.create_snapshot, snapshot)
def test_delete_snapshot_without_backing(self):
@ -693,7 +621,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
snapshot['volume'] = FakeObject()
snapshot['volume']['status'] = 'in-use'
self.assertRaises(exception.InvalidVolume,
self.assertRaises(cinder_exceptions.InvalidVolume,
self._driver.delete_snapshot, snapshot)
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareEsxVmdkDriver.'
@ -757,7 +685,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
fake_src_vmdk_path = "[datastore] src_vm/src_vm.vmdk"
fake_backing = mock.sentinel.backing
fake_vmdk_path = mock.sentinel.path
#"[datastore] dest_vm/dest_vm.vmdk"
# "[datastore] dest_vm/dest_vm.vmdk"
fake_dc = mock.sentinel.datacenter
create_backing.return_value = fake_backing
@ -901,8 +829,8 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
# _extend_virtual_disk is called, VimFaultException is raised. The
# second time it is called, there is no exception.
_extend_virtual_disk.reset_mock()
_extend_virtual_disk.side_effect = [error_util.
VimFaultException(mock.Mock(),
_extend_virtual_disk.side_effect = [exceptions.
VimFaultException([],
'Error'), None]
# When _select_ds_for_volume raises no exception.
_select_ds_for_volume.return_value = (fake_host, fake_rp,
@ -921,11 +849,11 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
# If get_backing raises error_util.VimException,
# this exception will be caught for volume extend.
_extend_virtual_disk.reset_mock()
_extend_virtual_disk.side_effect = [error_util.
VimFaultException(mock.Mock(),
_extend_virtual_disk.side_effect = [exceptions.
VimFaultException([],
'Error'), None]
volume_ops.get_backing.side_effect = error_util.VimException('Error')
self.assertRaises(error_util.VimException, self._driver.extend_volume,
volume_ops.get_backing.side_effect = exceptions.VimException('Error')
self.assertRaises(exceptions.VimException, self._driver.extend_volume,
fake_vol, new_size)
# If _select_ds_for_volume raised an exception, the rest code will
@ -934,11 +862,11 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
volume_ops.get_backing.reset_mock()
volume_ops.relocate_backing.reset_mock()
volume_ops.move_backing_to_folder.reset_mock()
_extend_virtual_disk.side_effect = [error_util.
VimFaultException(mock.Mock(),
_extend_virtual_disk.side_effect = [exceptions.
VimFaultException([],
'Error'), None]
_select_ds_for_volume.side_effect = error_util.VimException('Error')
self.assertRaises(error_util.VimException, self._driver.extend_volume,
_select_ds_for_volume.side_effect = exceptions.VimException('Error')
self.assertRaises(exceptions.VimException, self._driver.extend_volume,
fake_vol, new_size)
_extend_virtual_disk.assert_called_once_with(fake_name, new_size)
self.assertFalse(volume_ops.get_backing.called)
@ -953,7 +881,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
image_service = mock.Mock()
image_service.show.return_value = fake_image_meta
fake_volume = {'name': 'fake_name', 'size': 1}
self.assertRaises(exception.ImageUnacceptable,
self.assertRaises(cinder_exceptions.ImageUnacceptable,
self._driver.copy_image_to_volume,
fake_context, fake_volume,
image_service, fake_image_id)
@ -1078,9 +1006,9 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
extend_disk.reset_mock()
create_disk_from_preallocated_image.side_effect = (
error_util.VimException("Error"))
exceptions.VimException("Error"))
self.assertRaises(error_util.VimException,
self.assertRaises(exceptions.VimException,
self._driver.copy_image_to_volume,
context, volume, image_service, image_id)
vops.delete_backing.assert_called_once_with(backing)
@ -1125,9 +1053,9 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
create_descriptor.reset_mock()
copy_image.reset_mock()
copy_image.side_effect = error_util.VimException("error")
copy_image.side_effect = exceptions.VimException("error")
self.assertRaises(
error_util.VimException,
exceptions.VimException,
self._driver._create_virtual_disk_from_preallocated_image,
context, image_service, image_id, image_size_in_bytes, dc_ref,
ds_name, folder_path, disk_name, adapter_type)
@ -1175,7 +1103,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
dc_ref, src_path, dest_path)
self.assertEqual(dest_path, ret)
@mock.patch.object(vmware_images, 'fetch_stream_optimized_image')
@mock.patch.object(image_transfer, 'download_stream_optimized_image')
@mock.patch.object(VMDK_DRIVER, '_extend_vmdk_virtual_disk')
@mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume')
@mock.patch.object(VMDK_DRIVER, '_get_storage_profile_id')
@ -1187,7 +1115,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
get_profile_id,
_select_ds_for_volume,
_extend_virtual_disk,
fetch_optimized_image):
download_image):
"""Test copy_image_to_volume.
Test with an acceptable vmdk disk format and streamOptimized disk type.
@ -1197,14 +1125,14 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
get_profile_id,
_select_ds_for_volume,
_extend_virtual_disk,
fetch_optimized_image)
download_image)
def _test_copy_image_to_volume_stream_optimized(self, volumeops,
session,
get_profile_id,
_select_ds_for_volume,
_extend_virtual_disk,
fetch_optimized_image):
download_image):
fake_context = mock.Mock()
fake_backing = mock.sentinel.backing
fake_image_id = 'image-id'
@ -1240,8 +1168,8 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
# If _select_ds_for_volume raises an exception, get_create_spec
# will not be called.
_select_ds_for_volume.side_effect = error_util.VimException('Error')
self.assertRaises(exception.VolumeBackendAPIException,
_select_ds_for_volume.side_effect = exceptions.VimException('Error')
self.assertRaises(cinder_exceptions.VolumeBackendAPIException,
self._driver.copy_image_to_volume,
fake_context, fake_volume,
image_service, fake_image_id)
@ -1269,17 +1197,17 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
fake_summary.name,
profile_id,
adapter_type)
self.assertTrue(fetch_optimized_image.called)
fetch_optimized_image.assert_called_with(fake_context, timeout,
image_service,
fake_image_id,
session=session,
host=self.IP,
resource_pool=fake_rp,
vm_folder=fake_folder,
vm_create_spec=
vm_import_spec,
image_size=size)
self.assertTrue(download_image.called)
download_image.assert_called_with(fake_context, timeout,
image_service,
fake_image_id,
session=session,
host=self.IP,
port=self.PORT,
resource_pool=fake_rp,
vm_folder=fake_folder,
vm_import_spec=vm_import_spec,
image_size=size)
_extend_virtual_disk.assert_called_once_with(fake_volume['name'],
fake_volume_size)
@ -1295,9 +1223,9 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
# If fetch_stream_optimized_image raises an exception,
# get_backing and delete_backing will be called.
fetch_optimized_image.side_effect = exception.CinderException
download_image.side_effect = exceptions.VimException('error')
self.assertRaises(exception.CinderException,
self.assertRaises(exceptions.VimException,
self._driver.copy_image_to_volume,
fake_context, fake_volume,
image_service, fake_image_id)
@ -1316,7 +1244,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
volume['attached_host'] = None
m.ReplayAll()
self.assertRaises(exception.ImageUnacceptable,
self.assertRaises(cinder_exceptions.ImageUnacceptable,
self._driver.copy_volume_to_image,
mox.IgnoreArg(), volume,
mox.IgnoreArg(), image_meta)
@ -1330,7 +1258,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
volume['instance_uuid'] = 'my_uuid'
m.ReplayAll()
self.assertRaises(exception.InvalidVolume,
self.assertRaises(cinder_exceptions.InvalidVolume,
self._driver.copy_volume_to_image,
mox.IgnoreArg(), volume,
mox.IgnoreArg(), mox.IgnoreArg())
@ -1376,14 +1304,21 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
# vmware_images.upload_image
timeout = self._config.vmware_image_transfer_timeout_secs
host_ip = self.IP
m.StubOutWithMock(vmware_images, 'upload_image')
vmware_images.upload_image(mox.IgnoreArg(), timeout, image_service,
image_id, project_id, session=self._session,
host=host_ip, vm=backing,
vmdk_file_path=vmdk_file_path,
vmdk_size=size,
image_name=image_id,
image_version=1)
m.StubOutWithMock(image_transfer, 'upload_image')
image_transfer.upload_image(mox.IgnoreArg(),
timeout,
image_service,
image_id,
project_id,
session=self._session,
host=host_ip,
port=self.PORT,
vm=backing,
vmdk_file_path=vmdk_file_path,
vmdk_size=size,
image_name=image_id,
image_version=1,
is_public=True)
m.ReplayAll()
self._driver.copy_volume_to_image(mox.IgnoreArg(), volume,
@ -1391,38 +1326,6 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
m.UnsetStubs()
m.VerifyAll()
def test_retrieve_properties_ex_fault_checker(self):
"""Test retrieve_properties_ex_fault_checker is called."""
m = self.mox
class FakeVim(vim.Vim):
def __init__(self):
pass
@property
def client(self):
class FakeRetrv(object):
def RetrievePropertiesEx(self, collector):
pass
def __getattr__(self, name):
if name == 'service':
return FakeRetrv()
return FakeRetrv()
def RetrieveServiceContent(self, type='ServiceInstance'):
return mox.MockAnything()
_vim = FakeVim()
m.ReplayAll()
# retrieve_properties_ex_fault_checker throws authentication error
self.assertRaises(error_util.VimFaultException,
_vim.RetrievePropertiesEx, mox.IgnoreArg())
m.UnsetStubs()
m.VerifyAll()
@mock.patch.object(VMDK_DRIVER, '_delete_temp_backing')
@mock.patch('oslo_utils.uuidutils.generate_uuid')
@mock.patch.object(VMDK_DRIVER, '_get_volume_group_folder')
@ -1588,13 +1491,13 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
'gold-1',
new_profile]
vops.clone_backing.side_effect = error_util.VimException('error')
vops.clone_backing.side_effect = exceptions.VimException('error')
vops.rename_backing.reset_mock()
vops.change_backing_profile.reset_mock()
self.assertRaises(
error_util.VimException, self._driver.retype, context, vol,
exceptions.VimException, self._driver.retype, context, vol,
new_type, diff, host)
exp_rename_calls = [mock.call(backing, uuid),
mock.call(backing, vol['name'])]
@ -1636,13 +1539,13 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
fake_dc)
# Test the exceptional case for extend_virtual_disk
volume_ops.extend_virtual_disk.side_effect = error_util.VimException(
volume_ops.extend_virtual_disk.side_effect = exceptions.VimException(
'VimException raised.')
self.assertRaises(error_util.VimException,
self.assertRaises(exceptions.VimException,
self._driver._extend_vmdk_virtual_disk,
fake_name, fake_size)
@mock.patch.object(vmware_images, 'download_stream_optimized_disk')
@mock.patch.object(image_transfer, 'copy_stream_optimized_disk')
@mock.patch('cinder.openstack.common.fileutils.file_open')
@mock.patch.object(VMDK_DRIVER, '_temporary_file')
@mock.patch('oslo_utils.uuidutils.generate_uuid')
@ -1650,12 +1553,12 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
@mock.patch.object(VMDK_DRIVER, 'volumeops')
@mock.patch.object(VMDK_DRIVER, 'session')
def test_backup_volume(self, session, vops, create_backing, generate_uuid,
temporary_file, file_open, download_disk):
temporary_file, file_open, copy_disk):
self._test_backup_volume(session, vops, create_backing, generate_uuid,
temporary_file, file_open, download_disk)
temporary_file, file_open, copy_disk)
def _test_backup_volume(self, session, vops, create_backing, generate_uuid,
temporary_file, file_open, download_disk):
temporary_file, file_open, copy_disk):
volume = {'name': 'vol-1', 'id': 1, 'size': 1}
self._db.volume_get.return_value = volume
@ -1689,9 +1592,9 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
temporary_file.assert_called_once_with(suffix=".vmdk", prefix=uuid)
self.assertEqual(mock.call(tmp_file_path, "wb"),
file_open.call_args_list[0])
download_disk.assert_called_once_with(
copy_disk.assert_called_once_with(
context, self.IMG_TX_TIMEOUT, tmp_file, session=session,
host=self.IP, vm=backing, vmdk_file_path=vmdk_path,
host=self.IP, port=self.PORT, vm=backing, vmdk_file_path=vmdk_path,
vmdk_size=volume['size'] * units.Gi)
self.assertEqual(mock.call(tmp_file_path, "rb"),
file_open.call_args_list[1])
@ -1720,8 +1623,8 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
vops.get_backing.return_value = backing
vops.snapshot_exists.return_value = True
self.assertRaises(
exception.InvalidVolume, self._driver.restore_backup, context,
backup, volume, backup_service)
cinder_exceptions.InvalidVolume, self._driver.restore_backup,
context, backup, volume, backup_service)
uuid = "c1037b23-c5e9-4446-815f-3e097cbf5bb0"
generate_uuid.return_value = uuid
@ -1842,12 +1745,12 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
def vops_rename(backing, new_name):
if backing == dest and new_name == volume['name']:
raise error_util.VimException("error")
raise exceptions.VimException("error")
vops.rename_backing.side_effect = vops_rename
generate_uuid.side_effect = [src_uuid, dest_uuid, tmp_uuid]
self.assertRaises(
error_util.VimException, self._driver._restore_backing, context,
exceptions.VimException, self._driver._restore_backing, context,
volume, backing, tmp_file_path, backup_size)
exp_rename_calls = [mock.call(backing, tmp_uuid),
mock.call(dest, volume['name']),
@ -1858,7 +1761,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
delete_temp_backing.call_args_list)
@mock.patch.object(VMDK_DRIVER, '_delete_temp_backing')
@mock.patch.object(vmware_images, 'upload_stream_optimized_disk')
@mock.patch.object(image_transfer, 'download_stream_optimized_data')
@mock.patch('cinder.openstack.common.fileutils.file_open')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
@mock.patch(
@ -1868,14 +1771,14 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
@mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume')
def test_create_backing_from_stream_optimized_file(
self, select_ds, session, get_storage_profile_id, get_disk_type,
vops, file_open, upload_disk, delete_temp_backing):
vops, file_open, download_data, delete_temp_backing):
self._test_create_backing_from_stream_optimized_file(
select_ds, session, get_storage_profile_id, get_disk_type, vops,
file_open, upload_disk, delete_temp_backing)
file_open, download_data, delete_temp_backing)
def _test_create_backing_from_stream_optimized_file(
self, select_ds, session, get_storage_profile_id, get_disk_type,
vops, file_open, upload_disk, delete_temp_backing):
vops, file_open, download_data, delete_temp_backing):
rp = mock.sentinel.rp
folder = mock.sentinel.folder
summary = mock.Mock()
@ -1901,7 +1804,7 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
file_open_ret.__exit__ = mock.Mock(return_value=None)
vm_ref = mock.sentinel.vm_ref
upload_disk.return_value = vm_ref
download_data.return_value = vm_ref
context = mock.sentinel.context
name = 'vm-1'
@ -1915,16 +1818,16 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase):
vops.get_create_spec.assert_called_once_with(
name, 0, disk_type, summary.name, profile_id)
file_open.assert_called_once_with(tmp_file_path, "rb")
upload_disk.assert_called_once_with(
download_data.assert_called_once_with(
context, self.IMG_TX_TIMEOUT, tmp_file, session=session,
host=self.IP, resource_pool=rp, vm_folder=folder,
vm_create_spec=import_spec, vmdk_size=file_size_bytes)
host=self.IP, port=self.PORT, resource_pool=rp, vm_folder=folder,
vm_import_spec=import_spec, image_size=file_size_bytes)
upload_disk.side_effect = error_util.VimException("error")
download_data.side_effect = exceptions.VimException("error")
backing = mock.sentinel.backing
vops.get_backing.return_value = backing
self.assertRaises(
error_util.VimException,
exceptions.VimException,
self._driver._create_backing_from_stream_optimized_file,
context, name, volume, tmp_file_path, file_size_bytes)
delete_temp_backing.assert_called_once_with(backing)
@ -1942,38 +1845,12 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
self._driver = vmdk.VMwareVcVmdkDriver(configuration=self._config,
db=self._db)
def test_get_pbm_wsdl_location(self):
# no version returns None
wsdl = self._driver._get_pbm_wsdl_location(None)
self.assertIsNone(wsdl)
def expected_wsdl(version):
driver_dir = os.path.join(os.path.dirname(__file__), '..',
'volume', 'drivers', 'vmware')
driver_abs_dir = os.path.abspath(driver_dir)
return 'file://' + os.path.join(driver_abs_dir, 'wsdl', version,
'pbmService.wsdl')
# verify wsdl path for different version strings
with mock.patch('os.path.exists') as path_exists:
path_exists.return_value = True
wsdl = self._driver._get_pbm_wsdl_location(LooseVersion('5'))
self.assertEqual(expected_wsdl('5'), wsdl)
wsdl = self._driver._get_pbm_wsdl_location(LooseVersion('5.5'))
self.assertEqual(expected_wsdl('5.5'), wsdl)
wsdl = self._driver._get_pbm_wsdl_location(LooseVersion('5.5.1'))
self.assertEqual(expected_wsdl('5.5'), wsdl)
# if wsdl path does not exist, then it returns None
path_exists.return_value = False
wsdl = self._driver._get_pbm_wsdl_location(LooseVersion('5.5'))
self.assertIsNone(wsdl)
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'session', new_callable=mock.PropertyMock)
def test_get_vc_version(self, session):
# test config overrides fetching from VC server
version = self._driver._get_vc_version()
self.assertEqual(self.DEFAULT_VC_VERSION, version)
self.assertEqual(LooseVersion(self.DEFAULT_VC_VERSION), version)
# explicitly remove config entry
self._driver.configuration.vmware_host_version = None
session.return_value.vim.service_content.about.version = '6.0.1'
@ -1996,8 +1873,7 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
self.assertEqual(session_obj, self._driver.volumeops._session)
self.assertEqual(session_obj, self._driver.ds_sel._session)
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'_get_pbm_wsdl_location')
@mock.patch('oslo_vmware.pbm.get_pbm_wsdl_location')
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'_get_vc_version')
def test_do_setup_with_invalid_pbm_wsdl(self, get_vc_version,
@ -2006,16 +1882,16 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
get_vc_version.return_value = vc_version
get_pbm_wsdl_location.return_value = None
self.assertRaises(error_util.VMwareDriverException,
self.assertRaises(exceptions.VMwareDriverException,
self._driver.do_setup,
mock.ANY)
self.assertFalse(self._driver._storage_policy_enabled)
get_vc_version.assert_called_once_with()
get_pbm_wsdl_location.assert_called_once_with(vc_version)
get_pbm_wsdl_location.assert_called_once_with(
six.text_type(vc_version))
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'_get_pbm_wsdl_location')
@mock.patch('oslo_vmware.pbm.get_pbm_wsdl_location')
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'_get_vc_version')
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
@ -2032,7 +1908,8 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
self.assertTrue(self._driver._storage_policy_enabled)
get_vc_version.assert_called_once_with()
get_pbm_wsdl_location.assert_called_once_with(vc_version)
get_pbm_wsdl_location.assert_called_once_with(
six.text_type(vc_version))
self.assertEqual(session_obj, self._driver.volumeops._session)
self.assertEqual(session_obj, self._driver.ds_sel._session)
@ -2384,7 +2261,7 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
get_clone_type.return_value = linked_clone
# invoke the create_volume_from_snapshot api
self.assertRaises(exception.InvalidVolume,
self.assertRaises(cinder_exceptions.InvalidVolume,
driver.create_cloned_volume,
volume,
src_vref)
@ -2419,50 +2296,46 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
profile = self._driver._get_storage_profile(volume)
self.assertIsNone(profile)
@mock.patch('cinder.volume.drivers.vmware.vim_util.'
'convert_datastores_to_hubs')
@mock.patch('cinder.volume.drivers.vmware.vim_util.'
'convert_hubs_to_datastores')
@mock.patch('oslo_vmware.pbm.convert_datastores_to_hubs')
@mock.patch('oslo_vmware.pbm.get_profile_id_by_name')
@mock.patch('oslo_vmware.pbm.filter_hubs_by_profile')
@mock.patch('oslo_vmware.pbm.filter_datastores_by_hubs')
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'session', new_callable=mock.PropertyMock)
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'volumeops', new_callable=mock.PropertyMock)
def test_filter_ds_by_profile(self, volumeops, session, hubs_to_ds,
ds_to_hubs):
def test_filter_ds_by_profile(self, session, filter_dss, filter_hubs,
get_profile_id, dss_to_hubs):
"""Test vmdk _filter_ds_by_profile() method."""
volumeops = volumeops.return_value
session = session.return_value
# Test with no profile id
datastores = [mock.sentinel.ds1, mock.sentinel.ds2]
profile = 'fake_profile'
volumeops.retrieve_profile_id.return_value = None
self.assertRaises(error_util.VimException,
get_profile_id.return_value = None
self.assertRaises(exceptions.VimException,
self._driver._filter_ds_by_profile,
datastores, profile)
volumeops.retrieve_profile_id.assert_called_once_with(profile)
get_profile_id.assert_called_once_with(session, profile)
# Test with a fake profile id
profileId = 'fake_profile_id'
filtered_dss = [mock.sentinel.ds1]
# patch method calls from _filter_ds_by_profile
volumeops.retrieve_profile_id.return_value = profileId
get_profile_id.return_value = profileId
pbm_cf = mock.sentinel.pbm_cf
session.pbm.client.factory = pbm_cf
hubs = [mock.sentinel.hub1, mock.sentinel.hub2]
ds_to_hubs.return_value = hubs
volumeops.filter_matching_hubs.return_value = mock.sentinel.hubs
hubs_to_ds.return_value = filtered_dss
dss_to_hubs.return_value = hubs
filter_hubs.return_value = mock.sentinel.hubs
filter_dss.return_value = filtered_dss
# call _filter_ds_by_profile with a fake profile
actual_dss = self._driver._filter_ds_by_profile(datastores, profile)
# verify return value and called methods
self.assertEqual(filtered_dss, actual_dss,
"Wrong filtered datastores returned.")
ds_to_hubs.assert_called_once_with(pbm_cf, datastores)
volumeops.filter_matching_hubs.assert_called_once_with(hubs,
profileId)
hubs_to_ds.assert_called_once_with(mock.sentinel.hubs, datastores)
dss_to_hubs.assert_called_once_with(pbm_cf, datastores)
filter_hubs.assert_called_once_with(session, hubs, profileId)
filter_dss.assert_called_once_with(mock.sentinel.hubs, datastores)
@mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.'
'session', new_callable=mock.PropertyMock)
@ -2565,7 +2438,7 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
self._test_create_virtual_disk_from_sparse_image(
copy_image, copy_temp_virtual_disk, flat_extent_path, sparse_path)
@mock.patch.object(vmware_images, 'fetch_stream_optimized_image')
@mock.patch.object(image_transfer, 'download_stream_optimized_image')
@mock.patch.object(VMDK_DRIVER, '_extend_vmdk_virtual_disk')
@mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume')
@mock.patch.object(VMDK_DRIVER, '_get_storage_profile_id')
@ -2576,7 +2449,7 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
get_profile_id,
_select_ds_for_volume,
_extend_virtual_disk,
fetch_optimized_image):
download_image):
"""Test copy_image_to_volume.
Test with an acceptable vmdk disk format and streamOptimized disk type.
@ -2586,7 +2459,7 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
get_profile_id,
_select_ds_for_volume,
_extend_virtual_disk,
fetch_optimized_image)
download_image)
@mock.patch.object(VMDK_DRIVER, '_delete_temp_backing')
@mock.patch('oslo_utils.uuidutils.generate_uuid')
@ -2610,7 +2483,7 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
self._test_extend_volume(volume_ops, _extend_virtual_disk,
_select_ds_for_volume)
@mock.patch.object(vmware_images, 'download_stream_optimized_disk')
@mock.patch.object(image_transfer, 'copy_stream_optimized_disk')
@mock.patch('cinder.openstack.common.fileutils.file_open')
@mock.patch.object(VMDK_DRIVER, '_temporary_file')
@mock.patch('oslo_utils.uuidutils.generate_uuid')
@ -2618,9 +2491,9 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
@mock.patch.object(VMDK_DRIVER, 'volumeops')
@mock.patch.object(VMDK_DRIVER, 'session')
def test_backup_volume(self, session, vops, create_backing, generate_uuid,
temporary_file, file_open, download_disk):
temporary_file, file_open, copy_disk):
self._test_backup_volume(session, vops, create_backing, generate_uuid,
temporary_file, file_open, download_disk)
temporary_file, file_open, copy_disk)
@mock.patch.object(VMDK_DRIVER, 'extend_volume')
@mock.patch.object(VMDK_DRIVER, '_restore_backing')
@ -2649,7 +2522,7 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
delete_temp_backing)
@mock.patch.object(VMDK_DRIVER, '_delete_temp_backing')
@mock.patch.object(vmware_images, 'upload_stream_optimized_disk')
@mock.patch.object(image_transfer, 'download_stream_optimized_data')
@mock.patch('cinder.openstack.common.fileutils.file_open')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
@mock.patch(
@ -2659,10 +2532,10 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase):
@mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume')
def test_create_backing_from_stream_optimized_file(
self, select_ds, session, get_storage_profile_id, get_disk_type,
vops, file_open, upload_disk, delete_temp_backing):
vops, file_open, download_data, delete_temp_backing):
self._test_create_backing_from_stream_optimized_file(
select_ds, session, get_storage_profile_id, get_disk_type, vops,
file_open, upload_disk, delete_temp_backing)
file_open, download_data, delete_temp_backing)
@mock.patch.object(VMDK_DRIVER, '_get_folder_ds_summary')
@mock.patch.object(VMDK_DRIVER, 'volumeops')
@ -2750,6 +2623,6 @@ class ImageDiskTypeTest(test.TestCase):
vmdk.ImageDiskType.validate("preallocated")
vmdk.ImageDiskType.validate("streamOptimized")
vmdk.ImageDiskType.validate("sparse")
self.assertRaises(exception.ImageUnacceptable,
self.assertRaises(cinder_exceptions.ImageUnacceptable,
vmdk.ImageDiskType.validate,
"thick")

View File

@ -19,10 +19,11 @@ Test suite for VMware VMDK driver volumeops module.
import mock
from oslo_utils import units
from oslo_vmware import exceptions
from oslo_vmware import vim_util
from cinder import test
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import vim_util
from cinder.volume.drivers.vmware import exceptions as vmdk_exceptions
from cinder.volume.drivers.vmware import volumeops
@ -319,7 +320,7 @@ class VolumeOpsTestCase(test.TestCase):
host_mounts,
host_mounts,
resource_pool]
self.assertRaises(error_util.VimException,
self.assertRaises(exceptions.VimException,
self.vops.get_dss_rp,
host)
@ -1194,7 +1195,7 @@ class VolumeOpsTestCase(test.TestCase):
# Test with no disk device.
invoke_api.return_value = []
self.assertRaises(error_util.VirtualDiskNotFoundException,
self.assertRaises(vmdk_exceptions.VirtualDiskNotFoundException,
self.vops.get_vmdk_path,
backing)
@ -1213,7 +1214,7 @@ class VolumeOpsTestCase(test.TestCase):
# Test with no disk device.
invoke_api.return_value = []
self.assertRaises(error_util.VirtualDiskNotFoundException,
self.assertRaises(vmdk_exceptions.VirtualDiskNotFoundException,
self.vops.get_disk_size,
mock.sentinel.backing)
@ -1325,84 +1326,6 @@ class VolumeOpsTestCase(test.TestCase):
eagerZero=False)
self.session.wait_for_task.assert_called_once_with(task)
def test_get_all_profiles(self):
profile_ids = [1, 2]
methods = ['PbmQueryProfile', 'PbmRetrieveContent']
def invoke_api_side_effect(module, method, *args, **kwargs):
self.assertEqual(self.session.pbm, module)
self.assertEqual(methods.pop(0), method)
self.assertEqual(self.session.pbm.service_content.profileManager,
args[0])
if method == 'PbmQueryProfile':
self.assertEqual('STORAGE',
kwargs['resourceType'].resourceType)
return profile_ids
self.assertEqual(profile_ids, kwargs['profileIds'])
self.session.invoke_api.side_effect = invoke_api_side_effect
self.vops.get_all_profiles()
self.assertEqual(2, self.session.invoke_api.call_count)
# Clear side effects.
self.session.invoke_api.side_effect = None
def test_get_all_profiles_with_no_profiles(self):
self.session.invoke_api.return_value = []
res_type = mock.sentinel.res_type
self.session.pbm.client.factory.create.return_value = res_type
profiles = self.vops.get_all_profiles()
self.session.invoke_api.assert_called_once_with(
self.session.pbm,
'PbmQueryProfile',
self.session.pbm.service_content.profileManager,
resourceType=res_type)
self.assertEqual([], profiles)
def _create_profile(self, profile_id, name):
profile = mock.Mock()
profile.profileId = profile_id
profile.name = name
return profile
@mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.'
'get_all_profiles')
def test_retrieve_profile_id(self, get_all_profiles):
profiles = [self._create_profile(str(i), 'profile-%d' % i)
for i in range(0, 10)]
get_all_profiles.return_value = profiles
exp_profile_id = '5'
profile_id = self.vops.retrieve_profile_id(
'profile-%s' % exp_profile_id)
self.assertEqual(exp_profile_id, profile_id)
get_all_profiles.assert_called_once_with()
@mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.'
'get_all_profiles')
def test_retrieve_profile_id_with_invalid_profile(self, get_all_profiles):
profiles = [self._create_profile(str(i), 'profile-%d' % i)
for i in range(0, 10)]
get_all_profiles.return_value = profiles
profile_id = self.vops.retrieve_profile_id('profile-%s' % (i + 1))
self.assertIsNone(profile_id)
get_all_profiles.assert_called_once_with()
def test_filter_matching_hubs(self):
hubs = mock.Mock()
profile_id = 'profile-0'
self.vops.filter_matching_hubs(hubs, profile_id)
self.session.invoke_api.assert_called_once_with(
self.session.pbm,
'PbmQueryMatchingHub',
self.session.pbm.service_content.placementSolver,
hubsToSearch=hubs,
profile=profile_id)
class VirtualDiskPathTest(test.TestCase):
"""Unit tests for VirtualDiskPath."""
@ -1454,7 +1377,7 @@ class VirtualDiskTypeTest(test.TestCase):
volumeops.VirtualDiskType.validate("thick")
volumeops.VirtualDiskType.validate("thin")
volumeops.VirtualDiskType.validate("eagerZeroedThick")
self.assertRaises(error_util.InvalidDiskTypeException,
self.assertRaises(vmdk_exceptions.InvalidDiskTypeException,
volumeops.VirtualDiskType.validate,
"preallocated")
@ -1468,7 +1391,7 @@ class VirtualDiskTypeTest(test.TestCase):
self.assertEqual("eagerZeroedThick",
volumeops.VirtualDiskType.get_virtual_disk_type(
"eagerZeroedThick"))
self.assertRaises(error_util.InvalidDiskTypeException,
self.assertRaises(vmdk_exceptions.InvalidDiskTypeException,
volumeops.VirtualDiskType.get_virtual_disk_type,
"preallocated")
@ -1489,7 +1412,7 @@ class VirtualDiskAdapterTypeTest(test.TestCase):
volumeops.VirtualDiskAdapterType.validate("busLogic")
volumeops.VirtualDiskAdapterType.validate("lsiLogicsas")
volumeops.VirtualDiskAdapterType.validate("ide")
self.assertRaises(error_util.InvalidAdapterTypeException,
self.assertRaises(vmdk_exceptions.InvalidAdapterTypeException,
volumeops.VirtualDiskAdapterType.validate,
"pvscsi")
@ -1506,7 +1429,7 @@ class VirtualDiskAdapterTypeTest(test.TestCase):
self.assertEqual("ide",
volumeops.VirtualDiskAdapterType.get_adapter_type(
"ide"))
self.assertRaises(error_util.InvalidAdapterTypeException,
self.assertRaises(vmdk_exceptions.InvalidAdapterTypeException,
volumeops.VirtualDiskAdapterType.get_adapter_type,
"pvscsi")
@ -1527,7 +1450,7 @@ class ControllerTypeTest(test.TestCase):
self.assertEqual(volumeops.ControllerType.IDE,
volumeops.ControllerType.get_controller_type(
'ide'))
self.assertRaises(error_util.InvalidAdapterTypeException,
self.assertRaises(vmdk_exceptions.InvalidAdapterTypeException,
volumeops.ControllerType.get_controller_type,
'invalid_type')

View File

@ -1,353 +0,0 @@
# Copyright (c) 2013 VMware, Inc.
# All Rights Reserved.
#
# 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.
"""
Session and API call management for VMware ESX/VC server.
Provides abstraction over cinder.volume.drivers.vmware.vim.Vim SOAP calls.
"""
from cinder.i18n import _, _LE, _LI, _LW
from cinder.openstack.common import log as logging
from cinder.openstack.common import loopingcall
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import pbm
from cinder.volume.drivers.vmware import vim
from cinder.volume.drivers.vmware import vim_util
LOG = logging.getLogger(__name__)
class Retry(object):
"""Decorator for retrying a function upon suggested exceptions.
The method retries for given number of times and the sleep
time increments till the max sleep time is reached.
If max retries is set to -1, then the decorated function is
invoked indefinitely till no exception is thrown or if
the caught exception is not in the list of suggested exceptions.
"""
def __init__(self, max_retry_count=-1, inc_sleep_time=10,
max_sleep_time=60, exceptions=()):
"""Initialize retry object based on input params.
:param max_retry_count: Max number of times, a function must be
retried when one of input 'exceptions'
is caught. The default -1 will always
retry the function till a non-exception
case, or an un-wanted error case arises.
:param inc_sleep_time: Incremental time in seconds for sleep time
between retrial
:param max_sleep_time: Max sleep time beyond which the sleep time will
not be incremented using param inc_sleep_time
and max_sleep_time will be used as sleep time
:param exceptions: Suggested exceptions for which the function must be
retried
"""
self._max_retry_count = max_retry_count
self._inc_sleep_time = inc_sleep_time
self._max_sleep_time = max_sleep_time
self._exceptions = exceptions
self._retry_count = 0
self._sleep_time = 0
def __call__(self, f):
def _func(*args, **kwargs):
try:
result = f(*args, **kwargs)
except self._exceptions as excep:
LOG.exception(_LE("Failure while invoking function: "
"%(func)s. Error: %(excep)s.") %
{'func': f.__name__, 'excep': excep})
if (self._max_retry_count != -1 and
self._retry_count >= self._max_retry_count):
raise excep
else:
self._retry_count += 1
self._sleep_time += self._inc_sleep_time
return self._sleep_time
except Exception as excep:
raise excep
# got result. Stop the loop.
raise loopingcall.LoopingCallDone(result)
def func(*args, **kwargs):
loop = loopingcall.DynamicLoopingCall(_func, *args, **kwargs)
timer = loop.start(periodic_interval_max=self._max_sleep_time)
return timer.wait()
return func
class VMwareAPISession(object):
"""Sets up a session with the server and handles all calls made to it."""
def __init__(self, server_ip, server_username, server_password,
api_retry_count, task_poll_interval, scheme='https',
create_session=True, wsdl_loc=None, pbm_wsdl=None):
"""Constructs session object.
:param server_ip: IP address of ESX/VC server
:param server_username: Username of ESX/VC server admin user
:param server_password: Password for param server_username
:param api_retry_count: Number of times an API must be retried upon
session/connection related errors
:param task_poll_interval: Sleep time in seconds for polling an
on-going async task as part of the API call
:param scheme: http or https protocol
:param create_session: Boolean whether to set up connection at the
time of instance creation
:param wsdl_loc: VIM WSDL file location for invoking SOAP calls on
server using suds
:param pbm_wsdl: PBM WSDL file location. If set to None the storage
policy related functionality will be disabled.
"""
self._server_ip = server_ip
self._server_username = server_username
self._server_password = server_password
self._wsdl_loc = wsdl_loc
self._api_retry_count = api_retry_count
self._task_poll_interval = task_poll_interval
self._scheme = scheme
self._session_id = None
self._session_username = None
self._vim = None
self._pbm_wsdl = pbm_wsdl
self._pbm = None
if create_session:
self.create_session()
@property
def vim(self):
if not self._vim:
self._vim = vim.Vim(protocol=self._scheme, host=self._server_ip,
wsdl_loc=self._wsdl_loc)
return self._vim
@property
def pbm(self):
if not self._pbm and self._pbm_wsdl:
self._pbm = pbm.PBMClient(self.vim, self._pbm_wsdl,
protocol=self._scheme,
host=self._server_ip)
return self._pbm
@Retry(exceptions=(error_util.VimConnectionException,))
def create_session(self):
"""Establish session with the server."""
# Login and setup the session with the server for making
# API calls
session_manager = self.vim.service_content.sessionManager
session = self.vim.Login(session_manager,
userName=self._server_username,
password=self._server_password)
# Terminate the earlier session, if possible (For the sake of
# preserving sessions as there is a limit to the number of
# sessions we can have)
if self._session_id:
try:
self.vim.TerminateSession(session_manager,
sessionId=[self._session_id])
except Exception as excep:
# This exception is something we can live with. It is
# just an extra caution on our side. The session may
# have been cleared. We could have made a call to
# SessionIsActive, but that is an overhead because we
# anyway would have to call TerminateSession.
LOG.exception(_LE("Error while terminating session: %s.") %
excep)
self._session_id = session.key
# We need to save the username in the session since we may need it
# later to check active session. The SessionIsActive method requires
# the username parameter to be exactly same as that in the session
# object. We can't use the username used for login since the Login
# method ignores the case.
self._session_username = session.userName
if self.pbm:
self.pbm.set_cookie()
LOG.info(_LI("Successfully established connection to the server."))
def __del__(self):
"""Logs-out the sessions."""
try:
self.vim.Logout(self.vim.service_content.sessionManager)
except Exception as excep:
LOG.exception(_LE("Error while logging out from vim session: %s."),
excep)
if self._pbm:
try:
self.pbm.Logout(self.pbm.service_content.sessionManager)
except Exception as excep:
LOG.exception(_LE("Error while logging out from pbm session: "
"%s."), excep)
def invoke_api(self, module, method, *args, **kwargs):
"""Wrapper method for invoking APIs.
Here we retry the API calls for exceptions which may come because
of session overload.
Make sure if a Vim instance is being passed here, this session's
Vim (self.vim) instance is used, as we retry establishing session
in case of session timedout.
:param module: Module invoking the VI SDK calls
:param method: Method in the module that invokes the VI SDK call
:param args: Arguments to the method
:param kwargs: Keyword arguments to the method
:return: Response of the API call
"""
@Retry(max_retry_count=self._api_retry_count,
exceptions=(error_util.SessionOverLoadException,
error_util.VimConnectionException))
def _invoke_api(module, method, *args, **kwargs):
while True:
try:
api_method = getattr(module, method)
return api_method(*args, **kwargs)
except error_util.VimFaultException as excep:
if error_util.NOT_AUTHENTICATED not in excep.fault_list:
raise excep
# If it is a not-authenticated fault, we re-authenticate
# the user and retry the API invocation.
# The not-authenticated fault is set by the fault checker
# due to an empty response. An empty response could be a
# valid response; for e.g., response for the query to
# return the VMs in an ESX server which has no VMs in it.
# Also, the server responds with an empty response in the
# case of an inactive session. Therefore, we need a way to
# differentiate between these two cases.
if self._is_current_session_active():
LOG.debug("Returning empty response for "
"%(module)s.%(method)s invocation.",
{'module': module,
'method': method})
return []
# empty response is due to an inactive session
LOG.warn(_LW("Current session: %(session)s is inactive; "
"re-creating the session while invoking "
"method %(module)s.%(method)s."),
{'session': self._session_id,
'module': module,
'method': method},
exc_info=True)
self.create_session()
return _invoke_api(module, method, *args, **kwargs)
def _is_current_session_active(self):
"""Check if current session is active.
:returns: True if the session is active; False otherwise
"""
LOG.debug("Checking if the current session: %s is active.",
self._session_id)
is_active = False
try:
is_active = self.vim.SessionIsActive(
self.vim.service_content.sessionManager,
sessionID=self._session_id,
userName=self._session_username)
except error_util.VimException:
LOG.warn(_LW("Error occurred while checking whether the "
"current session: %s is active."),
self._session_id,
exc_info=True)
return is_active
def wait_for_task(self, task):
"""Return a deferred that will give the result of the given task.
The task is polled until it completes. The method returns the task
information upon successful completion.
:param task: Managed object reference of the task
:return: Task info upon successful completion of the task
"""
loop = loopingcall.FixedIntervalLoopingCall(self._poll_task, task)
return loop.start(self._task_poll_interval).wait()
def _poll_task(self, task):
"""Poll the given task.
If the task completes successfully then returns task info.
In case of error sends back appropriate error.
:param task: Managed object reference of the task
:param event: Event that captures task status
"""
try:
task_info = self.invoke_api(vim_util, 'get_object_property',
self.vim, task, 'info')
if task_info.state in ['queued', 'running']:
# If task already completed on server, it will not return
# the progress.
if hasattr(task_info, 'progress'):
LOG.debug("Task: %(task)s progress: %(prog)s." %
{'task': task, 'prog': task_info.progress})
return
elif task_info.state == 'success':
LOG.debug("Task %s status: success." % task)
else:
error_msg = str(task_info.error.localizedMessage)
LOG.exception(_LE("Task: %(task)s failed with "
"error: %(err)s.") %
{'task': task, 'err': error_msg})
raise error_util.VimFaultException([], error_msg)
except Exception as excep:
LOG.exception(_LE("Task: %(task)s failed with "
"error: %(err)s.") %
{'task': task, 'err': excep})
raise excep
# got the result. So stop the loop.
raise loopingcall.LoopingCallDone(task_info)
def wait_for_lease_ready(self, lease):
loop = loopingcall.FixedIntervalLoopingCall(self._poll_lease, lease)
return loop.start(self._task_poll_interval).wait()
def _poll_lease(self, lease):
try:
state = self.invoke_api(vim_util, 'get_object_property',
self.vim, lease, 'state')
if state == 'ready':
# done
LOG.debug("Lease is ready.")
elif state == 'initializing':
LOG.debug("Lease initializing...")
return
elif state == 'error':
error_msg = self.invoke_api(vim_util, 'get_object_property',
self.vim, lease, 'error')
LOG.exception(error_msg)
excep = error_util.VimFaultException([], error_msg)
raise excep
else:
# unknown state - complain
error_msg = _("Error: unknown lease state %s.") % state
raise error_util.VimFaultException([], error_msg)
except Exception as excep:
LOG.exception(excep)
raise excep
# stop the loop since state is ready
raise loopingcall.LoopingCallDone()

View File

@ -18,11 +18,12 @@ Classes and utility methods for datastore selection.
"""
from oslo_utils import excutils
from oslo_vmware import exceptions
from oslo_vmware import pbm
from cinder.i18n import _LE, _LW
from cinder.openstack.common import log as logging
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import vim_util
from cinder.volume.drivers.vmware import exceptions as vmdk_exceptions
LOG = logging.getLogger(__name__)
@ -45,7 +46,7 @@ class DatastoreSelector(object):
SIZE_BYTES = "sizeBytes"
PROFILE_NAME = "storageProfileName"
# TODO(vbala) Remove dependency on volumeops and vim_util.
# TODO(vbala) Remove dependency on volumeops.
def __init__(self, vops, session):
self._vops = vops
self._session = session
@ -57,11 +58,11 @@ class DatastoreSelector(object):
:return: vCenter profile ID
:raises: ProfileNotFoundException
"""
profile_id = self._vops.retrieve_profile_id(profile_name)
profile_id = pbm.get_profile_id_by_name(self._session, profile_name)
if profile_id is None:
LOG.error(_LE("Storage profile: %s cannot be found in vCenter."),
profile_name)
raise error_util.ProfileNotFoundException(
raise vmdk_exceptions.ProfileNotFoundException(
storage_profile=profile_name)
LOG.debug("Storage profile: %(name)s resolved to vCenter profile ID: "
"%(id)s.",
@ -72,9 +73,10 @@ class DatastoreSelector(object):
def _filter_by_profile(self, datastores, profile_id):
"""Filter out input datastores that do not match the given profile."""
cf = self._session.pbm.client.factory
hubs = vim_util.convert_datastores_to_hubs(cf, datastores)
filtered_hubs = self._vops.filter_matching_hubs(hubs, profile_id)
return vim_util.convert_hubs_to_datastores(filtered_hubs, datastores)
hubs = pbm.convert_datastores_to_hubs(cf, datastores)
filtered_hubs = pbm.filter_hubs_by_profile(self._session, hubs,
profile_id)
return pbm.filter_datastores_by_hubs(filtered_hubs, datastores)
def _filter_datastores(self, datastores, size_bytes, profile_id,
hard_anti_affinity_datastores,
@ -207,12 +209,12 @@ class DatastoreSelector(object):
for host_ref in hosts:
try:
(datastores, rp) = self._vops.get_dss_rp(host_ref)
except error_util.VimConnectionException:
except exceptions.VimConnectionException:
# No need to try other hosts when there is a connection problem
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Error occurred while "
"selecting datastore."))
except error_util.VimException:
except exceptions.VimException:
# TODO(vbala) volumeops.get_dss_rp shouldn't throw VimException
# for empty datastore list.
LOG.warn(_LW("Unable to fetch datastores connected "

View File

@ -1,95 +0,0 @@
# Copyright (c) 2013 VMware, Inc.
# All Rights Reserved.
#
# 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.
"""
from cinder import exception
from cinder.i18n import _
NOT_AUTHENTICATED = 'NotAuthenticated'
class VimException(exception.CinderException):
"""The VIM Exception class."""
def __init__(self, msg):
exception.CinderException.__init__(self, msg)
class SessionOverLoadException(VimException):
"""Session Overload Exception."""
pass
class VimAttributeException(VimException):
"""VI Attribute Error."""
pass
class VimConnectionException(VimException):
"""Thrown when there is a connection problem."""
pass
class VimFaultException(VimException):
"""Exception thrown when there are faults during VIM API calls."""
def __init__(self, fault_list, msg):
super(VimFaultException, self).__init__(msg)
self.fault_list = fault_list
class VMwareDriverException(exception.CinderException):
"""Base class for all exceptions raised by the VMDK driver.
All exceptions raised by the vmdk driver should raise an exception
descended from this class as a root. This will allow the driver to
potentially trap problems related to its own internal configuration
before halting the cinder-volume node.
"""
message = _("VMware VMDK driver exception.")
class VMwaredriverConfigurationException(VMwareDriverException):
"""Base class for all configuration exceptions.
"""
message = _("VMware VMDK driver configuration error.")
class InvalidAdapterTypeException(VMwareDriverException):
"""Thrown when the disk adapter type is invalid."""
message = _("Invalid disk adapter type: %(invalid_type)s.")
class InvalidDiskTypeException(VMwareDriverException):
"""Thrown when the disk type is invalid."""
message = _("Invalid disk type: %(disk_type)s.")
class ImageTransferException(VMwareDriverException):
"""Thrown when there is an error during image transfer."""
message = _("Error occurred during image transfer.")
class VirtualDiskNotFoundException(VMwareDriverException):
"""Thrown when virtual disk is not found."""
message = _("There is no virtual disk device.")
class ProfileNotFoundException(VMwareDriverException):
"""Thrown when the given storage profile cannot be found."""
message = _("Storage profile: %(storage_profile)s not found.")

View File

@ -0,0 +1,42 @@
# Copyright (c) 2015 VMware, Inc.
# All Rights Reserved.
#
# 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 definitions.
"""
from oslo_vmware import exceptions
from cinder.i18n import _
class InvalidAdapterTypeException(exceptions.VMwareDriverException):
"""Thrown when the disk adapter type is invalid."""
msg_fmt = _("Invalid disk adapter type: %(invalid_type)s.")
class InvalidDiskTypeException(exceptions.VMwareDriverException):
"""Thrown when the disk type is invalid."""
msg_fmt = _("Invalid disk type: %(disk_type)s.")
class VirtualDiskNotFoundException(exceptions.VMwareDriverException):
"""Thrown when virtual disk is not found."""
msg_fmt = _("There is no virtual disk device.")
class ProfileNotFoundException(exceptions.VMwareDriverException):
"""Thrown when the given storage profile cannot be found."""
msg_fmt = _("Storage profile: %(storage_profile)s not found.")

View File

@ -1,207 +0,0 @@
# Copyright (c) 2013 VMware, Inc.
# All Rights Reserved.
#
# 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.
"""
import errno
from eventlet import event
from eventlet import greenthread
from eventlet import queue
from cinder.i18n import _
from cinder.openstack.common import log as logging
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import read_write_util
LOG = logging.getLogger(__name__)
IO_THREAD_SLEEP_TIME = .01
GLANCE_POLL_INTERVAL = 5
class ThreadSafePipe(queue.LightQueue):
"""The pipe to hold the data which the reader writes to and the writer
reads from.
"""
def __init__(self, maxsize, max_transfer_size):
queue.LightQueue.__init__(self, maxsize)
self.max_transfer_size = max_transfer_size
self.transferred = 0
def read(self, chunk_size):
"""Read data from the pipe.
Chunksize is ignored for we have ensured that the data chunks written
to the pipe by readers is the same as the chunks asked for by Writer.
"""
if self.transferred < self.max_transfer_size:
data_item = self.get()
self.transferred += len(data_item)
LOG.debug("Read %(bytes)s out of %(max)s from ThreadSafePipe." %
{'bytes': self.transferred,
'max': self.max_transfer_size})
return data_item
else:
LOG.debug("Completed transfer of size %s." % self.transferred)
return ""
def write(self, data):
"""Put a data item in the pipe."""
self.put(data)
def seek(self, offset, whence=0):
"""Set the file's current position at the offset."""
# Illegal seek; the file object is a pipe
raise IOError(errno.ESPIPE, "Illegal seek")
def tell(self):
"""Get size of the file to be read."""
return self.max_transfer_size
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, context, input_file, image_service, image_id,
image_meta=None):
if not image_meta:
image_meta = {}
self.context = context
self.input_file = input_file
self.image_service = image_service
self.image_id = image_id
self.image_meta = image_meta
self._running = False
def start(self):
self.done = event.Event()
def _inner():
"""Initiate write thread.
Function to do the image data transfer through an update
and thereon checks if the state is 'active'.
"""
LOG.debug("Initiating image service update on image: %(image)s "
"with meta: %(meta)s" % {'image': self.image_id,
'meta': self.image_meta})
try:
self.image_service.update(self.context,
self.image_id,
self.image_meta,
data=self.input_file)
self._running = True
while self._running:
image_meta = self.image_service.show(self.context,
self.image_id)
image_status = image_meta.get('status')
if image_status == 'active':
self.stop()
LOG.debug("Glance image: %s is now active." %
self.image_id)
self.done.send(True)
# If the state is killed, then raise an exception.
elif image_status == 'killed':
self.stop()
msg = (_("Glance image: %s is in killed state.") %
self.image_id)
LOG.error(msg)
excep = error_util.ImageTransferException(msg)
self.done.send_exception(excep)
elif image_status in ['saving', 'queued']:
greenthread.sleep(GLANCE_POLL_INTERVAL)
else:
self.stop()
msg = _("Glance image %(id)s is in unknown state "
"- %(state)s") % {'id': self.image_id,
'state': image_status}
LOG.error(msg)
excep = error_util.ImageTransferException(msg)
self.done.send_exception(excep)
except Exception as ex:
self.stop()
msg = (_("Error occurred while writing to image: %s") %
self.image_id)
LOG.exception(msg)
excep = error_util.ImageTransferException(ex)
self.done.send_exception(excep)
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_file, output_file):
self.input_file = input_file
self.output_file = output_file
self._running = False
self.got_exception = False
def start(self):
self.done = event.Event()
def _inner():
"""Read data from input and write the same to output."""
self._running = True
while self._running:
try:
data = self.input_file.read(read_write_util.READ_CHUNKSIZE)
if not data:
self.stop()
self.done.send(True)
self.output_file.write(data)
if hasattr(self.input_file, "update_progress"):
self.input_file.update_progress()
if hasattr(self.output_file, "update_progress"):
self.output_file.update_progress()
greenthread.sleep(IO_THREAD_SLEEP_TIME)
except Exception as 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,97 +0,0 @@
# Copyright (c) 2013 VMware, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Class for making VMware PBM SOAP calls.
This is used for storage policy based placement of volumes. Read more about
it here:
http://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.vspsdk.apiref.doc/\
right-pane.html
"""
import suds
import suds.sax.element as element
from cinder.openstack.common import log as logging
from cinder.volume.drivers.vmware import vim as vim_module
from cinder.volume.drivers.vmware import vim_util
LOG = logging.getLogger(__name__)
SERVICE_INSTANCE = 'ServiceInstance'
SERVICE_TYPE = 'PbmServiceInstance'
class PBMClient(vim_module.Vim):
"""Sets up a client to interact with the vSphere PBM APIs.
This client piggy backs on Vim object's authenticated cookie to invoke
PBM API calls.
Note that this class needs the PBM wsdl file in order to make SOAP API
calls. This wsdl file is included in the VMware Storage Policy SDK.
A user of this feature needs to install this SDK on the Cinder volume
nodes and configure the path in the cinder.conf file.
"""
def __init__(self, vimSession, pbm_wsdl, protocol='https',
host='localhost'):
"""Constructs a PBM client object.
:param vimSession: an authenticated api.VMwareAPISession object
:param pbm_wsdl: URL path to where pbmService.wsdl file is located.
:param protocol: http or https
:param host: Server IPAddress[:port] or Hostname[:port]
"""
self._vimSession = vimSession
self._url = vim_util.get_soap_url(protocol, host, 'pbm')
# create the pbm client
self._client = suds.client.Client(pbm_wsdl, location=self._url,
cache=suds.cache.NoCache())
PBMClient._copy_client_cookie(self._vimSession, self._client)
# Get the PBM service content
si_moref = vim_module.get_moref(SERVICE_INSTANCE, SERVICE_TYPE)
self._sc = self._client.service.PbmRetrieveServiceContent(si_moref)
@staticmethod
def _copy_client_cookie(vimSession, pbmClient):
"""Copy the vim session cookie to pbm client soap header.
:param vimSession: an vim session authenticated with VC/ESX
:param pbmClient: a PBMClient object to set the session cookie
"""
vcSessionCookie = PBMClient._get_vc_session_cookie(vimSession)
vcc = element.Element('vcSessionCookie').setText(vcSessionCookie)
pbmClient.set_options(soapheaders=vcc)
@staticmethod
def _get_vc_session_cookie(vimSession):
"""Look for vmware_soap_session cookie in vimSession."""
cookies = vimSession.client.options.transport.cookiejar
for c in cookies:
if c.name.lower() == 'vmware_soap_session':
return c.value
@property
def service_content(self):
return self._sc
@property
def client(self):
return self._client
def set_cookie(self):
"""Set the authenticated vim session cookie in this pbm client."""
PBMClient._copy_client_cookie(self._vimSession, self.client)

View File

@ -1,338 +0,0 @@
# Copyright (c) 2013 VMware, Inc.
# All Rights Reserved.
#
# 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 VMware server.
"""
import httplib
import urllib
import urllib2
from oslo_utils import netutils
import six.moves.urllib.parse as urlparse
from cinder.i18n import _, _LI
from cinder.openstack.common import log as logging
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import vim_util
LOG = logging.getLogger(__name__)
USER_AGENT = 'OpenStack-ESX-Adapter'
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 VMDK file access over HTTP."""
def __init__(self, file_handle):
self.eof = False
self.file_handle = file_handle
def close(self):
"""Close the file handle."""
try:
self.file_handle.close()
except Exception as 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()
def get_soap_url(self, scheme, host):
"""return IPv4/v6 compatible url constructed for host."""
if netutils.is_valid_ipv6(host):
return '%s://[%s]' % (scheme, host)
return '%s://%s' % (scheme, host)
def _fix_esx_url(self, url, host):
"""Fix netloc if it is a ESX host.
For a ESX host the netloc is set to '*' in the url returned in
HttpNfcLeaseInfo. The netloc is right IP when talking to a VC.
"""
urlp = urlparse.urlparse(url)
if urlp.netloc == '*':
scheme, _, path, params, query, fragment = urlp
url = urlparse.urlunparse((scheme, host, path, params,
query, fragment))
return url
def find_vmdk_url(self, lease_info, host):
"""Find the URL corresponding to a vmdk disk in lease info."""
url = None
for deviceUrl in lease_info.deviceUrl:
if deviceUrl.disk:
url = self._fix_esx_url(deviceUrl.url, host)
break
return url
class VMwareHTTPWriteFile(VMwareHTTPFile):
"""VMware file write handler class."""
def __init__(self, host, data_center_name, datastore_name, cookies,
file_path, file_size, scheme='https'):
soap_url = self.get_soap_url(scheme, host)
base_url = '%s/folder/%s' % (soap_url, file_path)
param_list = {'dcPath': data_center_name, 'dsName': datastore_name}
base_url = base_url + '?' + urllib.urlencode(param_list)
_urlparse = urlparse.urlparse(base_url)
scheme, netloc, path, _params, query, _fragment = _urlparse
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 as excep:
LOG.debug("Exception during HTTP connection close in "
"VMwareHTTPWrite. Exception is %s." % excep)
super(VMwareHTTPWriteFile, self).close()
class VMwareHTTPWriteVmdk(VMwareHTTPFile):
"""Write VMDK over HTTP using VMware HttpNfcLease."""
def __init__(self, session, host, rp_ref, vm_folder_ref, vm_create_spec,
vmdk_size):
"""Initialize a writer for vmdk file.
:param session: a valid api session to ESX/VC server
:param host: the ESX or VC host IP
:param rp_ref: resource pool into which backing VM is imported
:param vm_folder_ref: VM folder in ESX/VC inventory to use as parent
of backing VM
:param vm_create_spec: backing VM created using this create spec
:param vmdk_size: VMDK size to be imported into backing VM
"""
self._session = session
self._vmdk_size = vmdk_size
self._progress = 0
lease = session.invoke_api(session.vim, 'ImportVApp', rp_ref,
spec=vm_create_spec, folder=vm_folder_ref)
session.wait_for_lease_ready(lease)
self._lease = lease
lease_info = session.invoke_api(vim_util, 'get_object_property',
session.vim, lease, 'info')
self._vm_ref = lease_info.entity
# Find the url for vmdk device
url = self.find_vmdk_url(lease_info, host)
if not url:
msg = _("Could not retrieve URL from lease.")
LOG.exception(msg)
raise error_util.VimException(msg)
LOG.info(_LI("Opening vmdk url: %s for write.") % url)
# Prepare the http connection to the vmdk url
cookies = session.vim.client.options.transport.cookiejar
_urlparse = urlparse.urlparse(url)
scheme, netloc, path, _params, query, _fragment = _urlparse
if scheme == 'http':
conn = httplib.HTTPConnection(netloc)
elif scheme == 'https':
conn = httplib.HTTPSConnection(netloc)
if query:
path = path + '?' + query
conn.putrequest('PUT', path)
conn.putheader('User-Agent', USER_AGENT)
conn.putheader('Content-Length', str(vmdk_size))
conn.putheader('Overwrite', 't')
conn.putheader('Cookie', self._build_vim_cookie_headers(cookies))
conn.putheader('Content-Type', 'binary/octet-stream')
conn.endheaders()
self.conn = conn
VMwareHTTPFile.__init__(self, conn)
def write(self, data):
"""Write to the file."""
self._progress += len(data)
LOG.debug("Written %s bytes to vmdk." % self._progress)
self.file_handle.send(data)
def update_progress(self):
"""Updates progress to lease.
This call back to the lease is essential to keep the lease alive
across long running write operations.
"""
percent = int(float(self._progress) / self._vmdk_size * 100)
try:
LOG.debug("Updating progress to %s percent." % percent)
self._session.invoke_api(self._session.vim,
'HttpNfcLeaseProgress',
self._lease, percent=percent)
except error_util.VimException as ex:
LOG.exception(ex)
raise ex
def close(self):
"""End the lease and close the connection."""
state = self._session.invoke_api(vim_util, 'get_object_property',
self._session.vim,
self._lease, 'state')
if state == 'ready':
self._session.invoke_api(self._session.vim, 'HttpNfcLeaseComplete',
self._lease)
LOG.debug("Lease released.")
else:
LOG.debug("Lease is already in state: %s." % state)
super(VMwareHTTPWriteVmdk, self).close()
def get_imported_vm(self):
""""Get managed object reference of the VM created for import."""
return self._vm_ref
class VMwareHTTPReadVmdk(VMwareHTTPFile):
"""read VMDK over HTTP using VMware HttpNfcLease."""
def __init__(self, session, host, vm_ref, vmdk_path, vmdk_size):
"""Initialize a writer for vmdk file.
During an export operation the vmdk disk is converted to a
stream-optimized sparse disk format. So the size of the VMDK
after export may be smaller than the current vmdk disk size.
:param session: a valid api session to ESX/VC server
:param host: the ESX or VC host IP
:param vm_ref: backing VM whose vmdk is to be exported
:param vmdk_path: datastore relative path to vmdk file to be exported
:param vmdk_size: current disk size of vmdk file to be exported
"""
self._session = session
self._vmdk_size = vmdk_size
self._progress = 0
lease = session.invoke_api(session.vim, 'ExportVm', vm_ref)
session.wait_for_lease_ready(lease)
self._lease = lease
lease_info = session.invoke_api(vim_util, 'get_object_property',
session.vim, lease, 'info')
# find the right disk url corresponding to given vmdk_path
url = self.find_vmdk_url(lease_info, host)
if not url:
msg = _("Could not retrieve URL from lease.")
LOG.exception(msg)
raise error_util.VimException(msg)
LOG.info(_LI("Opening vmdk url: %s for read.") % url)
cookies = session.vim.client.options.transport.cookiejar
headers = {'User-Agent': USER_AGENT,
'Cookie': self._build_vim_cookie_headers(cookies)}
request = urllib2.Request(url, None, headers)
conn = urllib2.urlopen(request)
VMwareHTTPFile.__init__(self, conn)
def read(self, chunk_size):
"""Read a chunk from file."""
data = self.file_handle.read(READ_CHUNKSIZE)
self._progress += len(data)
LOG.debug("Read %s bytes from vmdk." % self._progress)
return data
def update_progress(self):
"""Updates progress to lease.
This call back to the lease is essential to keep the lease alive
across long running read operations.
"""
percent = int(float(self._progress) / self._vmdk_size * 100)
try:
LOG.debug("Updating progress to %s percent." % percent)
self._session.invoke_api(self._session.vim,
'HttpNfcLeaseProgress',
self._lease, percent=percent)
except error_util.VimException as ex:
LOG.exception(ex)
raise ex
def close(self):
"""End the lease and close the connection."""
state = self._session.invoke_api(vim_util, 'get_object_property',
self._session.vim,
self._lease, 'state')
if state == 'ready':
self._session.invoke_api(self._session.vim, 'HttpNfcLeaseComplete',
self._lease)
LOG.debug("Lease released.")
else:
LOG.debug("Lease is already in state: %s." % state)
super(VMwareHTTPReadVmdk, self).close()

View File

@ -1,238 +0,0 @@
# Copyright (c) 2013 VMware, Inc.
# All Rights Reserved.
#
# 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
import urllib2
import suds
from cinder.i18n import _
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import vim_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'
def get_moref(value, type):
"""Get managed object reference.
:param value: value for the managed object
:param type: type of the managed object
:return: Managed object reference with input value and type
"""
moref = suds.sudsobject.Property(value)
moref._type = type
return moref
class VIMMessagePlugin(suds.plugin.MessagePlugin):
def addAttributeForValue(self, node):
"""Helper to handle AnyType.
suds does not handle AnyType properly.
VI SDK requires type attribute to be set when AnyType is used
:param node: XML value node
"""
if node.name == 'value':
node.set('xsi:type', 'xsd:string')
def marshalled(self, context):
"""Marshal soap context.
Provides the plugin with the opportunity to prune empty
nodes and fixup nodes before sending it to the server.
:param context: SOAP context
"""
# 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(object):
"""The VIM Object."""
def __init__(self, protocol='https', host='localhost', wsdl_loc=None):
"""Create communication interfaces for initiating SOAP transactions.
:param protocol: http or https
:param host: Server IPAddress[:port] or Hostname[:port]
"""
self._protocol = protocol
self._host_name = host
if not wsdl_loc:
wsdl_loc = Vim._get_wsdl_loc(protocol, host)
soap_url = vim_util.get_soap_url(protocol, host)
self._client = suds.client.Client(wsdl_loc, location=soap_url,
plugins=[VIMMessagePlugin()],
cache=suds.cache.NoCache())
self._service_content = self.RetrieveServiceContent('ServiceInstance')
@staticmethod
def _get_wsdl_loc(protocol, host_name):
"""Return default WSDL file location hosted at the server.
:param protocol: http or https
:param host_name: ESX/VC server host name
:return: Default WSDL file location hosted at the server
"""
return vim_util.get_soap_url(protocol, host_name) + '/vimService.wsdl'
@property
def service_content(self):
return self._service_content
@property
def client(self):
return self._client
def __getattr__(self, attr_name):
"""Makes the API call and gets the result."""
def retrieve_properties_ex_fault_checker(response):
"""Checks the RetrievePropertiesEx response for errors.
Certain faults are sent as part of the SOAP body as property of
missingSet. For example NotAuthenticated fault. The method raises
appropriate VimFaultException when an error is found.
:param response: Response from RetrievePropertiesEx API call
"""
fault_list = []
if not response:
# This is the case when the session has timed out. ESX SOAP
# server sends an empty RetrievePropertiesExResponse. 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 = [error_util.NOT_AUTHENTICATED]
else:
for obj_cont in response:
if hasattr(obj_cont, 'missingSet'):
for missing_elem in obj_cont.missingSet:
fault_type = missing_elem.fault.fault.__class__
# Fault needs to be added to the type of fault
# for uniformity in error checking as SOAP faults
# define
fault_list.append(fault_type.__name__)
if fault_list:
exc_msg_list = ', '.join(fault_list)
raise error_util.VimFaultException(fault_list,
_("Error(s): %s occurred "
"in the call to "
"RetrievePropertiesEx.") %
exc_msg_list)
def vim_request_handler(managed_object, **kwargs):
"""Handler for VI SDK calls.
Builds the SOAP message and parses the response for fault
checking and other errors.
:param managed_object:Managed object reference
:param kwargs: Keyword arguments of the call
:return: Response of the API call
"""
try:
if isinstance(managed_object, str):
# For strings use string value for value and type
# of the managed object.
managed_object = get_moref(managed_object, managed_object)
request = getattr(self.client.service, attr_name)
response = request(managed_object, **kwargs)
if (attr_name.lower() == 'retrievepropertiesex'):
retrieve_properties_ex_fault_checker(response)
return response
except error_util.VimFaultException as excep:
raise
except suds.WebFault as excep:
doc = excep.document
detail = doc.childAtPath('/Envelope/Body/Fault/detail')
fault_list = []
if detail is not None:
for child in detail.getChildren():
fault_list.append(child.get('type'))
raise error_util.VimFaultException(fault_list, excep)
except AttributeError as excep:
raise error_util.VimAttributeException(_("No such SOAP method "
"%(attr)s. Detailed "
"error: %(excep)s.") %
{'attr': attr_name,
'excep': excep})
except (httplib.CannotSendRequest,
httplib.ResponseNotReady,
httplib.CannotSendHeader) as excep:
raise error_util.SessionOverLoadException(_("httplib error in "
"%(attr)s: "
"%(excep)s.") %
{'attr': attr_name,
'excep': excep})
except (urllib2.URLError, urllib2.HTTPError) as excep:
raise error_util.VimConnectionException(
_("urllib2 error in %(attr)s: %(excep)s.") %
{'attr': attr_name,
'excep': excep})
except Exception as excep:
# Socket errors which need special handling for they
# might be caused by server 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 %(attr)s: "
"%(excep)s.") %
{'attr':
attr_name,
'excep': excep})
# Type error that needs special handling for it might be
# caused by server API call overload
elif str(excep).find(RESP_NOT_XML_ERROR) != -1:
raise error_util.SessionOverLoadException(_("Type error "
"in %(attr)s: "
"%(excep)s.") %
{'attr':
attr_name,
'excep': excep})
else:
raise error_util.VimException(_("Error in %(attr)s. "
"Detailed error: "
"%(excep)s.") %
{'attr': attr_name,
'excep': excep})
return vim_request_handler
def __repr__(self):
return "VIM Object."
def __str__(self):
return "VIM Object."

View File

@ -1,344 +0,0 @@
# Copyright (c) 2013 VMware, Inc.
# All Rights Reserved.
#
# 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.
"""
from oslo_utils import netutils
def get_soap_url(protocol, host, path='sdk'):
"""Return URL to SOAP services for ESX/VC server.
:param protocol: https or http
:param host: ESX/VC server host IP
:param path: path part of the SOAP URL
:return: URL to SOAP services for ESX/VC server
"""
if netutils.is_valid_ipv6(host):
return '%s://[%s]/%s' % (protocol, host, path)
return '%s://%s/%s' % (protocol, host, path)
def build_selection_spec(client_factory, name):
"""Builds the selection spec.
:param client_factory: Factory to get API input specs
:param name: Name for the selection spec
:return: Selection spec
"""
sel_spec = client_factory.create('ns0:SelectionSpec')
sel_spec.name = name
return sel_spec
def build_traversal_spec(client_factory, name, type, path, skip,
select_set):
"""Builds the traversal spec object.
:param client_factory: Factory to get API input specs
:param name: Name for the traversal spec
:param type: Type of the managed object reference
:param path: Property path of the managed object reference
:param skip: Whether or not to filter the object identified by param path
:param select_set: Set of selection specs specifying additional objects
to filter
:return: Traversal spec
"""
traversal_spec = client_factory.create('ns0:TraversalSpec')
traversal_spec.name = name
traversal_spec.type = 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 Recursive Traversal Spec to traverse managed object hierarchy.
:param client_factory: Factory to get API input specs
:return: Recursive traversal spec
"""
visit_folders_select_spec = build_selection_spec(client_factory,
'visitFolders')
# Next hop from Datacenter
dc_to_hf = build_traversal_spec(client_factory, 'dc_to_hf', 'Datacenter',
'hostFolder', False,
[visit_folders_select_spec])
dc_to_vmf = build_traversal_spec(client_factory, 'dc_to_vmf', 'Datacenter',
'vmFolder', False,
[visit_folders_select_spec])
# Next hop from HostSystem
h_to_vm = build_traversal_spec(client_factory, 'h_to_vm', 'HostSystem',
'vm', False,
[visit_folders_select_spec])
# Next hop from ComputeResource
cr_to_h = build_traversal_spec(client_factory, 'cr_to_h',
'ComputeResource', 'host', False, [])
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')
cr_to_rp = build_traversal_spec(client_factory, 'cr_to_rp',
'ComputeResource', 'resourcePool', False,
[rp_to_rp_select_spec,
rp_to_vm_select_spec])
# Next hop from ClusterComputeResource
ccr_to_h = build_traversal_spec(client_factory, 'ccr_to_h',
'ClusterComputeResource', 'host',
False, [])
ccr_to_ds = build_traversal_spec(client_factory, 'ccr_to_ds',
'ClusterComputeResource', 'datastore',
False, [])
ccr_to_rp = build_traversal_spec(client_factory, 'ccr_to_rp',
'ClusterComputeResource', 'resourcePool',
False,
[rp_to_rp_select_spec,
rp_to_vm_select_spec])
# Next hop from ResourcePool
rp_to_rp = build_traversal_spec(client_factory, 'rp_to_rp', 'ResourcePool',
'resourcePool', False,
[rp_to_rp_select_spec,
rp_to_vm_select_spec])
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 rootFolder
traversal_spec = build_traversal_spec(client_factory, 'visitFolders',
'Folder', 'childEntity', False,
[visit_folders_select_spec,
h_to_vm, dc_to_hf, dc_to_vmf,
cr_to_ds, cr_to_h, cr_to_rp,
ccr_to_h, ccr_to_ds, ccr_to_rp,
rp_to_rp, 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.
:param client_factory: Factory to get API input specs
:param type: Type of the managed object reference property
:param properties_to_collect: Properties of the managed object reference
to be collected while traversal filtering
:param all_properties: Whether all the properties of managed object
reference needs to be collected
:return: 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.
:param client_factory: Factory to get API input specs
:param root_folder: Root folder reference as the starting point for
traversal
:param traversal_specs: filter specs required for traversal
:return: 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.
:param client_factory: Factory to get API input specs
:param property_specs: Property specs to be collected for filtered objects
:param object_specs: Object specs to identify objects to be filtered
:return: 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_objects(vim, type, max_objects, props_to_collect=None,
all_properties=False):
"""Gets all managed object references of a specified type.
It is caller's responsibility to continue or cancel retrieval.
:param vim: Vim object
:param type: Type of the managed object reference
:param max_objects: Maximum number of objects that should be returned in
a single call
:param props_to_collect: Properties of the managed object reference
to be collected
:param all_properties: Whether all properties of the managed object
reference are to be collected
:return: All managed object references of a specified type
"""
if not props_to_collect:
props_to_collect = ['name']
client_factory = vim.client.factory
recur_trav_spec = build_recursive_traversal_spec(client_factory)
object_spec = build_object_spec(client_factory,
vim.service_content.rootFolder,
[recur_trav_spec])
property_spec = build_property_spec(client_factory, type=type,
properties_to_collect=props_to_collect,
all_properties=all_properties)
property_filter_spec = build_property_filter_spec(client_factory,
[property_spec],
[object_spec])
options = client_factory.create('ns0:RetrieveOptions')
options.maxObjects = max_objects
return vim.RetrievePropertiesEx(vim.service_content.propertyCollector,
specSet=[property_filter_spec],
options=options)
def get_object_properties(vim, mobj, properties):
"""Gets properties of the managed object specified.
:param vim: Vim object
:param mobj: Reference to the managed object
:param properties: Properties of the managed object reference
to be retrieved
:return: Properties of the managed object specified
"""
client_factory = vim.client.factory
if mobj is None:
return None
collector = vim.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 = mobj._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]
options = client_factory.create('ns0:RetrieveOptions')
options.maxObjects = 1
retrieve_result = vim.RetrievePropertiesEx(collector,
specSet=[property_filter_spec],
options=options)
cancel_retrieval(vim, retrieve_result)
return retrieve_result.objects
def _get_token(retrieve_result):
"""Get token from results to obtain next set of results.
:retrieve_result: Result from the RetrievePropertiesEx API
:return: Token to obtain next set of results. None if no more results.
"""
return getattr(retrieve_result, 'token', None)
def cancel_retrieval(vim, retrieve_result):
"""Cancels the retrieve operation if necessary.
:param vim: Vim object
:param retrieve_result: Result from the RetrievePropertiesEx API
"""
token = _get_token(retrieve_result)
if token:
collector = vim.service_content.propertyCollector
vim.CancelRetrievePropertiesEx(collector, token=token)
def continue_retrieval(vim, retrieve_result):
"""Continue retrieving results, if present.
:param vim: Vim object
:param retrieve_result: Result from the RetrievePropertiesEx API
"""
token = _get_token(retrieve_result)
if token:
collector = vim.service_content.propertyCollector
return vim.ContinueRetrievePropertiesEx(collector, token=token)
def get_object_property(vim, mobj, property_name):
"""Gets property of the managed object specified.
:param vim: Vim object
:param mobj: Reference to the managed object
:param property_name: Name of the property to be retrieved
:return: Property of the managed object specified
"""
props = get_object_properties(vim, mobj, [property_name])
prop_val = None
if props:
prop = None
if hasattr(props[0], 'propSet'):
# propSet will be set only if the server provides value
# for the field
prop = props[0].propSet
if prop:
prop_val = prop[0].val
return prop_val
def convert_datastores_to_hubs(pbm_client_factory, datastores):
"""Convert Datastore morefs to PbmPlacementHub morefs.
:param pbm_client_factory: pbm client factory
:param datastores: list of datastore morefs
:returns: list of PbmPlacementHub morefs
"""
hubs = []
for ds in datastores:
hub = pbm_client_factory.create('ns0:PbmPlacementHub')
hub.hubId = ds.value
hub.hubType = 'Datastore'
hubs.append(hub)
return hubs
def convert_hubs_to_datastores(hubs, datastores):
"""Get filtered subset of datastores as represented by hubs.
:param hubs: represents a sub set of datastore ids
:param datastores: represents all candidate datastores
:returns: that subset of datastores objects that are also present in hubs
"""
hubIds = [hub.hubId for hub in hubs]
filtered_dss = [ds for ds in datastores if ds.value in hubIds]
return filtered_dss

View File

@ -31,18 +31,19 @@ from oslo_config import cfg
from oslo_utils import excutils
from oslo_utils import units
from oslo_utils import uuidutils
from oslo_vmware import api
from oslo_vmware import exceptions
from oslo_vmware import image_transfer
from oslo_vmware import pbm
from oslo_vmware import vim_util
import six
from cinder import exception
from cinder.i18n import _, _LE, _LI, _LW
from cinder.openstack.common import fileutils
from cinder.openstack.common import log as logging
from cinder.volume import driver
from cinder.volume.drivers.vmware import api
from cinder.volume.drivers.vmware import datastore as hub
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import vim
from cinder.volume.drivers.vmware import vim_util
from cinder.volume.drivers.vmware import vmware_images
from cinder.volume.drivers.vmware import volumeops
from cinder.volume import volume_types
@ -304,11 +305,11 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
try:
# find if any host can accommodate the volume
self._select_ds_for_volume(volume)
except error_util.VimException as excep:
except exceptions.VimException as excep:
msg = _("Not able to find a suitable datastore for the volume: "
"%s.") % volume['name']
LOG.exception(msg)
raise error_util.VimFaultException([excep], msg)
raise exceptions.VimFaultException([excep], msg)
LOG.debug("Verified volume %s can be created.", volume['name'])
def create_volume(self, volume):
@ -401,7 +402,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
"from the datastores: %(dss)s.") % {'size': size_bytes,
'dss': datastores}
LOG.error(msg)
raise error_util.VimException(msg)
raise exceptions.VimException(msg)
LOG.debug("Selected datastore: %(datastore)s with %(host_count)d "
"connected host(s) for the volume." %
@ -435,15 +436,16 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
LOG.debug("Filter datastores matching storage profile %(profile)s: "
"%(dss)s.",
{'profile': storage_profile, 'dss': datastores})
profileId = self.volumeops.retrieve_profile_id(storage_profile)
profileId = pbm.get_profile_id_by_name(self.session, storage_profile)
if not profileId:
msg = _("No such storage profile '%s; is defined in vCenter.")
LOG.error(msg, storage_profile)
raise error_util.VimException(msg % storage_profile)
raise exceptions.VimException(msg % storage_profile)
pbm_cf = self.session.pbm.client.factory
hubs = vim_util.convert_datastores_to_hubs(pbm_cf, datastores)
filtered_hubs = self.volumeops.filter_matching_hubs(hubs, profileId)
return vim_util.convert_hubs_to_datastores(filtered_hubs, datastores)
hubs = pbm.convert_datastores_to_hubs(pbm_cf, datastores)
filtered_hubs = pbm.filter_hubs_by_profile(self.session, hubs,
profileId)
return pbm.filter_datastores_by_hubs(filtered_hubs, datastores)
def _get_folder_ds_summary(self, volume, resource_pool, datastores):
"""Get folder and best datastore summary where volume can be placed.
@ -467,7 +469,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
msg = _("Aborting since none of the datastores match the "
"given storage profile %s.")
LOG.error(msg, storage_profile)
raise error_util.VimException(msg % storage_profile)
raise exceptions.VimException(msg % storage_profile)
elif storage_profile:
LOG.warn(_LW("Ignoring storage profile %s requirement for this "
"volume since policy based placement is "
@ -504,7 +506,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
storage_profile = self._get_storage_profile(volume)
profile_id = None
if self._storage_policy_enabled and storage_profile:
profile = self.volumeops.retrieve_profile_id(storage_profile)
profile = pbm.get_profile_id_by_name(self.session, storage_profile)
if profile:
profile_id = profile.uniqueId
return profile_id
@ -584,7 +586,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
rp, dss)
selected_host = host
break
except error_util.VimException as excep:
except exceptions.VimException as excep:
LOG.warn(_LW("Unable to find suitable datastore for volume"
" of size: %(vol)s GB under host: %(host)s. "
"More details: %(excep)s") %
@ -598,7 +600,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
msg = _("Unable to find host to accommodate a disk of size: %s "
"in the inventory.") % volume['size']
LOG.error(msg)
raise error_util.VimException(msg)
raise exceptions.VimException(msg)
def _create_backing_in_inventory(self, volume, create_params=None):
"""Creates backing under any suitable host.
@ -625,7 +627,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
create_params)
if backing:
break
except error_util.VimException as excep:
except exceptions.VimException as excep:
LOG.warn(_LW("Unable to find suitable datastore for "
"volume: %(vol)s under host: %(host)s. "
"More details: %(excep)s") %
@ -638,7 +640,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
msg = _("Unable to create volume: %s in the inventory.")
LOG.error(msg % volume['name'])
raise error_util.VimException(msg % volume['name'])
raise exceptions.VimException(msg % volume['name'])
def _initialize_connection(self, volume, connector):
"""Get information of volume's backing.
@ -654,7 +656,8 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
backing = self.volumeops.get_backing(volume['name'])
if 'instance' in connector:
# The instance exists
instance = vim.get_moref(connector['instance'], 'VirtualMachine')
instance = vim_util.get_moref(connector['instance'],
'VirtualMachine')
LOG.debug("The instance: %s for which initialize connection "
"is called, exists." % instance)
# Get host managing the instance
@ -922,16 +925,18 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
LOG.debug("Copying image: %(image_id)s to %(path)s.",
{'image_id': image_id,
'path': upload_file_path})
vmware_images.fetch_flat_image(context,
timeout,
image_service,
image_id,
image_size=image_size_in_bytes,
host=host_ip,
data_center_name=dc_name,
datastore_name=ds_name,
cookies=cookies,
file_path=upload_file_path)
# TODO(vbala): add config option to override non-default port
image_transfer.download_flat_image(context,
timeout,
image_service,
image_id,
image_size=image_size_in_bytes,
host=host_ip,
port=443,
data_center_name=dc_name,
datastore_name=ds_name,
cookies=cookies,
file_path=upload_file_path)
LOG.debug("Image: %(image_id)s copied to %(path)s.",
{'image_id': image_id,
'path': upload_file_path})
@ -943,7 +948,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
try:
self.volumeops.delete_vmdk_file(
descriptor_ds_file_path, dc_ref)
except error_util.VimException:
except exceptions.VimException:
LOG.warn(_LW("Error occurred while deleting temporary "
"disk: %s."),
descriptor_ds_file_path,
@ -956,7 +961,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
self.volumeops.copy_vmdk_file(
dc_ref, src_path.get_descriptor_ds_file_path(),
dest_path.get_descriptor_ds_file_path())
except error_util.VimException:
except exceptions.VimException:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Error occurred while copying %(src)s to "
"%(dst)s."),
@ -1029,7 +1034,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
try:
self.volumeops.delete_file(
path.get_descriptor_ds_file_path(), dc_ref)
except error_util.VimException:
except exceptions.VimException:
LOG.warn(_LW("Error occurred while deleting "
"descriptor: %s."),
path.get_descriptor_ds_file_path(),
@ -1058,7 +1063,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
LOG.debug("Deleting backing: %s.", backing)
try:
self.volumeops.delete_backing(backing)
except error_util.VimException:
except exceptions.VimException:
LOG.warn(_LW("Error occurred while deleting backing: %s."),
backing,
exc_info=True)
@ -1168,7 +1173,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
try:
# find host in which to create the volume
(_host, rp, folder, summary) = self._select_ds_for_volume(volume)
except error_util.VimException as excep:
except exceptions.VimException as excep:
err_msg = (_("Exception in _select_ds_for_volume: "
"%s."), excep)
raise exception.VolumeBackendAPIException(data=err_msg)
@ -1201,17 +1206,20 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
host_ip = self.configuration.vmware_host_ip
LOG.debug("Fetching glance image: %(id)s to server: %(host)s." %
{'id': image_id, 'host': host_ip})
vmware_images.fetch_stream_optimized_image(context, timeout,
image_service,
image_id,
session=self.session,
host=host_ip,
resource_pool=rp,
vm_folder=folder,
vm_create_spec=
vm_import_spec,
image_size=image_size)
except exception.CinderException as excep:
image_transfer.download_stream_optimized_image(
context,
timeout,
image_service,
image_id,
session=self.session,
host=host_ip,
port=443,
resource_pool=rp,
vm_folder=folder,
vm_import_spec=vm_import_spec,
image_size=image_size)
except (exceptions.VimException,
exceptions.VMwareDriverException) as excep:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Exception in copy_image_to_volume: %s."),
excep)
@ -1252,7 +1260,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
try:
self.volumeops.extend_virtual_disk(new_size_in_gb,
root_vmdk_path, datacenter)
except error_util.VimException:
except exceptions.VimException:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Unable to extend the size of the "
"vmdk virtual disk at the path %s."),
@ -1302,7 +1310,8 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
self._create_volume_from_non_stream_optimized_image(
context, volume, image_service, image_id,
image_size_in_bytes, image_adapter_type, image_disk_type)
except exception.CinderException as excep:
except (exceptions.VimException,
exceptions.VMwareDriverException) as excep:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Exception in copying the image to the "
"volume: %s."), excep)
@ -1361,16 +1370,20 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
timeout = self.configuration.vmware_image_transfer_timeout_secs
host_ip = self.configuration.vmware_host_ip
vmware_images.upload_image(context, timeout, image_service,
image_meta['id'],
volume['project_id'],
session=self.session,
host=host_ip,
vm=backing,
vmdk_file_path=vmdk_file_path,
vmdk_size=volume['size'] * units.Gi,
image_name=image_meta['name'],
image_version=1)
image_transfer.upload_image(context,
timeout,
image_service,
image_meta['id'],
volume['project_id'],
session=self.session,
host=host_ip,
port=443,
vm=backing,
vmdk_file_path=vmdk_file_path,
vmdk_size=volume['size'] * units.Gi,
image_name=image_meta['name'],
image_version=1,
is_public=True)
LOG.info(_LI("Done copying volume %(vol)s to a new image %(img)s") %
{'vol': volume['name'], 'img': image_meta['name']})
@ -1504,7 +1517,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
host)
self._delete_temp_backing(backing)
backing = new_backing
except error_util.VimException:
except exceptions.VimException:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Error occurred while cloning "
"backing:"
@ -1520,7 +1533,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
try:
self.volumeops.rename_backing(backing,
volume['name'])
except error_util.VimException:
except exceptions.VimException:
LOG.warn(_LW("Changing backing: %(backing)s "
"name from %(new_name)s to "
"%(old_name)s failed."),
@ -1561,14 +1574,14 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
"to size %(size)s GB.") %
{'vol': vol_name, 'size': new_size})
return
except error_util.VimFaultException:
except exceptions.VimFaultException:
LOG.info(_LI("Relocating volume %s vmdk to a different "
"datastore since trying to extend vmdk file "
"in place failed."), vol_name)
# If in place extend fails, then try to relocate the volume
try:
(host, rp, folder, summary) = self._select_ds_for_volume(new_size)
except error_util.VimException:
except exceptions.VimException:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Not able to find a different datastore to "
"place the extended volume %s."), vol_name)
@ -1583,7 +1596,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
host)
self._extend_vmdk_virtual_disk(vol_name, new_size)
self.volumeops.move_backing_to_folder(backing, folder)
except error_util.VimException:
except exceptions.VimException:
with excutils.save_and_reraise_exception():
LOG.exception(_LE("Not able to relocate volume %s for "
"extending."), vol_name)
@ -1610,9 +1623,15 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
vmdk_ds_file_path = self.volumeops.get_vmdk_path(backing)
with fileutils.file_open(tmp_file_path, "wb") as tmp_file:
vmware_images.download_stream_optimized_disk(
context, timeout, tmp_file, session=self.session,
host=host_ip, vm=backing, vmdk_file_path=vmdk_ds_file_path,
image_transfer.copy_stream_optimized_disk(
context,
timeout,
tmp_file,
session=self.session,
host=host_ip,
port=443,
vm=backing,
vmdk_file_path=vmdk_ds_file_path,
vmdk_size=volume['size'] * units.Gi)
def backup_volume(self, context, backup, backup_service):
@ -1675,10 +1694,17 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
host_ip = self.configuration.vmware_host_ip
try:
with fileutils.file_open(tmp_file_path, "rb") as tmp_file:
vm_ref = vmware_images.upload_stream_optimized_disk(
context, timeout, tmp_file, session=self.session,
host=host_ip, resource_pool=rp, vm_folder=folder,
vm_create_spec=vm_import_spec, vmdk_size=file_size_bytes)
vm_ref = image_transfer.download_stream_optimized_data(
context,
timeout,
tmp_file,
session=self.session,
host=host_ip,
port=443,
resource_pool=rp,
vm_folder=folder,
vm_import_spec=vm_import_spec,
image_size=file_size_bytes)
LOG.debug("Created backing: %(name)s from virtual disk: "
"%(path)s.",
{'name': name,
@ -1740,7 +1766,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
LOG.debug("Deleted old backing and renamed clone for restoring "
"backup.")
except (error_util.VimException, error_util.VMwareDriverException):
except (exceptions.VimException, exceptions.VMwareDriverException):
with excutils.save_and_reraise_exception():
if dest is not None:
# Copy happened; we need to delete the clone.
@ -1750,7 +1776,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver):
try:
self.volumeops.rename_backing(backing,
volume['name'])
except error_util.VimException:
except exceptions.VimException:
LOG.warn(_LW("Cannot undo volume rename; old name "
"was %(old_name)s and new name is "
"%(new_name)s."),
@ -1840,27 +1866,9 @@ class VMwareVcVmdkDriver(VMwareEsxVmdkDriver):
password, api_retry_count,
task_poll_interval,
wsdl_loc=wsdl_loc,
pbm_wsdl=pbm_wsdl)
pbm_wsdl_loc=pbm_wsdl)
return self._session
def _get_pbm_wsdl_location(self, vc_version):
"""Return PBM WSDL file location corresponding to VC version."""
if not vc_version:
return
ver = str(vc_version).split('.')
major_minor = ver[0]
if len(ver) >= 2:
major_minor = major_minor + '.' + ver[1]
curr_dir = os.path.abspath(os.path.dirname(__file__))
pbm_service_wsdl = os.path.join(curr_dir, 'wsdl', major_minor,
'pbmService.wsdl')
if not os.path.exists(pbm_service_wsdl):
LOG.warn(_LW("PBM WSDL file %s is missing!"), pbm_service_wsdl)
return
pbm_wsdl = 'file://' + pbm_service_wsdl
LOG.info(_LI("Using PBM WSDL location: %s"), pbm_wsdl)
return pbm_wsdl
def _get_vc_version(self):
"""Connect to VC server and fetch version.
@ -1872,9 +1880,9 @@ class VMwareVcVmdkDriver(VMwareEsxVmdkDriver):
LOG.info(_LI("Using overridden vmware_host_version from config: "
"%s"), version_str)
else:
version_str = self.session.vim.service_content.about.version
version_str = vim_util.get_vc_version(self.session)
LOG.info(_LI("Fetched VC server version: %s"), version_str)
# convert version_str to LooseVersion and return
# Convert version_str to LooseVersion and return.
version = None
try:
version = dist_version.LooseVersion(version_str)
@ -1892,11 +1900,12 @@ class VMwareVcVmdkDriver(VMwareEsxVmdkDriver):
# Enable pbm only if VC version is greater than 5.5
vc_version = self._get_vc_version()
if vc_version and vc_version >= self.PBM_ENABLED_VC_VERSION:
self.pbm_wsdl = self._get_pbm_wsdl_location(vc_version)
self.pbm_wsdl = pbm.get_pbm_wsdl_location(
six.text_type(vc_version))
if not self.pbm_wsdl:
LOG.error(_LE("Not able to configure PBM for VC server: %s"),
vc_version)
raise error_util.VMwareDriverException()
raise exceptions.VMwareDriverException()
self._storage_policy_enabled = True
# Destroy current session so that it is recreated with pbm enabled
self._session = None

View File

@ -1,199 +0,0 @@
# Copyright (c) 2013 VMware, Inc.
# All Rights Reserved.
#
# 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 eventlet import timeout
from cinder.i18n import _LE, _LI
from cinder.openstack.common import log as logging
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import io_util
from cinder.volume.drivers.vmware import read_write_util as rw_util
LOG = logging.getLogger(__name__)
QUEUE_BUFFER_SIZE = 10
def start_transfer(context, timeout_secs, read_file_handle, max_data_size,
write_file_handle=None, image_service=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, max_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 glance changing to active.
# The GlanceWriteThread handles the same for us.
elif image_service and image_id:
write_thread = io_util.GlanceWriteThread(context, thread_safe_pipe,
image_service, image_id,
image_meta)
# Start the read and write threads.
read_event = read_thread.start()
write_event = write_thread.start()
timer = timeout.Timeout(timeout_secs)
try:
# Wait on the read and write events to signal their end
read_event.wait()
write_event.wait()
except (timeout.Timeout, Exception) as 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(_LE("Error occurred during image transfer."))
if isinstance(exc, error_util.ImageTransferException):
raise
raise error_util.ImageTransferException(exc)
finally:
timer.cancel()
# 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_flat_image(context, timeout_secs, image_service, image_id, **kwargs):
"""Download flat image from the glance image server."""
LOG.debug("Downloading image: %s from glance image server as a flat vmdk"
" file." % image_id)
file_size = int(kwargs.get('image_size'))
read_iter = image_service.download(context, image_id)
read_handle = rw_util.GlanceFileRead(read_iter)
write_handle = rw_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(context, timeout_secs, read_handle, file_size,
write_file_handle=write_handle)
LOG.info(_LI("Downloaded image: %s from glance "
"image server.") % image_id)
def fetch_stream_optimized_image(context, timeout_secs, image_service,
image_id, **kwargs):
"""Download stream optimized image from glance image server."""
LOG.debug("Downloading image: %s from glance image server using HttpNfc"
" import." % image_id)
file_size = int(kwargs.get('image_size'))
read_iter = image_service.download(context, image_id)
read_handle = rw_util.GlanceFileRead(read_iter)
write_handle = rw_util.VMwareHTTPWriteVmdk(kwargs.get('session'),
kwargs.get('host'),
kwargs.get('resource_pool'),
kwargs.get('vm_folder'),
kwargs.get('vm_create_spec'),
file_size)
start_transfer(context, timeout_secs, read_handle, file_size,
write_file_handle=write_handle)
LOG.info(_LI("Downloaded image: %s from glance image "
"server.") % image_id)
def upload_image(context, timeout_secs, image_service, image_id, owner_id,
**kwargs):
"""Upload the vm's disk file to Glance image server."""
LOG.debug("Uploading image: %s to the Glance image server using HttpNfc"
" export." % image_id)
file_size = kwargs.get('vmdk_size')
read_handle = rw_util.VMwareHTTPReadVmdk(kwargs.get('session'),
kwargs.get('host'),
kwargs.get('vm'),
kwargs.get('vmdk_file_path'),
file_size)
# The properties and other fields that we need to set for the image.
# Important to set the 'size' to 0 here. Otherwise the glance client
# uses the volume size which may not be image size after upload since
# it is converted to a stream-optimized sparse disk
image_metadata = {'disk_format': 'vmdk',
'is_public': 'false',
'name': kwargs.get('image_name'),
'status': 'active',
'container_format': 'bare',
'size': 0,
'properties': {'vmware_image_version':
kwargs.get('image_version'),
'vmware_disktype': 'streamOptimized',
'owner_id': owner_id}}
start_transfer(context, timeout_secs, read_handle, file_size,
image_service=image_service, image_id=image_id,
image_meta=image_metadata)
LOG.info(_LI("Uploaded image: %s to the Glance image server.") % image_id)
def download_stream_optimized_disk(
context, timeout_secs, write_handle, **kwargs):
"""Download virtual disk in streamOptimized format from VMware server."""
vmdk_file_path = kwargs.get('vmdk_file_path')
LOG.debug("Downloading virtual disk: %(vmdk_path)s to %(dest)s.",
{'vmdk_path': vmdk_file_path,
'dest': write_handle.name})
file_size = kwargs.get('vmdk_size')
read_handle = rw_util.VMwareHTTPReadVmdk(kwargs.get('session'),
kwargs.get('host'),
kwargs.get('vm'),
vmdk_file_path,
file_size)
start_transfer(context, timeout_secs, read_handle, file_size, write_handle)
LOG.debug("Downloaded virtual disk: %s.", vmdk_file_path)
def upload_stream_optimized_disk(context, timeout_secs, read_handle, **kwargs):
"""Upload virtual disk in streamOptimized format to VMware server."""
LOG.debug("Uploading virtual disk file: %(path)s to create backing with "
"spec: %(spec)s.",
{'path': read_handle.name,
'spec': kwargs.get('vm_create_spec')})
file_size = kwargs.get('vmdk_size')
write_handle = rw_util.VMwareHTTPWriteVmdk(kwargs.get('session'),
kwargs.get('host'),
kwargs.get('resource_pool'),
kwargs.get('vm_folder'),
kwargs.get('vm_create_spec'),
file_size)
start_transfer(context, timeout_secs, read_handle, file_size,
write_file_handle=write_handle)
LOG.debug("Uploaded virtual disk file: %s.", read_handle.name)
return write_handle.get_imported_vm()

View File

@ -20,11 +20,13 @@ Implements operations on volumes residing on VMware datastores.
import urllib
from oslo_utils import units
from oslo_vmware import exceptions
from oslo_vmware import vim_util
from cinder.i18n import _, _LE, _LI
from cinder.openstack.common import log as logging
from cinder.volume.drivers.vmware import error_util
from cinder.volume.drivers.vmware import vim_util
from cinder.volume.drivers.vmware import exceptions as vmdk_exceptions
LOG = logging.getLogger(__name__)
LINKED_CLONE_TYPE = 'linked'
@ -159,7 +161,7 @@ class VirtualDiskType(object):
:raises: InvalidDiskTypeException
"""
if not VirtualDiskType.is_valid(extra_spec_disk_type):
raise error_util.InvalidDiskTypeException(
raise vmdk_exceptions.InvalidDiskTypeException(
disk_type=extra_spec_disk_type)
@staticmethod
@ -206,7 +208,7 @@ class VirtualDiskAdapterType(object):
:raises: InvalidAdapterTypeException
"""
if not VirtualDiskAdapterType.is_valid(extra_spec_adapter_type):
raise error_util.InvalidAdapterTypeException(
raise vmdk_exceptions.InvalidAdapterTypeException(
invalid_type=extra_spec_adapter_type)
@staticmethod
@ -250,7 +252,8 @@ class ControllerType(object):
"""
if adapter_type in ControllerType.CONTROLLER_TYPE_DICT:
return ControllerType.CONTROLLER_TYPE_DICT[adapter_type]
raise error_util.InvalidAdapterTypeException(invalid_type=adapter_type)
raise vmdk_exceptions.InvalidAdapterTypeException(
invalid_type=adapter_type)
@staticmethod
def is_scsi_controller(controller_type):
@ -462,7 +465,7 @@ class VMwareVolumeOps(object):
if not valid_dss:
msg = _("There are no valid datastores attached to %s.") % host
LOG.error(msg)
raise error_util.VimException(msg)
raise exceptions.VimException(msg)
else:
LOG.debug("Valid datastores are: %s", valid_dss)
return (valid_dss, resource_pool)
@ -1205,7 +1208,7 @@ class VMwareVolumeOps(object):
LOG.error(_LE("Virtual disk device of "
"backing: %s not found."), backing)
raise error_util.VirtualDiskNotFoundException()
raise vmdk_exceptions.VirtualDiskNotFoundException()
def get_vmdk_path(self, backing):
"""Get the vmdk file name of the backing.
@ -1337,57 +1340,3 @@ class VMwareVolumeOps(object):
LOG.debug("Initiated deleting vmdk file via task: %s." % task)
self._session.wait_for_task(task)
LOG.info(_LI("Deleted vmdk file: %s.") % vmdk_file_path)
def get_all_profiles(self):
"""Get all profiles defined in current VC.
:return: PbmProfile data objects from VC
"""
LOG.debug("Get all profiles defined in current VC.")
pbm = self._session.pbm
profile_manager = pbm.service_content.profileManager
res_type = pbm.client.factory.create('ns0:PbmProfileResourceType')
res_type.resourceType = 'STORAGE'
profiles = []
profileIds = self._session.invoke_api(pbm, 'PbmQueryProfile',
profile_manager,
resourceType=res_type)
LOG.debug("Got profile IDs: %s", profileIds)
if profileIds:
profiles = self._session.invoke_api(pbm, 'PbmRetrieveContent',
profile_manager,
profileIds=profileIds)
return profiles
def retrieve_profile_id(self, profile_name):
"""Get the profile uuid from current VC for given profile name.
:param profile_name: profile name as string
:return: profile id as string
"""
LOG.debug("Trying to retrieve profile id for %s", profile_name)
for profile in self.get_all_profiles():
if profile.name == profile_name:
profileId = profile.profileId
LOG.debug("Got profile id %(id)s for profile %(name)s.",
{'id': profileId, 'name': profile_name})
return profileId
def filter_matching_hubs(self, hubs, profile_id):
"""Filter and return only hubs that match given profile.
:param hubs: PbmPlacementHub morefs candidates
:param profile_id: profile id string
:return: subset of hubs that match given profile_id
"""
LOG.debug("Filtering hubs %(hubs)s that match profile "
"%(profile)s.", {'hubs': hubs, 'profile': profile_id})
pbm = self._session.pbm
placement_solver = pbm.service_content.placementSolver
filtered_hubs = self._session.invoke_api(pbm, 'PbmQueryMatchingHub',
placement_solver,
hubsToSearch=hubs,
profile=profile_id)
LOG.debug("Filtered hubs: %s", filtered_hubs)
return filtered_hubs

View File

@ -1,242 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright 2005-2013 VMware, Inc. All rights reserved.
-->
<schema
targetNamespace="urn:vim25"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:vim25="urn:vim25"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
>
<complexType name="DynamicArray">
<sequence>
<element name="dynamicType" type="xsd:string" minOccurs="0" />
<element name="val" type="xsd:anyType" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="DynamicData">
<sequence>
<element name="dynamicType" type="xsd:string" minOccurs="0" />
<element name="dynamicProperty" type="vim25:DynamicProperty" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="DynamicProperty">
<sequence>
<element name="name" type="xsd:string" />
<element name="val" type="xsd:anyType" />
</sequence>
</complexType>
<complexType name="ArrayOfDynamicProperty">
<sequence>
<element name="DynamicProperty" type="vim25:DynamicProperty" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="KeyAnyValue">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="key" type="xsd:string" />
<element name="value" type="xsd:anyType" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfKeyAnyValue">
<sequence>
<element name="KeyAnyValue" type="vim25:KeyAnyValue" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="LocalizableMessage">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="key" type="xsd:string" />
<element name="arg" type="vim25:KeyAnyValue" minOccurs="0" maxOccurs="unbounded" />
<element name="message" type="xsd:string" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfLocalizableMessage">
<sequence>
<element name="LocalizableMessage" type="vim25:LocalizableMessage" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="HostCommunication">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="HostNotConnected">
<complexContent>
<extension base="vim25:HostCommunication">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="HostNotReachable">
<complexContent>
<extension base="vim25:HostCommunication">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="InvalidArgument">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
<element name="invalidProperty" type="xsd:string" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="InvalidRequest">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="InvalidType">
<complexContent>
<extension base="vim25:InvalidRequest">
<sequence>
<element name="argument" type="xsd:string" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ManagedObjectNotFound">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
<element name="obj" type="vim25:ManagedObjectReference" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="MethodNotFound">
<complexContent>
<extension base="vim25:InvalidRequest">
<sequence>
<element name="receiver" type="vim25:ManagedObjectReference" />
<element name="method" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="NotEnoughLicenses">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="NotImplemented">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="NotSupported">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="RequestCanceled">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="SecurityError">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="SystemError">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
<element name="reason" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="UnexpectedFault">
<complexContent>
<extension base="vim25:RuntimeFault">
<sequence>
<element name="faultName" type="xsd:string" />
<element name="fault" type="vim25:LocalizedMethodFault" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="LocalizedMethodFault">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="fault" type="vim25:MethodFault" />
<element name="localizedMessage" type="xsd:string" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="MethodFault">
<sequence>
<element name="dynamicType" type="xsd:string" minOccurs="0" />
<element name="dynamicProperty" type="vim25:DynamicProperty" minOccurs="0" maxOccurs="unbounded" />
<element name="faultCause" type="vim25:LocalizedMethodFault" minOccurs="0" />
<element name="faultMessage" type="vim25:LocalizableMessage" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="ArrayOfMethodFault">
<sequence>
<element name="MethodFault" type="vim25:MethodFault" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="RuntimeFault">
<complexContent>
<extension base="vim25:MethodFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ManagedObjectReference">
<simpleContent>
<extension base="xsd:string">
<attribute name="type" type="xsd:string"/>
</extension>
</simpleContent>
</complexType>
<complexType name="ArrayOfString">
<sequence>
<element name="string" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="ArrayOfAnyType">
<sequence>
<element name="anyType" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</schema>

View File

@ -1,155 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright 2005-2013 VMware, Inc. All rights reserved.
-->
<schema
targetNamespace="urn:pbm"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:pbm="urn:pbm"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:vim25="urn:vim25"
elementFormDefault="qualified"
>
<import namespace="urn:vim25" schemaLocation="core-types.xsd" />
<include schemaLocation="pbm-types.xsd" />
<complexType name="PbmRetrieveServiceContentRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
</sequence>
</complexType>
<complexType name="PbmCheckComplianceRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="entities" type="pbm:PbmServerObjectRef" maxOccurs="unbounded" />
<element name="profile" type="pbm:PbmProfileId" minOccurs="0" />
</sequence>
</complexType>
<complexType name="PbmFetchComplianceResultRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="entities" type="pbm:PbmServerObjectRef" maxOccurs="unbounded" />
<element name="profile" type="pbm:PbmProfileId" minOccurs="0" />
</sequence>
</complexType>
<complexType name="PbmCheckRollupComplianceRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="entity" type="pbm:PbmServerObjectRef" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmFetchRollupComplianceResultRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="entity" type="pbm:PbmServerObjectRef" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmQueryMatchingHubRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="hubsToSearch" type="pbm:PbmPlacementHub" minOccurs="0" maxOccurs="unbounded" />
<element name="profile" type="pbm:PbmProfileId" />
</sequence>
</complexType>
<complexType name="PbmQueryMatchingHubWithSpecRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="hubsToSearch" type="pbm:PbmPlacementHub" minOccurs="0" maxOccurs="unbounded" />
<element name="createSpec" type="pbm:PbmCapabilityProfileCreateSpec" />
</sequence>
</complexType>
<complexType name="PbmCheckCompatibilityRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="hubsToSearch" type="pbm:PbmPlacementHub" minOccurs="0" maxOccurs="unbounded" />
<element name="profile" type="pbm:PbmProfileId" />
</sequence>
</complexType>
<complexType name="PbmCheckCompatibilityWithSpecRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="hubsToSearch" type="pbm:PbmPlacementHub" minOccurs="0" maxOccurs="unbounded" />
<element name="profileSpec" type="pbm:PbmCapabilityProfileCreateSpec" />
</sequence>
</complexType>
<complexType name="PbmFetchResourceTypeRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
</sequence>
</complexType>
<complexType name="PbmFetchVendorInfoRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="resourceType" type="pbm:PbmProfileResourceType" minOccurs="0" />
</sequence>
</complexType>
<complexType name="PbmFetchCapabilityMetadataRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="resourceType" type="pbm:PbmProfileResourceType" minOccurs="0" />
<element name="vendorUuid" type="xsd:string" minOccurs="0" />
</sequence>
</complexType>
<complexType name="PbmCreateRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="createSpec" type="pbm:PbmCapabilityProfileCreateSpec" />
</sequence>
</complexType>
<complexType name="PbmUpdateRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="profileId" type="pbm:PbmProfileId" />
<element name="updateSpec" type="pbm:PbmCapabilityProfileUpdateSpec" />
</sequence>
</complexType>
<complexType name="PbmDeleteRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="profileId" type="pbm:PbmProfileId" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmQueryProfileRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="resourceType" type="pbm:PbmProfileResourceType" />
<element name="profileCategory" type="xsd:string" minOccurs="0" />
</sequence>
</complexType>
<complexType name="PbmRetrieveContentRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="profileIds" type="pbm:PbmProfileId" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmQueryAssociatedProfilesRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="entities" type="pbm:PbmServerObjectRef" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmQueryAssociatedProfileRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="entity" type="pbm:PbmServerObjectRef" />
</sequence>
</complexType>
<complexType name="PbmQueryAssociatedEntityRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="profile" type="pbm:PbmProfileId" />
<element name="entityType" type="xsd:string" minOccurs="0" />
</sequence>
</complexType>
<complexType name="PbmQueryDefaultRequirementProfileRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="hub" type="pbm:PbmPlacementHub" />
</sequence>
</complexType>
<complexType name="PbmResetDefaultRequirementProfileRequestType">
<sequence>
<element name="_this" type="vim25:ManagedObjectReference" />
<element name="profile" type="pbm:PbmProfileId" minOccurs="0" />
</sequence>
</complexType>
</schema>

View File

@ -1,729 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright 2005-2013 VMware, Inc. All rights reserved.
-->
<schema
targetNamespace="urn:pbm"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:pbm="urn:pbm"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:vim25="urn:vim25"
elementFormDefault="qualified"
>
<import namespace="urn:vim25" schemaLocation="core-types.xsd" />
<complexType name="PbmAboutInfo">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="name" type="xsd:string" />
<element name="version" type="xsd:string" />
<element name="instanceUuid" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmExtendedElementDescription">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="label" type="xsd:string" />
<element name="summary" type="xsd:string" />
<element name="key" type="xsd:string" />
<element name="messageCatalogKeyPrefix" type="xsd:string" />
<element name="messageArg" type="vim25:KeyAnyValue" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</extension>
</complexContent>
</complexType>
<simpleType name="PbmVvolType">
<restriction base="xsd:string">
<enumeration value="Config" />
<enumeration value="Data" />
<enumeration value="Swap" />
</restriction>
</simpleType>
<simpleType name="PbmObjectType">
<restriction base="xsd:string">
<enumeration value="virtualMachine" />
<enumeration value="virtualDiskId" />
<enumeration value="virtualDiskUUID" />
<enumeration value="datastore" />
<enumeration value="unknown" />
</restriction>
</simpleType>
<complexType name="PbmServerObjectRef">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="objectType" type="xsd:string" />
<element name="key" type="xsd:string" />
<element name="serverUuid" type="xsd:string" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmServerObjectRef">
<sequence>
<element name="PbmServerObjectRef" type="pbm:PbmServerObjectRef" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmServiceInstanceContent">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="aboutInfo" type="pbm:PbmAboutInfo" />
<element name="sessionManager" type="vim25:ManagedObjectReference" />
<element name="capabilityMetadataManager" type="vim25:ManagedObjectReference" />
<element name="profileManager" type="vim25:ManagedObjectReference" />
<element name="complianceManager" type="vim25:ManagedObjectReference" />
<element name="placementSolver" type="vim25:ManagedObjectReference" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityInstance">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="id" type="pbm:PbmCapabilityMetadataUniqueId" />
<element name="constraint" type="pbm:PbmCapabilityConstraintInstance" maxOccurs="unbounded" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCapabilityInstance">
<sequence>
<element name="PbmCapabilityInstance" type="pbm:PbmCapabilityInstance" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmCapabilityMetadataUniqueId">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="namespace" type="xsd:string" />
<element name="id" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityMetadata">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="id" type="pbm:PbmCapabilityMetadataUniqueId" />
<element name="summary" type="pbm:PbmExtendedElementDescription" />
<element name="mandatory" type="xsd:boolean" minOccurs="0" />
<element name="hint" type="xsd:boolean" minOccurs="0" />
<element name="keyId" type="xsd:string" minOccurs="0" />
<element name="allowMultipleConstraints" type="xsd:boolean" minOccurs="0" />
<element name="propertyMetadata" type="pbm:PbmCapabilityPropertyMetadata" maxOccurs="unbounded" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCapabilityMetadata">
<sequence>
<element name="PbmCapabilityMetadata" type="pbm:PbmCapabilityMetadata" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmCapabilityConstraintInstance">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="propertyInstance" type="pbm:PbmCapabilityPropertyInstance" maxOccurs="unbounded" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCapabilityConstraintInstance">
<sequence>
<element name="PbmCapabilityConstraintInstance" type="pbm:PbmCapabilityConstraintInstance" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmCapabilityGenericTypeInfo">
<complexContent>
<extension base="pbm:PbmCapabilityTypeInfo">
<sequence>
<element name="genericTypeName" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityPropertyInstance">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="id" type="xsd:string" />
<element name="value" type="xsd:anyType" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCapabilityPropertyInstance">
<sequence>
<element name="PbmCapabilityPropertyInstance" type="pbm:PbmCapabilityPropertyInstance" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmCapabilityPropertyMetadata">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="id" type="xsd:string" />
<element name="summary" type="pbm:PbmExtendedElementDescription" />
<element name="mandatory" type="xsd:boolean" />
<element name="type" type="pbm:PbmCapabilityTypeInfo" minOccurs="0" />
<element name="defaultValue" type="xsd:anyType" minOccurs="0" />
<element name="allowedValue" type="xsd:anyType" minOccurs="0" />
<element name="requirementsTypeHint" type="xsd:string" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCapabilityPropertyMetadata">
<sequence>
<element name="PbmCapabilityPropertyMetadata" type="pbm:PbmCapabilityPropertyMetadata" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmCapabilityTypeInfo">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="typeName" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityMetadataPerCategory">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="subCategory" type="xsd:string" />
<element name="capabilityMetadata" type="pbm:PbmCapabilityMetadata" maxOccurs="unbounded" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCapabilityMetadataPerCategory">
<sequence>
<element name="PbmCapabilityMetadataPerCategory" type="pbm:PbmCapabilityMetadataPerCategory" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmCapabilitySchemaVendorInfo">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="vendorUuid" type="xsd:string" />
<element name="info" type="pbm:PbmExtendedElementDescription" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityNamespaceInfo">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="version" type="xsd:string" />
<element name="namespace" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityVendorResourceTypeInfo">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="resourceType" type="xsd:string" />
<element name="vendorNamespaceInfo" type="pbm:PbmCapabilityVendorNamespaceInfo" maxOccurs="unbounded" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCapabilityVendorResourceTypeInfo">
<sequence>
<element name="PbmCapabilityVendorResourceTypeInfo" type="pbm:PbmCapabilityVendorResourceTypeInfo" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmCapabilityVendorNamespaceInfo">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="vendorInfo" type="pbm:PbmCapabilitySchemaVendorInfo" />
<element name="namespaceInfo" type="pbm:PbmCapabilityNamespaceInfo" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCapabilityVendorNamespaceInfo">
<sequence>
<element name="PbmCapabilityVendorNamespaceInfo" type="pbm:PbmCapabilityVendorNamespaceInfo" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmCapabilitySchema">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="vendorInfo" type="pbm:PbmCapabilitySchemaVendorInfo" />
<element name="namespaceInfo" type="pbm:PbmCapabilityNamespaceInfo" />
<element name="capabilityMetadataPerCategory" type="pbm:PbmCapabilityMetadataPerCategory" maxOccurs="unbounded" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCapabilitySchema">
<sequence>
<element name="PbmCapabilitySchema" type="pbm:PbmCapabilitySchema" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<simpleType name="PbmBuiltinGenericType">
<restriction base="xsd:string">
<enumeration value="VMW_RANGE" />
<enumeration value="VMW_SET" />
</restriction>
</simpleType>
<simpleType name="PbmBuiltinType">
<restriction base="xsd:string">
<enumeration value="XSD_LONG" />
<enumeration value="XSD_SHORT" />
<enumeration value="XSD_INTEGER" />
<enumeration value="XSD_INT" />
<enumeration value="XSD_STRING" />
<enumeration value="XSD_BOOLEAN" />
<enumeration value="XSD_DOUBLE" />
<enumeration value="XSD_DATETIME" />
<enumeration value="VMW_TIMESPAN" />
</restriction>
</simpleType>
<complexType name="PbmCapabilityDescription">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="description" type="pbm:PbmExtendedElementDescription" />
<element name="value" type="xsd:anyType" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityDiscreteSet">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="values" type="xsd:anyType" maxOccurs="unbounded" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityRange">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="min" type="xsd:anyType" />
<element name="max" type="xsd:anyType" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityTimeSpan">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="value" type="xsd:int" />
<element name="unit" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<simpleType name="PbmCapabilityTimeUnitType">
<restriction base="xsd:string">
<enumeration value="SECONDS" />
<enumeration value="MINUTES" />
<enumeration value="HOURS" />
<enumeration value="DAYS" />
<enumeration value="WEEKS" />
<enumeration value="MONTHS" />
<enumeration value="YEARS" />
</restriction>
</simpleType>
<simpleType name="PbmComplianceStatus">
<restriction base="xsd:string">
<enumeration value="compliant" />
<enumeration value="nonCompliant" />
<enumeration value="unknown" />
<enumeration value="notApplicable" />
</restriction>
</simpleType>
<complexType name="PbmComplianceResult">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="checkTime" type="xsd:dateTime" />
<element name="entity" type="pbm:PbmServerObjectRef" />
<element name="profile" type="pbm:PbmProfileId" minOccurs="0" />
<element name="complianceStatus" type="xsd:string" />
<element name="mismatch" type="xsd:boolean" />
<element name="violatedPolicies" type="pbm:PbmCompliancePolicyStatus" minOccurs="0" maxOccurs="unbounded" />
<element name="operationalStatus" type="pbm:PbmComplianceOperationalStatus" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmComplianceResult">
<sequence>
<element name="PbmComplianceResult" type="pbm:PbmComplianceResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmComplianceOperationalStatus">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="healthy" type="xsd:boolean" minOccurs="0" />
<element name="operationETA" type="xsd:dateTime" minOccurs="0" />
<element name="operationProgress" type="xsd:long" minOccurs="0" />
<element name="transitional" type="xsd:boolean" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCompliancePolicyStatus">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="expectedValue" type="pbm:PbmCapabilityInstance" />
<element name="currentValue" type="pbm:PbmCapabilityInstance" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCompliancePolicyStatus">
<sequence>
<element name="PbmCompliancePolicyStatus" type="pbm:PbmCompliancePolicyStatus" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmRollupComplianceResult">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="oldestCheckTime" type="xsd:dateTime" />
<element name="entity" type="pbm:PbmServerObjectRef" />
<element name="overallComplianceStatus" type="xsd:string" />
<element name="result" type="pbm:PbmComplianceResult" minOccurs="0" maxOccurs="unbounded" />
<element name="profileMismatch" type="xsd:boolean" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmRollupComplianceResult">
<sequence>
<element name="PbmRollupComplianceResult" type="pbm:PbmRollupComplianceResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmAlreadyExists">
<complexContent>
<extension base="pbm:PbmFault">
<sequence>
<element name="name" type="xsd:string" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityProfilePropertyMismatchFault">
<complexContent>
<extension base="pbm:PbmPropertyMismatchFault">
<sequence>
<element name="resourcePropertyInstance" type="pbm:PbmCapabilityPropertyInstance" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCompatibilityCheckFault">
<complexContent>
<extension base="pbm:PbmFault">
<sequence>
<element name="hub" type="pbm:PbmPlacementHub" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmDefaultProfileAppliesFault">
<complexContent>
<extension base="pbm:PbmCompatibilityCheckFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmDuplicateName">
<complexContent>
<extension base="pbm:PbmFault">
<sequence>
<element name="name" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmIncompatibleVendorSpecificRuleSet">
<complexContent>
<extension base="pbm:PbmCapabilityProfilePropertyMismatchFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmFaultNotFound">
<complexContent>
<extension base="pbm:PbmFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmFault">
<complexContent>
<extension base="vim25:MethodFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmFaultProfileStorageFault">
<complexContent>
<extension base="pbm:PbmFault">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmPropertyMismatchFault">
<complexContent>
<extension base="pbm:PbmCompatibilityCheckFault">
<sequence>
<element name="capabilityInstanceId" type="pbm:PbmCapabilityMetadataUniqueId" />
<element name="requirementPropertyInstance" type="pbm:PbmCapabilityPropertyInstance" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmResourceInUse">
<complexContent>
<extension base="pbm:PbmFault">
<sequence>
<element name="type" type="xsd:string" minOccurs="0" />
<element name="name" type="xsd:string" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmPlacementCompatibilityResult">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="hub" type="pbm:PbmPlacementHub" />
<element name="warning" type="vim25:LocalizedMethodFault" minOccurs="0" maxOccurs="unbounded" />
<element name="error" type="vim25:LocalizedMethodFault" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmPlacementCompatibilityResult">
<sequence>
<element name="PbmPlacementCompatibilityResult" type="pbm:PbmPlacementCompatibilityResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmPlacementHub">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="hubType" type="xsd:string" />
<element name="hubId" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmPlacementHub">
<sequence>
<element name="PbmPlacementHub" type="pbm:PbmPlacementHub" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<simpleType name="PbmProfileCategoryEnum">
<restriction base="xsd:string">
<enumeration value="REQUIREMENT" />
<enumeration value="RESOURCE" />
</restriction>
</simpleType>
<complexType name="PbmCapabilityProfile">
<complexContent>
<extension base="pbm:PbmProfile">
<sequence>
<element name="profileCategory" type="xsd:string" />
<element name="resourceType" type="pbm:PbmProfileResourceType" />
<element name="constraints" type="pbm:PbmCapabilityConstraints" />
<element name="generationId" type="xsd:long" minOccurs="0" />
<element name="isDefault" type="xsd:boolean" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityProfileCreateSpec">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="name" type="xsd:string" />
<element name="description" type="xsd:string" minOccurs="0" />
<element name="resourceType" type="pbm:PbmProfileResourceType" />
<element name="constraints" type="pbm:PbmCapabilityConstraints" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityProfileUpdateSpec">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="name" type="xsd:string" minOccurs="0" />
<element name="description" type="xsd:string" minOccurs="0" />
<element name="constraints" type="pbm:PbmCapabilityConstraints" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmCapabilityConstraints">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmDefaultCapabilityProfile">
<complexContent>
<extension base="pbm:PbmCapabilityProfile">
<sequence>
<element name="vvolType" type="xsd:string" maxOccurs="unbounded" />
<element name="containerId" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="PbmProfile">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="profileId" type="pbm:PbmProfileId" />
<element name="name" type="xsd:string" />
<element name="description" type="xsd:string" minOccurs="0" />
<element name="creationTime" type="xsd:dateTime" />
<element name="createdBy" type="xsd:string" />
<element name="lastUpdatedTime" type="xsd:dateTime" />
<element name="lastUpdatedBy" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmProfile">
<sequence>
<element name="PbmProfile" type="pbm:PbmProfile" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmProfileId">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="uniqueId" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmProfileId">
<sequence>
<element name="PbmProfileId" type="pbm:PbmProfileId" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmProfileOperationOutcome">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="profileId" type="pbm:PbmProfileId" />
<element name="fault" type="vim25:LocalizedMethodFault" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmProfileOperationOutcome">
<sequence>
<element name="PbmProfileOperationOutcome" type="pbm:PbmProfileOperationOutcome" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmProfileType">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="uniqueId" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmProfileType">
<sequence>
<element name="PbmProfileType" type="pbm:PbmProfileType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmQueryProfileResult">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="object" type="pbm:PbmServerObjectRef" />
<element name="profileId" type="pbm:PbmProfileId" minOccurs="0" maxOccurs="unbounded" />
<element name="fault" type="vim25:LocalizedMethodFault" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmQueryProfileResult">
<sequence>
<element name="PbmQueryProfileResult" type="pbm:PbmQueryProfileResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmProfileResourceType">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="resourceType" type="xsd:string" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmProfileResourceType">
<sequence>
<element name="PbmProfileResourceType" type="pbm:PbmProfileResourceType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<simpleType name="PbmProfileResourceTypeEnum">
<restriction base="xsd:string">
<enumeration value="STORAGE" />
</restriction>
</simpleType>
<complexType name="PbmCapabilitySubProfile">
<complexContent>
<extension base="vim25:DynamicData">
<sequence>
<element name="name" type="xsd:string" />
<element name="capability" type="pbm:PbmCapabilityInstance" maxOccurs="unbounded" />
<element name="forceProvision" type="xsd:boolean" minOccurs="0" />
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfPbmCapabilitySubProfile">
<sequence>
<element name="PbmCapabilitySubProfile" type="pbm:PbmCapabilitySubProfile" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="PbmCapabilitySubProfileConstraints">
<complexContent>
<extension base="pbm:PbmCapabilityConstraints">
<sequence>
<element name="subProfiles" type="pbm:PbmCapabilitySubProfile" maxOccurs="unbounded" />
</sequence>
</extension>
</complexContent>
</complexType>
</schema>

View File

@ -1,889 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright 2005-2013 VMware, Inc. All rights reserved.
-->
<definitions targetNamespace="urn:pbm"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:pbm="urn:pbm"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>
<types>
<schema
targetNamespace="urn:pbm"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:pbm="urn:pbm"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:vim25="urn:vim25"
elementFormDefault="qualified"
>
<import namespace="urn:vim25" schemaLocation="core-types.xsd" />
<include schemaLocation="pbm-messagetypes.xsd" />
<element name="versionURI" type="xsd:string" />
<element name="HostCommunicationFault" type="vim25:HostCommunication"/>
<element name="HostNotConnectedFault" type="vim25:HostNotConnected"/>
<element name="HostNotReachableFault" type="vim25:HostNotReachable"/>
<element name="InvalidArgumentFault" type="vim25:InvalidArgument"/>
<element name="InvalidRequestFault" type="vim25:InvalidRequest"/>
<element name="InvalidTypeFault" type="vim25:InvalidType"/>
<element name="ManagedObjectNotFoundFault" type="vim25:ManagedObjectNotFound"/>
<element name="MethodNotFoundFault" type="vim25:MethodNotFound"/>
<element name="NotEnoughLicensesFault" type="vim25:NotEnoughLicenses"/>
<element name="NotImplementedFault" type="vim25:NotImplemented"/>
<element name="NotSupportedFault" type="vim25:NotSupported"/>
<element name="RequestCanceledFault" type="vim25:RequestCanceled"/>
<element name="SecurityErrorFault" type="vim25:SecurityError"/>
<element name="SystemErrorFault" type="vim25:SystemError"/>
<element name="UnexpectedFaultFault" type="vim25:UnexpectedFault"/>
<element name="MethodFaultFault" type="vim25:MethodFault"/>
<element name="RuntimeFaultFault" type="vim25:RuntimeFault"/>
<element name="PbmRetrieveServiceContent" type="pbm:PbmRetrieveServiceContentRequestType" />
<element name="PbmRetrieveServiceContentResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmServiceInstanceContent" />
</sequence>
</complexType>
</element>
<element name="PbmCheckCompliance" type="pbm:PbmCheckComplianceRequestType" />
<element name="PbmCheckComplianceResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmComplianceResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmFetchComplianceResult" type="pbm:PbmFetchComplianceResultRequestType" />
<element name="PbmFetchComplianceResultResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmComplianceResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmCheckRollupCompliance" type="pbm:PbmCheckRollupComplianceRequestType" />
<element name="PbmCheckRollupComplianceResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmRollupComplianceResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmFetchRollupComplianceResult" type="pbm:PbmFetchRollupComplianceResultRequestType" />
<element name="PbmFetchRollupComplianceResultResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmRollupComplianceResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmAlreadyExistsFault" type="pbm:PbmAlreadyExists"/>
<element name="PbmCapabilityProfilePropertyMismatchFaultFault" type="pbm:PbmCapabilityProfilePropertyMismatchFault"/>
<element name="PbmCompatibilityCheckFaultFault" type="pbm:PbmCompatibilityCheckFault"/>
<element name="PbmDefaultProfileAppliesFaultFault" type="pbm:PbmDefaultProfileAppliesFault"/>
<element name="PbmDuplicateNameFault" type="pbm:PbmDuplicateName"/>
<element name="PbmIncompatibleVendorSpecificRuleSetFault" type="pbm:PbmIncompatibleVendorSpecificRuleSet"/>
<element name="PbmFaultNotFoundFault" type="pbm:PbmFaultNotFound"/>
<element name="PbmFaultFault" type="pbm:PbmFault"/>
<element name="PbmFaultProfileStorageFaultFault" type="pbm:PbmFaultProfileStorageFault"/>
<element name="PbmPropertyMismatchFaultFault" type="pbm:PbmPropertyMismatchFault"/>
<element name="PbmResourceInUseFault" type="pbm:PbmResourceInUse"/>
<element name="PbmQueryMatchingHub" type="pbm:PbmQueryMatchingHubRequestType" />
<element name="PbmQueryMatchingHubResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmPlacementHub" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmQueryMatchingHubWithSpec" type="pbm:PbmQueryMatchingHubWithSpecRequestType" />
<element name="PbmQueryMatchingHubWithSpecResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmPlacementHub" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmCheckCompatibility" type="pbm:PbmCheckCompatibilityRequestType" />
<element name="PbmCheckCompatibilityResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmPlacementCompatibilityResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmCheckCompatibilityWithSpec" type="pbm:PbmCheckCompatibilityWithSpecRequestType" />
<element name="PbmCheckCompatibilityWithSpecResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmPlacementCompatibilityResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmFetchResourceType" type="pbm:PbmFetchResourceTypeRequestType" />
<element name="PbmFetchResourceTypeResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmProfileResourceType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmFetchVendorInfo" type="pbm:PbmFetchVendorInfoRequestType" />
<element name="PbmFetchVendorInfoResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmCapabilityVendorResourceTypeInfo" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmFetchCapabilityMetadata" type="pbm:PbmFetchCapabilityMetadataRequestType" />
<element name="PbmFetchCapabilityMetadataResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmCapabilityMetadataPerCategory" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmCreate" type="pbm:PbmCreateRequestType" />
<element name="PbmCreateResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmProfileId" />
</sequence>
</complexType>
</element>
<element name="PbmUpdate" type="pbm:PbmUpdateRequestType" />
<element name="PbmUpdateResponse">
<complexType />
</element>
<element name="PbmDelete" type="pbm:PbmDeleteRequestType" />
<element name="PbmDeleteResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmProfileOperationOutcome" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmQueryProfile" type="pbm:PbmQueryProfileRequestType" />
<element name="PbmQueryProfileResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmProfileId" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmRetrieveContent" type="pbm:PbmRetrieveContentRequestType" />
<element name="PbmRetrieveContentResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmProfile" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmQueryAssociatedProfiles" type="pbm:PbmQueryAssociatedProfilesRequestType" />
<element name="PbmQueryAssociatedProfilesResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmQueryProfileResult" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmQueryAssociatedProfile" type="pbm:PbmQueryAssociatedProfileRequestType" />
<element name="PbmQueryAssociatedProfileResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmProfileId" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmQueryAssociatedEntity" type="pbm:PbmQueryAssociatedEntityRequestType" />
<element name="PbmQueryAssociatedEntityResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmServerObjectRef" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<element name="PbmQueryDefaultRequirementProfile" type="pbm:PbmQueryDefaultRequirementProfileRequestType" />
<element name="PbmQueryDefaultRequirementProfileResponse">
<complexType>
<sequence>
<element name="returnval" type="pbm:PbmProfileId" minOccurs="0" />
</sequence>
</complexType>
</element>
<element name="PbmResetDefaultRequirementProfile" type="pbm:PbmResetDefaultRequirementProfileRequestType" />
<element name="PbmResetDefaultRequirementProfileResponse">
<complexType />
</element>
</schema>
</types>
<message name="HostCommunicationFaultMsg">
<part name="fault" element="pbm:HostCommunicationFault" />
</message>
<message name="HostNotConnectedFaultMsg">
<part name="fault" element="pbm:HostNotConnectedFault" />
</message>
<message name="HostNotReachableFaultMsg">
<part name="fault" element="pbm:HostNotReachableFault" />
</message>
<message name="InvalidArgumentFaultMsg">
<part name="fault" element="pbm:InvalidArgumentFault" />
</message>
<message name="InvalidRequestFaultMsg">
<part name="fault" element="pbm:InvalidRequestFault" />
</message>
<message name="InvalidTypeFaultMsg">
<part name="fault" element="pbm:InvalidTypeFault" />
</message>
<message name="ManagedObjectNotFoundFaultMsg">
<part name="fault" element="pbm:ManagedObjectNotFoundFault" />
</message>
<message name="MethodNotFoundFaultMsg">
<part name="fault" element="pbm:MethodNotFoundFault" />
</message>
<message name="NotEnoughLicensesFaultMsg">
<part name="fault" element="pbm:NotEnoughLicensesFault" />
</message>
<message name="NotImplementedFaultMsg">
<part name="fault" element="pbm:NotImplementedFault" />
</message>
<message name="NotSupportedFaultMsg">
<part name="fault" element="pbm:NotSupportedFault" />
</message>
<message name="RequestCanceledFaultMsg">
<part name="fault" element="pbm:RequestCanceledFault" />
</message>
<message name="SecurityErrorFaultMsg">
<part name="fault" element="pbm:SecurityErrorFault" />
</message>
<message name="SystemErrorFaultMsg">
<part name="fault" element="pbm:SystemErrorFault" />
</message>
<message name="UnexpectedFaultFaultMsg">
<part name="fault" element="pbm:UnexpectedFaultFault" />
</message>
<message name="MethodFaultFaultMsg">
<part name="fault" element="pbm:MethodFaultFault" />
</message>
<message name="RuntimeFaultFaultMsg">
<part name="fault" element="pbm:RuntimeFaultFault" />
</message>
<message name="PbmRetrieveServiceContentRequestMsg">
<part name="parameters" element="pbm:PbmRetrieveServiceContent" />
</message>
<message name="PbmRetrieveServiceContentResponseMsg">
<part name="parameters" element="pbm:PbmRetrieveServiceContentResponse" />
</message>
<message name="PbmCheckComplianceRequestMsg">
<part name="parameters" element="pbm:PbmCheckCompliance" />
</message>
<message name="PbmCheckComplianceResponseMsg">
<part name="parameters" element="pbm:PbmCheckComplianceResponse" />
</message>
<message name="PbmFetchComplianceResultRequestMsg">
<part name="parameters" element="pbm:PbmFetchComplianceResult" />
</message>
<message name="PbmFetchComplianceResultResponseMsg">
<part name="parameters" element="pbm:PbmFetchComplianceResultResponse" />
</message>
<message name="PbmCheckRollupComplianceRequestMsg">
<part name="parameters" element="pbm:PbmCheckRollupCompliance" />
</message>
<message name="PbmCheckRollupComplianceResponseMsg">
<part name="parameters" element="pbm:PbmCheckRollupComplianceResponse" />
</message>
<message name="PbmFetchRollupComplianceResultRequestMsg">
<part name="parameters" element="pbm:PbmFetchRollupComplianceResult" />
</message>
<message name="PbmFetchRollupComplianceResultResponseMsg">
<part name="parameters" element="pbm:PbmFetchRollupComplianceResultResponse" />
</message>
<message name="PbmAlreadyExistsFaultMsg">
<part name="fault" element="pbm:PbmAlreadyExistsFault" />
</message>
<message name="PbmCapabilityProfilePropertyMismatchFaultFaultMsg">
<part name="fault" element="pbm:PbmCapabilityProfilePropertyMismatchFaultFault" />
</message>
<message name="PbmCompatibilityCheckFaultFaultMsg">
<part name="fault" element="pbm:PbmCompatibilityCheckFaultFault" />
</message>
<message name="PbmDefaultProfileAppliesFaultFaultMsg">
<part name="fault" element="pbm:PbmDefaultProfileAppliesFaultFault" />
</message>
<message name="PbmDuplicateNameFaultMsg">
<part name="fault" element="pbm:PbmDuplicateNameFault" />
</message>
<message name="PbmIncompatibleVendorSpecificRuleSetFaultMsg">
<part name="fault" element="pbm:PbmIncompatibleVendorSpecificRuleSetFault" />
</message>
<message name="PbmFaultNotFoundFaultMsg">
<part name="fault" element="pbm:PbmFaultNotFoundFault" />
</message>
<message name="PbmFaultFaultMsg">
<part name="fault" element="pbm:PbmFaultFault" />
</message>
<message name="PbmFaultProfileStorageFaultFaultMsg">
<part name="fault" element="pbm:PbmFaultProfileStorageFaultFault" />
</message>
<message name="PbmPropertyMismatchFaultFaultMsg">
<part name="fault" element="pbm:PbmPropertyMismatchFaultFault" />
</message>
<message name="PbmResourceInUseFaultMsg">
<part name="fault" element="pbm:PbmResourceInUseFault" />
</message>
<message name="PbmQueryMatchingHubRequestMsg">
<part name="parameters" element="pbm:PbmQueryMatchingHub" />
</message>
<message name="PbmQueryMatchingHubResponseMsg">
<part name="parameters" element="pbm:PbmQueryMatchingHubResponse" />
</message>
<message name="PbmQueryMatchingHubWithSpecRequestMsg">
<part name="parameters" element="pbm:PbmQueryMatchingHubWithSpec" />
</message>
<message name="PbmQueryMatchingHubWithSpecResponseMsg">
<part name="parameters" element="pbm:PbmQueryMatchingHubWithSpecResponse" />
</message>
<message name="PbmCheckCompatibilityRequestMsg">
<part name="parameters" element="pbm:PbmCheckCompatibility" />
</message>
<message name="PbmCheckCompatibilityResponseMsg">
<part name="parameters" element="pbm:PbmCheckCompatibilityResponse" />
</message>
<message name="PbmCheckCompatibilityWithSpecRequestMsg">
<part name="parameters" element="pbm:PbmCheckCompatibilityWithSpec" />
</message>
<message name="PbmCheckCompatibilityWithSpecResponseMsg">
<part name="parameters" element="pbm:PbmCheckCompatibilityWithSpecResponse" />
</message>
<message name="PbmFetchResourceTypeRequestMsg">
<part name="parameters" element="pbm:PbmFetchResourceType" />
</message>
<message name="PbmFetchResourceTypeResponseMsg">
<part name="parameters" element="pbm:PbmFetchResourceTypeResponse" />
</message>
<message name="PbmFetchVendorInfoRequestMsg">
<part name="parameters" element="pbm:PbmFetchVendorInfo" />
</message>
<message name="PbmFetchVendorInfoResponseMsg">
<part name="parameters" element="pbm:PbmFetchVendorInfoResponse" />
</message>
<message name="PbmFetchCapabilityMetadataRequestMsg">
<part name="parameters" element="pbm:PbmFetchCapabilityMetadata" />
</message>
<message name="PbmFetchCapabilityMetadataResponseMsg">
<part name="parameters" element="pbm:PbmFetchCapabilityMetadataResponse" />
</message>
<message name="PbmCreateRequestMsg">
<part name="parameters" element="pbm:PbmCreate" />
</message>
<message name="PbmCreateResponseMsg">
<part name="parameters" element="pbm:PbmCreateResponse" />
</message>
<message name="PbmUpdateRequestMsg">
<part name="parameters" element="pbm:PbmUpdate" />
</message>
<message name="PbmUpdateResponseMsg">
<part name="parameters" element="pbm:PbmUpdateResponse" />
</message>
<message name="PbmDeleteRequestMsg">
<part name="parameters" element="pbm:PbmDelete" />
</message>
<message name="PbmDeleteResponseMsg">
<part name="parameters" element="pbm:PbmDeleteResponse" />
</message>
<message name="PbmQueryProfileRequestMsg">
<part name="parameters" element="pbm:PbmQueryProfile" />
</message>
<message name="PbmQueryProfileResponseMsg">
<part name="parameters" element="pbm:PbmQueryProfileResponse" />
</message>
<message name="PbmRetrieveContentRequestMsg">
<part name="parameters" element="pbm:PbmRetrieveContent" />
</message>
<message name="PbmRetrieveContentResponseMsg">
<part name="parameters" element="pbm:PbmRetrieveContentResponse" />
</message>
<message name="PbmQueryAssociatedProfilesRequestMsg">
<part name="parameters" element="pbm:PbmQueryAssociatedProfiles" />
</message>
<message name="PbmQueryAssociatedProfilesResponseMsg">
<part name="parameters" element="pbm:PbmQueryAssociatedProfilesResponse" />
</message>
<message name="PbmQueryAssociatedProfileRequestMsg">
<part name="parameters" element="pbm:PbmQueryAssociatedProfile" />
</message>
<message name="PbmQueryAssociatedProfileResponseMsg">
<part name="parameters" element="pbm:PbmQueryAssociatedProfileResponse" />
</message>
<message name="PbmQueryAssociatedEntityRequestMsg">
<part name="parameters" element="pbm:PbmQueryAssociatedEntity" />
</message>
<message name="PbmQueryAssociatedEntityResponseMsg">
<part name="parameters" element="pbm:PbmQueryAssociatedEntityResponse" />
</message>
<message name="PbmQueryDefaultRequirementProfileRequestMsg">
<part name="parameters" element="pbm:PbmQueryDefaultRequirementProfile" />
</message>
<message name="PbmQueryDefaultRequirementProfileResponseMsg">
<part name="parameters" element="pbm:PbmQueryDefaultRequirementProfileResponse" />
</message>
<message name="PbmResetDefaultRequirementProfileRequestMsg">
<part name="parameters" element="pbm:PbmResetDefaultRequirementProfile" />
</message>
<message name="PbmResetDefaultRequirementProfileResponseMsg">
<part name="parameters" element="pbm:PbmResetDefaultRequirementProfileResponse" />
</message>
<portType name="PbmPortType">
<operation name="PbmRetrieveServiceContent">
<input message="pbm:PbmRetrieveServiceContentRequestMsg" />
<output message="pbm:PbmRetrieveServiceContentResponseMsg" />
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmCheckCompliance">
<input message="pbm:PbmCheckComplianceRequestMsg" />
<output message="pbm:PbmCheckComplianceResponseMsg" />
<fault name="PbmFaultFault" message="pbm:PbmFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmFetchComplianceResult">
<input message="pbm:PbmFetchComplianceResultRequestMsg" />
<output message="pbm:PbmFetchComplianceResultResponseMsg" />
<fault name="PbmFaultFault" message="pbm:PbmFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmCheckRollupCompliance">
<input message="pbm:PbmCheckRollupComplianceRequestMsg" />
<output message="pbm:PbmCheckRollupComplianceResponseMsg" />
<fault name="PbmFaultFault" message="pbm:PbmFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmFetchRollupComplianceResult">
<input message="pbm:PbmFetchRollupComplianceResultRequestMsg" />
<output message="pbm:PbmFetchRollupComplianceResultResponseMsg" />
<fault name="PbmFaultFault" message="pbm:PbmFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmQueryMatchingHub">
<input message="pbm:PbmQueryMatchingHubRequestMsg" />
<output message="pbm:PbmQueryMatchingHubResponseMsg" />
<fault name="PbmFaultFault" message="pbm:PbmFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmQueryMatchingHubWithSpec">
<input message="pbm:PbmQueryMatchingHubWithSpecRequestMsg" />
<output message="pbm:PbmQueryMatchingHubWithSpecResponseMsg" />
<fault name="PbmFaultFault" message="pbm:PbmFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmCheckCompatibility">
<input message="pbm:PbmCheckCompatibilityRequestMsg" />
<output message="pbm:PbmCheckCompatibilityResponseMsg" />
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmCheckCompatibilityWithSpec">
<input message="pbm:PbmCheckCompatibilityWithSpecRequestMsg" />
<output message="pbm:PbmCheckCompatibilityWithSpecResponseMsg" />
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmFetchResourceType">
<input message="pbm:PbmFetchResourceTypeRequestMsg" />
<output message="pbm:PbmFetchResourceTypeResponseMsg" />
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmFetchVendorInfo">
<input message="pbm:PbmFetchVendorInfoRequestMsg" />
<output message="pbm:PbmFetchVendorInfoResponseMsg" />
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmFetchCapabilityMetadata">
<input message="pbm:PbmFetchCapabilityMetadataRequestMsg" />
<output message="pbm:PbmFetchCapabilityMetadataResponseMsg" />
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmCreate">
<input message="pbm:PbmCreateRequestMsg" />
<output message="pbm:PbmCreateResponseMsg" />
<fault name="InvalidArgumentFault" message="pbm:InvalidArgumentFaultMsg"/>
<fault name="PbmFaultProfileStorageFaultFault" message="pbm:PbmFaultProfileStorageFaultFaultMsg"/>
<fault name="PbmDuplicateNameFault" message="pbm:PbmDuplicateNameFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmUpdate">
<input message="pbm:PbmUpdateRequestMsg" />
<output message="pbm:PbmUpdateResponseMsg" />
<fault name="InvalidArgumentFault" message="pbm:InvalidArgumentFaultMsg"/>
<fault name="PbmFaultProfileStorageFaultFault" message="pbm:PbmFaultProfileStorageFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmDelete">
<input message="pbm:PbmDeleteRequestMsg" />
<output message="pbm:PbmDeleteResponseMsg" />
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmQueryProfile">
<input message="pbm:PbmQueryProfileRequestMsg" />
<output message="pbm:PbmQueryProfileResponseMsg" />
<fault name="InvalidArgumentFault" message="pbm:InvalidArgumentFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmRetrieveContent">
<input message="pbm:PbmRetrieveContentRequestMsg" />
<output message="pbm:PbmRetrieveContentResponseMsg" />
<fault name="InvalidArgumentFault" message="pbm:InvalidArgumentFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmQueryAssociatedProfiles">
<input message="pbm:PbmQueryAssociatedProfilesRequestMsg" />
<output message="pbm:PbmQueryAssociatedProfilesResponseMsg" />
<fault name="PbmFaultFault" message="pbm:PbmFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmQueryAssociatedProfile">
<input message="pbm:PbmQueryAssociatedProfileRequestMsg" />
<output message="pbm:PbmQueryAssociatedProfileResponseMsg" />
<fault name="PbmFaultFault" message="pbm:PbmFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmQueryAssociatedEntity">
<input message="pbm:PbmQueryAssociatedEntityRequestMsg" />
<output message="pbm:PbmQueryAssociatedEntityResponseMsg" />
<fault name="PbmFaultFault" message="pbm:PbmFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmQueryDefaultRequirementProfile">
<input message="pbm:PbmQueryDefaultRequirementProfileRequestMsg" />
<output message="pbm:PbmQueryDefaultRequirementProfileResponseMsg" />
<fault name="InvalidArgumentFault" message="pbm:InvalidArgumentFaultMsg"/>
<fault name="PbmFaultFault" message="pbm:PbmFaultFaultMsg"/>
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
<operation name="PbmResetDefaultRequirementProfile">
<input message="pbm:PbmResetDefaultRequirementProfileRequestMsg" />
<output message="pbm:PbmResetDefaultRequirementProfileResponseMsg" />
<fault name="RuntimeFault" message="pbm:RuntimeFaultFaultMsg"/>
</operation>
</portType>
<binding name="PbmBinding" type="pbm:PbmPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="PbmRetrieveServiceContent">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmCheckCompliance">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="PbmFaultFault">
<soap:fault name="PbmFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmFetchComplianceResult">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="PbmFaultFault">
<soap:fault name="PbmFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmCheckRollupCompliance">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="PbmFaultFault">
<soap:fault name="PbmFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmFetchRollupComplianceResult">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="PbmFaultFault">
<soap:fault name="PbmFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmQueryMatchingHub">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="PbmFaultFault">
<soap:fault name="PbmFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmQueryMatchingHubWithSpec">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="PbmFaultFault">
<soap:fault name="PbmFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmCheckCompatibility">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmCheckCompatibilityWithSpec">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmFetchResourceType">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmFetchVendorInfo">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmFetchCapabilityMetadata">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmCreate">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="InvalidArgumentFault">
<soap:fault name="InvalidArgumentFault" use="literal" />
</fault>
<fault name="PbmFaultProfileStorageFaultFault">
<soap:fault name="PbmFaultProfileStorageFaultFault" use="literal" />
</fault>
<fault name="PbmDuplicateNameFault">
<soap:fault name="PbmDuplicateNameFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmUpdate">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="InvalidArgumentFault">
<soap:fault name="InvalidArgumentFault" use="literal" />
</fault>
<fault name="PbmFaultProfileStorageFaultFault">
<soap:fault name="PbmFaultProfileStorageFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmDelete">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmQueryProfile">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="InvalidArgumentFault">
<soap:fault name="InvalidArgumentFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmRetrieveContent">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="InvalidArgumentFault">
<soap:fault name="InvalidArgumentFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmQueryAssociatedProfiles">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="PbmFaultFault">
<soap:fault name="PbmFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmQueryAssociatedProfile">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="PbmFaultFault">
<soap:fault name="PbmFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmQueryAssociatedEntity">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="PbmFaultFault">
<soap:fault name="PbmFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmQueryDefaultRequirementProfile">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="InvalidArgumentFault">
<soap:fault name="InvalidArgumentFault" use="literal" />
</fault>
<fault name="PbmFaultFault">
<soap:fault name="PbmFaultFault" use="literal" />
</fault>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
<operation name="PbmResetDefaultRequirementProfile">
<soap:operation soapAction="urn:pbm/1.0" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
<fault name="RuntimeFault">
<soap:fault name="RuntimeFault" use="literal" />
</fault>
</operation>
</binding>
</definitions>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright 2005-2013 VMware, Inc. All rights reserved.
-->
<definitions targetNamespace="urn:pbmService"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:interface="urn:pbm"
>
<import location="pbm.wsdl" namespace="urn:pbm" />
<service name="PbmService">
<port binding="interface:PbmBinding" name="PbmPort">
<soap:address location="http://localhost/pbm/services/pbmService" />
</port>
</service>
</definitions>

View File

@ -43,4 +43,5 @@ suds>=0.4
WebOb>=1.2.3
wsgiref>=0.1.2
oslo.i18n>=1.3.0 # Apache-2.0
oslo.vmware>=0.9.0 # Apache-2.0
xattr>=0.4