89b4a8a1b9
Log messages are no longer being translated. This removes all use of the _LE, _LI, and _LW translation markers to simplify logging and to avoid confusion with new contributions. See: http://lists.openstack.org/pipermail/openstack-i18n/2016-November/002574.html http://lists.openstack.org/pipermail/openstack-dev/2017-March/113365.html Change-Id: Ib7bb69eac558fa157331f9cf0fb452e6053714a7
242 lines
8.6 KiB
Python
242 lines
8.6 KiB
Python
# 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.
|
|
|
|
"""
|
|
VMware PBM service client and PBM related utility methods
|
|
|
|
PBM is used for policy based placement in VMware datastores.
|
|
Refer http://goo.gl/GR2o6U for more details.
|
|
"""
|
|
|
|
import logging
|
|
import os
|
|
|
|
import six.moves.urllib.parse as urlparse
|
|
import six.moves.urllib.request as urllib
|
|
|
|
from oslo_vmware import service
|
|
from oslo_vmware import vim_util
|
|
|
|
|
|
SERVICE_TYPE = 'PbmServiceInstance'
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class Pbm(service.Service):
|
|
"""Service class that provides access to the Storage Policy API."""
|
|
|
|
def __init__(self, protocol='https', host='localhost', port=443,
|
|
wsdl_url=None, cacert=None, insecure=True, pool_maxsize=10,
|
|
connection_timeout=None, op_id_prefix='oslo.vmware'):
|
|
"""Constructs a PBM service client object.
|
|
|
|
:param protocol: http or https
|
|
:param host: server IP address or host name
|
|
:param port: port for connection
|
|
:param wsdl_url: PBM WSDL url
|
|
:param cacert: Specify a CA bundle file to use in verifying a
|
|
TLS (https) server certificate.
|
|
:param insecure: Verify HTTPS connections using system certificates,
|
|
used only if cacert is not specified
|
|
:param pool_maxsize: Maximum number of connections in http
|
|
connection pool
|
|
:param op_id_prefix: String prefix for the operation ID.
|
|
:param connection_timeout: Maximum time in seconds to wait for peer to
|
|
respond.
|
|
"""
|
|
base_url = service.Service.build_base_url(protocol, host, port)
|
|
soap_url = base_url + '/pbm'
|
|
super(Pbm, self).__init__(wsdl_url, soap_url, cacert, insecure,
|
|
pool_maxsize, connection_timeout,
|
|
op_id_prefix)
|
|
|
|
def set_soap_cookie(self, cookie):
|
|
"""Set the specified vCenter session cookie in the SOAP header
|
|
|
|
:param cookie: cookie to set
|
|
"""
|
|
self._vc_session_cookie = cookie
|
|
|
|
def retrieve_service_content(self):
|
|
ref = vim_util.get_moref(service.SERVICE_INSTANCE, SERVICE_TYPE)
|
|
return self.PbmRetrieveServiceContent(ref)
|
|
|
|
def __repr__(self):
|
|
return "PBM Object"
|
|
|
|
def __str__(self):
|
|
return "PBM Object"
|
|
|
|
|
|
def get_all_profiles(session):
|
|
"""Get all the profiles defined in VC server.
|
|
|
|
:returns: PbmProfile data objects
|
|
:raises: VimException, VimFaultException, VimAttributeException,
|
|
VimSessionOverLoadException, VimConnectionException
|
|
"""
|
|
LOG.debug("Fetching all the profiles defined in VC server.")
|
|
|
|
pbm = session.pbm
|
|
profile_manager = pbm.service_content.profileManager
|
|
res_type = pbm.client.factory.create('ns0:PbmProfileResourceType')
|
|
res_type.resourceType = 'STORAGE'
|
|
profiles = []
|
|
profile_ids = session.invoke_api(pbm,
|
|
'PbmQueryProfile',
|
|
profile_manager,
|
|
resourceType=res_type)
|
|
LOG.debug("Fetched profile IDs: %s.", profile_ids)
|
|
if profile_ids:
|
|
profiles = session.invoke_api(pbm,
|
|
'PbmRetrieveContent',
|
|
profile_manager,
|
|
profileIds=profile_ids)
|
|
return profiles
|
|
|
|
|
|
def get_profile_id_by_name(session, profile_name):
|
|
"""Get the profile UUID corresponding to the given profile name.
|
|
|
|
:param profile_name: profile name whose UUID needs to be retrieved
|
|
:returns: profile UUID string or None if profile not found
|
|
:raises: VimException, VimFaultException, VimAttributeException,
|
|
VimSessionOverLoadException, VimConnectionException
|
|
"""
|
|
LOG.debug("Retrieving profile ID for profile: %s.", profile_name)
|
|
for profile in get_all_profiles(session):
|
|
if profile.name == profile_name:
|
|
profile_id = profile.profileId
|
|
LOG.debug("Retrieved profile ID: %(id)s for profile: %(name)s.",
|
|
{'id': profile_id,
|
|
'name': profile_name})
|
|
return profile_id
|
|
return None
|
|
|
|
|
|
def filter_hubs_by_profile(session, hubs, profile_id):
|
|
"""Filter and return hubs that match the given profile.
|
|
|
|
:param hubs: PbmPlacementHub morefs
|
|
:param profile_id: profile ID
|
|
:returns: subset of hubs that match the given profile
|
|
:raises: VimException, VimFaultException, VimAttributeException,
|
|
VimSessionOverLoadException, VimConnectionException
|
|
"""
|
|
LOG.debug("Filtering hubs: %(hubs)s that match profile: %(profile)s.",
|
|
{'hubs': hubs,
|
|
'profile': profile_id})
|
|
|
|
pbm = session.pbm
|
|
placement_solver = pbm.service_content.placementSolver
|
|
filtered_hubs = session.invoke_api(pbm,
|
|
'PbmQueryMatchingHub',
|
|
placement_solver,
|
|
hubsToSearch=hubs,
|
|
profile=profile_id)
|
|
LOG.debug("Filtered hubs: %s", filtered_hubs)
|
|
return filtered_hubs
|
|
|
|
|
|
def convert_datastores_to_hubs(pbm_client_factory, datastores):
|
|
"""Convert given datastore morefs to PbmPlacementHub morefs.
|
|
|
|
:param pbm_client_factory: Factory to create PBM API input specs
|
|
: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 filter_datastores_by_hubs(hubs, datastores):
|
|
"""Get filtered subset of datastores corresponding to the given hub list.
|
|
|
|
:param hubs: list of PbmPlacementHub morefs
|
|
:param datastores: all candidate datastores
|
|
:returns: subset of datastores corresponding to the given hub list
|
|
"""
|
|
filtered_dss = []
|
|
hub_ids = [hub.hubId for hub in hubs]
|
|
for ds in datastores:
|
|
if ds.value in hub_ids:
|
|
filtered_dss.append(ds)
|
|
return filtered_dss
|
|
|
|
|
|
def get_pbm_wsdl_location(vc_version):
|
|
"""Return PBM WSDL file location corresponding to VC version.
|
|
|
|
:param vc_version: a dot-separated version string. For example, "1.2".
|
|
:return: the pbm wsdl file location.
|
|
"""
|
|
if not vc_version:
|
|
return
|
|
ver = vc_version.split('.')
|
|
major_minor = ver[0]
|
|
if len(ver) >= 2:
|
|
major_minor = '%s.%s' % (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.warning("PBM WSDL file %s not found.", pbm_service_wsdl)
|
|
return
|
|
pbm_wsdl = urlparse.urljoin('file:', urllib.pathname2url(pbm_service_wsdl))
|
|
LOG.debug("Using PBM WSDL location: %s.", pbm_wsdl)
|
|
return pbm_wsdl
|
|
|
|
|
|
def get_profiles(session, vm):
|
|
"""Query storage profiles associated with the given vm.
|
|
|
|
:param session: VMwareAPISession instance
|
|
:param vm: vm reference
|
|
:return: profile IDs
|
|
"""
|
|
pbm = session.pbm
|
|
profile_manager = pbm.service_content.profileManager
|
|
|
|
object_ref = pbm.client.factory.create('ns0:PbmServerObjectRef')
|
|
object_ref.key = vm.value
|
|
object_ref.objectType = 'virtualMachine'
|
|
|
|
return session.invoke_api(pbm, 'PbmQueryAssociatedProfile',
|
|
profile_manager, entity=object_ref)
|
|
|
|
|
|
def get_profiles_by_ids(session, profile_ids):
|
|
"""Get storage profiles by IDs.
|
|
|
|
:param session: VMwareAPISession instance
|
|
:param profile_ids: profile IDs
|
|
:return: profile objects
|
|
"""
|
|
profiles = []
|
|
if profile_ids:
|
|
pbm = session.pbm
|
|
profile_manager = pbm.service_content.profileManager
|
|
profiles = session.invoke_api(pbm,
|
|
'PbmRetrieveContent',
|
|
profile_manager,
|
|
profileIds=profile_ids)
|
|
return profiles
|