Replace guts with openstack.config
The code has been moved into openstacksdk. Make os-client-config a thin wrapper around that code. The legacy client code needs to stay, as it was removed in openstacksdk. We also have to plumb os_client_config.defaults and os_client_config.cloud_region.CloudRegion in so that users get the os-client-config versions from the openstacksdk methods that return the relevant objects. Support for per-service region_name has been dropped. This was never used anywhere and was added for compatibility with openstacksdk Profile objects. Since Profile objects are no more, we can remove it. It never made any sense. Change-Id: I7180e20aa675c0ccbe3718493a6eff2be7e1b8b6
This commit is contained in:
parent
cf5f446f27
commit
5c2eae8f82
@ -5,6 +5,11 @@ os-client-config
|
||||
.. image:: http://governance.openstack.org/badges/os-client-config.svg
|
||||
:target: http://governance.openstack.org/reference/tags/index.html
|
||||
|
||||
.. warning::
|
||||
`os-client-config` has been superceded by `openstacksdk`_. While
|
||||
`os-client-config` will continue to exist, it is highly recommended that
|
||||
users transition to using `openstacksdk`_ directly.
|
||||
|
||||
`os-client-config` is a library for collecting client configuration for
|
||||
using an OpenStack cloud in a consistent and comprehensive manner. It
|
||||
will find cloud config for as few as 1 cloud and as many as you want to
|
||||
@ -23,3 +28,5 @@ Source
|
||||
* Documentation: http://docs.openstack.org/os-client-config/latest
|
||||
* Source: http://git.openstack.org/cgit/openstack/os-client-config
|
||||
* Bugs: http://bugs.launchpad.net/os-client-config
|
||||
|
||||
.. _openstacksdk: http://docs.openstack.org/openstacksdk/latest
|
||||
|
@ -5,6 +5,13 @@ os-client-config
|
||||
.. image:: http://governance.openstack.org/badges/os-client-config.svg
|
||||
:target: http://governance.openstack.org/reference/tags/index.html
|
||||
|
||||
.. warning::
|
||||
`os-client-config` has been superceded by `openstacksdk`_. While
|
||||
`os-client-config` will continue to exist, it is highly recommended that
|
||||
users transition to using `openstacksdk`_ directly.
|
||||
|
||||
.. _openstacksdk: https//docs.openstack.org/openstacksdk/latest
|
||||
|
||||
`os-client-config` is a library for collecting client configuration for
|
||||
using an OpenStack cloud in a consistent and comprehensive manner. It
|
||||
will find cloud config for as few as 1 cloud and as many as you want to
|
||||
|
@ -63,7 +63,7 @@ Constructing OpenStack SDK object
|
||||
If what you want to do is get an OpenStack SDK Connection and you want it to
|
||||
do all the normal things related to clouds.yaml, `OS_` environment variables,
|
||||
a helper function is provided. The following will get you a fully configured
|
||||
`openstacksdk` instance.
|
||||
`openstack.connection.Connection` instance.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -2,355 +2,5 @@
|
||||
Vendor Support
|
||||
==============
|
||||
|
||||
OpenStack presents deployers with many options, some of which can expose
|
||||
differences to end users. `os-client-config` tries its best to collect
|
||||
information about various things a user would need to know. The following
|
||||
is a text representation of the vendor related defaults `os-client-config`
|
||||
knows about.
|
||||
|
||||
Default Values
|
||||
--------------
|
||||
|
||||
These are the default behaviors unless a cloud is configured differently.
|
||||
|
||||
* Identity uses `password` authentication
|
||||
* Identity API Version is 2
|
||||
* Image API Version is 2
|
||||
* Volume API Version is 2
|
||||
* Images must be in `qcow2` format
|
||||
* Images are uploaded using PUT interface
|
||||
* Public IPv4 is directly routable via DHCP from Neutron
|
||||
* IPv6 is not provided
|
||||
* Floating IPs are not required
|
||||
* Floating IPs are provided by Neutron
|
||||
* Security groups are provided by Neutron
|
||||
* Vendor specific agents are not used
|
||||
|
||||
auro
|
||||
----
|
||||
|
||||
https://api.auro.io:5000/v2.0
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
van1 Vancouver, BC
|
||||
============== ================
|
||||
|
||||
* Public IPv4 is provided via NAT with Neutron Floating IP
|
||||
|
||||
betacloud
|
||||
---------
|
||||
|
||||
https://api-1.betacloud.io:5000/v3
|
||||
|
||||
============== ==================
|
||||
Region Name Location
|
||||
============== ==================
|
||||
betacloud-1 Nuremberg, Germany
|
||||
============== ==================
|
||||
|
||||
* Identity API Version is 3
|
||||
* Images must be in `raw` format
|
||||
* Public IPv4 is provided via NAT with Neutron Floating IP
|
||||
* Volume API Version is 3
|
||||
|
||||
catalyst
|
||||
--------
|
||||
|
||||
https://api.cloud.catalyst.net.nz:5000/v2.0
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
nz-por-1 Porirua, NZ
|
||||
nz_wlg_2 Wellington, NZ
|
||||
============== ================
|
||||
|
||||
* Image API Version is 1
|
||||
* Images must be in `raw` format
|
||||
* Volume API Version is 1
|
||||
|
||||
citycloud
|
||||
---------
|
||||
|
||||
https://identity1.citycloud.com:5000/v3/
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
Buf1 Buffalo, NY
|
||||
Fra1 Frankfurt, DE
|
||||
Kna1 Karlskrona, SE
|
||||
La1 Los Angeles, CA
|
||||
Lon1 London, UK
|
||||
Sto2 Stockholm, SE
|
||||
============== ================
|
||||
|
||||
* Identity API Version is 3
|
||||
* Public IPv4 is provided via NAT with Neutron Floating IP
|
||||
* Volume API Version is 1
|
||||
|
||||
conoha
|
||||
------
|
||||
|
||||
https://identity.%(region_name)s.conoha.io
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
tyo1 Tokyo, JP
|
||||
sin1 Singapore
|
||||
sjc1 San Jose, CA
|
||||
============== ================
|
||||
|
||||
* Image upload is not supported
|
||||
|
||||
dreamcompute
|
||||
------------
|
||||
|
||||
https://iad2.dream.io:5000
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
RegionOne Ashburn, VA
|
||||
============== ================
|
||||
|
||||
* Identity API Version is 3
|
||||
* Images must be in `raw` format
|
||||
* IPv6 is provided to every server
|
||||
|
||||
dreamhost
|
||||
---------
|
||||
|
||||
Deprecated, please use dreamcompute
|
||||
|
||||
https://keystone.dream.io/v2.0
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
RegionOne Ashburn, VA
|
||||
============== ================
|
||||
|
||||
* Images must be in `raw` format
|
||||
* Public IPv4 is provided via NAT with Neutron Floating IP
|
||||
* IPv6 is provided to every server
|
||||
|
||||
otc
|
||||
---
|
||||
|
||||
https://iam.%(region_name)s.otc.t-systems.com/v3
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
eu-de Germany
|
||||
============== ================
|
||||
|
||||
* Identity API Version is 3
|
||||
* Images must be in `vhd` format
|
||||
* Public IPv4 is provided via NAT with Neutron Floating IP
|
||||
|
||||
elastx
|
||||
------
|
||||
|
||||
https://ops.elastx.net:5000/v2.0
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
regionOne Stockholm, SE
|
||||
============== ================
|
||||
|
||||
* Public IPv4 is provided via NAT with Neutron Floating IP
|
||||
|
||||
entercloudsuite
|
||||
---------------
|
||||
|
||||
https://api.entercloudsuite.com/v2.0
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
nl-ams1 Amsterdam, NL
|
||||
it-mil1 Milan, IT
|
||||
de-fra1 Frankfurt, DE
|
||||
============== ================
|
||||
|
||||
* Image API Version is 1
|
||||
* Volume API Version is 1
|
||||
|
||||
fuga
|
||||
----
|
||||
|
||||
https://identity.api.fuga.io:5000
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
cystack Netherlands
|
||||
============== ================
|
||||
|
||||
* Identity API Version is 3
|
||||
* Volume API Version is 3
|
||||
|
||||
internap
|
||||
--------
|
||||
|
||||
https://identity.api.cloud.iweb.com/v2.0
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
ams01 Amsterdam, NL
|
||||
da01 Dallas, TX
|
||||
nyj01 New York, NY
|
||||
sin01 Singapore
|
||||
sjc01 San Jose, CA
|
||||
============== ================
|
||||
|
||||
* Floating IPs are not supported
|
||||
|
||||
limestonenetworks
|
||||
-----------------
|
||||
|
||||
https://auth.cloud.lstn.net:5000/v3
|
||||
|
||||
============== ==================
|
||||
Region Name Location
|
||||
============== ==================
|
||||
us-dfw-1 Dallas, TX
|
||||
us-slc Salt Lake City, UT
|
||||
============== ==================
|
||||
|
||||
* Identity API Version is 3
|
||||
* Images must be in `raw` format
|
||||
* IPv6 is provided to every server connected to the `Public Internet` network
|
||||
|
||||
ovh
|
||||
---
|
||||
|
||||
https://auth.cloud.ovh.net/v2.0
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
BHS1 Beauharnois, QC
|
||||
SBG1 Strassbourg, FR
|
||||
GRA1 Gravelines, FR
|
||||
============== ================
|
||||
|
||||
* Images may be in `raw` format. The `qcow2` default is also supported
|
||||
* Floating IPs are not supported
|
||||
|
||||
rackspace
|
||||
---------
|
||||
|
||||
https://identity.api.rackspacecloud.com/v2.0/
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
DFW Dallas, TX
|
||||
HKG Hong Kong
|
||||
IAD Washington, D.C.
|
||||
LON London, UK
|
||||
ORD Chicago, IL
|
||||
SYD Sydney, NSW
|
||||
============== ================
|
||||
|
||||
* Database Service Type is `rax:database`
|
||||
* Compute Service Name is `cloudServersOpenStack`
|
||||
* Images must be in `vhd` format
|
||||
* Images must be uploaded using the Glance Task Interface
|
||||
* Floating IPs are not supported
|
||||
* Public IPv4 is directly routable via static config by Nova
|
||||
* IPv6 is provided to every server
|
||||
* Security groups are not supported
|
||||
* Uploaded Images need properties to not use vendor agent::
|
||||
:vm_mode: hvm
|
||||
:xenapi_use_agent: False
|
||||
* Volume API Version is 1
|
||||
* While passwords are recommended for use, API keys do work as well.
|
||||
The `rackspaceauth` python package must be installed, and then the following
|
||||
can be added to clouds.yaml::
|
||||
|
||||
auth:
|
||||
username: myusername
|
||||
api_key: myapikey
|
||||
auth_type: rackspace_apikey
|
||||
|
||||
switchengines
|
||||
-------------
|
||||
|
||||
https://keystone.cloud.switch.ch:5000/v2.0
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
LS Lausanne, CH
|
||||
ZH Zurich, CH
|
||||
============== ================
|
||||
|
||||
* Images must be in `raw` format
|
||||
* Images must be uploaded using the Glance Task Interface
|
||||
* Volume API Version is 1
|
||||
|
||||
ultimum
|
||||
-------
|
||||
|
||||
https://console.ultimum-cloud.com:5000/v2.0
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
RegionOne Prague, CZ
|
||||
============== ================
|
||||
|
||||
* Volume API Version is 1
|
||||
|
||||
unitedstack
|
||||
-----------
|
||||
|
||||
https://identity.api.ustack.com/v3
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
bj1 Beijing, CN
|
||||
gd1 Guangdong, CN
|
||||
============== ================
|
||||
|
||||
* Identity API Version is 3
|
||||
* Images must be in `raw` format
|
||||
* Volume API Version is 1
|
||||
|
||||
vexxhost
|
||||
--------
|
||||
|
||||
http://auth.vexxhost.net
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
ca-ymq-1 Montreal, QC
|
||||
============== ================
|
||||
|
||||
* DNS API Version is 1
|
||||
* Identity API Version is 3
|
||||
|
||||
zetta
|
||||
-----
|
||||
|
||||
https://identity.api.zetta.io/v3
|
||||
|
||||
============== ================
|
||||
Region Name Location
|
||||
============== ================
|
||||
no-osl1 Oslo, NO
|
||||
============== ================
|
||||
|
||||
* DNS API Version is 2
|
||||
* Identity API Version is 3
|
||||
Please see
|
||||
https://docs.openstack.org/openstacksdk/latest/user/vendor-support.html
|
||||
|
@ -25,6 +25,7 @@ monotonic==0.6
|
||||
mox3==0.20.0
|
||||
netaddr==0.7.18
|
||||
netifaces==0.10.4
|
||||
openstacksdk==0.13.0
|
||||
oslo.i18n==3.15.3
|
||||
oslo.utils==3.33.0
|
||||
oslotest==3.2.0
|
||||
|
@ -1,28 +0,0 @@
|
||||
# Copyright (c) 2015 IBM Corp.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
class NullHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
pass
|
||||
|
||||
|
||||
def setup_logging(name):
|
||||
log = logging.getLogger(name)
|
||||
if len(log.handlers) == 0:
|
||||
h = NullHandler()
|
||||
log.addHandler(h)
|
||||
return log
|
@ -13,16 +13,11 @@
|
||||
# under the License.
|
||||
|
||||
import importlib
|
||||
import math
|
||||
import warnings
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
import keystoneauth1.exceptions.catalog
|
||||
from keystoneauth1 import session
|
||||
import requestsexceptions
|
||||
from openstack import _log
|
||||
from openstack.config import cloud_region
|
||||
|
||||
import os_client_config
|
||||
from os_client_config import _log
|
||||
from os_client_config import constructors
|
||||
from os_client_config import exceptions
|
||||
|
||||
@ -61,30 +56,10 @@ def _get_client(service_key):
|
||||
return ctr
|
||||
|
||||
|
||||
def _make_key(key, service_type):
|
||||
if not service_type:
|
||||
return key
|
||||
else:
|
||||
service_type = service_type.lower().replace('-', '_')
|
||||
return "_".join([service_type, key])
|
||||
|
||||
|
||||
class CloudConfig(object):
|
||||
def __init__(self, name, region, config,
|
||||
force_ipv4=False, auth_plugin=None,
|
||||
openstack_config=None, session_constructor=None,
|
||||
app_name=None, app_version=None):
|
||||
self.name = name
|
||||
self.region = region
|
||||
self.config = config
|
||||
class CloudConfig(cloud_region.CloudRegion):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CloudConfig, self).__init__(*args, **kwargs)
|
||||
self.log = _log.setup_logging(__name__)
|
||||
self._force_ipv4 = force_ipv4
|
||||
self._auth = auth_plugin
|
||||
self._openstack_config = openstack_config
|
||||
self._keystone_session = None
|
||||
self._session_constructor = session_constructor or session.Session
|
||||
self._app_name = app_name
|
||||
self._app_version = app_version
|
||||
|
||||
def __getattr__(self, key):
|
||||
"""Return arbitrary attributes."""
|
||||
@ -97,253 +72,20 @@ class CloudConfig(object):
|
||||
else:
|
||||
return None
|
||||
|
||||
def __iter__(self):
|
||||
return self.config.__iter__()
|
||||
|
||||
def __eq__(self, other):
|
||||
return (self.name == other.name and self.region == other.region
|
||||
and self.config == other.config)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def set_session_constructor(self, session_constructor):
|
||||
"""Sets the Session constructor."""
|
||||
self._session_constructor = session_constructor
|
||||
|
||||
def get_requests_verify_args(self):
|
||||
"""Return the verify and cert values for the requests library."""
|
||||
if self.config['verify'] and self.config['cacert']:
|
||||
verify = self.config['cacert']
|
||||
else:
|
||||
verify = self.config['verify']
|
||||
if self.config['cacert']:
|
||||
warnings.warn(
|
||||
"You are specifying a cacert for the cloud {0} but "
|
||||
"also to ignore the host verification. The host SSL cert "
|
||||
"will not be verified.".format(self.name))
|
||||
|
||||
cert = self.config.get('cert', None)
|
||||
if cert:
|
||||
if self.config['key']:
|
||||
cert = (cert, self.config['key'])
|
||||
return (verify, cert)
|
||||
|
||||
def get_services(self):
|
||||
"""Return a list of service types we know something about."""
|
||||
services = []
|
||||
for key, val in self.config.items():
|
||||
if (key.endswith('api_version')
|
||||
or key.endswith('service_type')
|
||||
or key.endswith('service_name')):
|
||||
services.append("_".join(key.split('_')[:-2]))
|
||||
return list(set(services))
|
||||
|
||||
def get_auth_args(self):
|
||||
return self.config['auth']
|
||||
|
||||
def get_interface(self, service_type=None):
|
||||
key = _make_key('interface', service_type)
|
||||
interface = self.config.get('interface')
|
||||
return self.config.get(key, interface)
|
||||
|
||||
def get_region_name(self, service_type=None):
|
||||
if not service_type:
|
||||
return self.region
|
||||
key = _make_key('region_name', service_type)
|
||||
return self.config.get(key, self.region)
|
||||
|
||||
def get_api_version(self, service_type):
|
||||
key = _make_key('api_version', service_type)
|
||||
return self.config.get(key, None)
|
||||
|
||||
def get_service_type(self, service_type):
|
||||
key = _make_key('service_type', service_type)
|
||||
# Cinder did an evil thing where they defined a second service
|
||||
# type in the catalog. Of course, that's insane, so let's hide this
|
||||
# atrocity from the as-yet-unsullied eyes of our users.
|
||||
# Of course, if the user requests a volumev2, that structure should
|
||||
# still work.
|
||||
# What's even more amazing is that they did it AGAIN with cinder v3
|
||||
# And then I learned that mistral copied it.
|
||||
if service_type == 'volume':
|
||||
vol_type = self.get_api_version(service_type)
|
||||
if vol_type and vol_type.startswith('2'):
|
||||
service_type = 'volumev2'
|
||||
elif vol_type and vol_type.startswith('3'):
|
||||
service_type = 'volumev3'
|
||||
elif service_type == 'workflow':
|
||||
wk_type = self.get_api_version(service_type)
|
||||
if wk_type and wk_type.startswith('2'):
|
||||
service_type = 'workflowv2'
|
||||
return self.config.get(key, service_type)
|
||||
|
||||
def get_service_name(self, service_type):
|
||||
key = _make_key('service_name', service_type)
|
||||
return self.config.get(key, None)
|
||||
|
||||
def get_endpoint(self, service_type):
|
||||
key = _make_key('endpoint_override', service_type)
|
||||
old_key = _make_key('endpoint', service_type)
|
||||
return self.config.get(key, self.config.get(old_key, None))
|
||||
def insert_user_agent(self):
|
||||
self._keystone_session.additional_user_agent.append(
|
||||
('os-client-config', os_client_config.__version__))
|
||||
super(CloudConfig, self).insert_user_agent()
|
||||
|
||||
@property
|
||||
def prefer_ipv6(self):
|
||||
return not self._force_ipv4
|
||||
def region(self):
|
||||
return self.region_name
|
||||
|
||||
@property
|
||||
def force_ipv4(self):
|
||||
return self._force_ipv4
|
||||
def get_region_name(self, *args):
|
||||
return self.region_name
|
||||
|
||||
def get_auth(self):
|
||||
"""Return a keystoneauth plugin from the auth credentials."""
|
||||
return self._auth
|
||||
|
||||
def get_session(self):
|
||||
"""Return a keystoneauth session based on the auth credentials."""
|
||||
if self._keystone_session is None:
|
||||
if not self._auth:
|
||||
raise exceptions.OpenStackConfigException(
|
||||
"Problem with auth parameters")
|
||||
(verify, cert) = self.get_requests_verify_args()
|
||||
# Turn off urllib3 warnings about insecure certs if we have
|
||||
# explicitly configured requests to tell it we do not want
|
||||
# cert verification
|
||||
if not verify:
|
||||
self.log.debug(
|
||||
"Turning off SSL warnings for {cloud}:{region}"
|
||||
" since verify=False".format(
|
||||
cloud=self.name, region=self.region))
|
||||
requestsexceptions.squelch_warnings(insecure_requests=not verify)
|
||||
self._keystone_session = self._session_constructor(
|
||||
auth=self._auth,
|
||||
verify=verify,
|
||||
cert=cert,
|
||||
timeout=self.config['api_timeout'])
|
||||
if hasattr(self._keystone_session, 'additional_user_agent'):
|
||||
self._keystone_session.additional_user_agent.append(
|
||||
('os-client-config', os_client_config.__version__))
|
||||
# Using old keystoneauth with new os-client-config fails if
|
||||
# we pass in app_name and app_version. Those are not essential,
|
||||
# nor a reason to bump our minimum, so just test for the session
|
||||
# having the attribute post creation and set them then.
|
||||
if hasattr(self._keystone_session, 'app_name'):
|
||||
self._keystone_session.app_name = self._app_name
|
||||
if hasattr(self._keystone_session, 'app_version'):
|
||||
self._keystone_session.app_version = self._app_version
|
||||
return self._keystone_session
|
||||
|
||||
def get_service_catalog(self):
|
||||
"""Helper method to grab the service catalog."""
|
||||
return self._auth.get_access(self.get_session()).service_catalog
|
||||
|
||||
def _get_version_args(self, service_key, version):
|
||||
"""Translate OCC version args to those needed by ksa adapter.
|
||||
|
||||
If no version is requested explicitly and we have a configured version,
|
||||
set the version parameter and let ksa deal with expanding that to
|
||||
min=ver.0, max=ver.latest.
|
||||
|
||||
If version is set, pass it through.
|
||||
|
||||
If version is not set and we don't have a configured version, default
|
||||
to latest.
|
||||
"""
|
||||
if version == 'latest':
|
||||
return None, None, 'latest'
|
||||
if not version:
|
||||
version = self.get_api_version(service_key)
|
||||
if not version:
|
||||
return None, None, 'latest'
|
||||
return version, None, None
|
||||
|
||||
def get_session_client(self, service_key, version=None):
|
||||
"""Return a prepped requests adapter for a given service.
|
||||
|
||||
This is useful for making direct requests calls against a
|
||||
'mounted' endpoint. That is, if you do:
|
||||
|
||||
client = get_session_client('compute')
|
||||
|
||||
then you can do:
|
||||
|
||||
client.get('/flavors')
|
||||
|
||||
and it will work like you think.
|
||||
"""
|
||||
(version, min_version, max_version) = self._get_version_args(
|
||||
service_key, version)
|
||||
|
||||
return adapter.Adapter(
|
||||
session=self.get_session(),
|
||||
service_type=self.get_service_type(service_key),
|
||||
service_name=self.get_service_name(service_key),
|
||||
interface=self.get_interface(service_key),
|
||||
version=version,
|
||||
min_version=min_version,
|
||||
max_version=max_version,
|
||||
region_name=self.region)
|
||||
|
||||
def _get_highest_endpoint(self, service_types, kwargs):
|
||||
session = self.get_session()
|
||||
for service_type in service_types:
|
||||
kwargs['service_type'] = service_type
|
||||
try:
|
||||
# Return the highest version we find that matches
|
||||
# the request
|
||||
return session.get_endpoint(**kwargs)
|
||||
except keystoneauth1.exceptions.catalog.EndpointNotFound:
|
||||
pass
|
||||
|
||||
def get_session_endpoint(
|
||||
self, service_key, min_version=None, max_version=None):
|
||||
"""Return the endpoint from config or the catalog.
|
||||
|
||||
If a configuration lists an explicit endpoint for a service,
|
||||
return that. Otherwise, fetch the service catalog from the
|
||||
keystone session and return the appropriate endpoint.
|
||||
|
||||
:param service_key: Generic key for service, such as 'compute' or
|
||||
'network'
|
||||
|
||||
"""
|
||||
|
||||
override_endpoint = self.get_endpoint(service_key)
|
||||
if override_endpoint:
|
||||
return override_endpoint
|
||||
endpoint = None
|
||||
kwargs = {
|
||||
'service_name': self.get_service_name(service_key),
|
||||
'region_name': self.region
|
||||
}
|
||||
kwargs['interface'] = self.get_interface(service_key)
|
||||
if service_key == 'volume' and not self.get_api_version('volume'):
|
||||
# If we don't have a configured cinder version, we can't know
|
||||
# to request a different service_type
|
||||
min_version = float(min_version or 1)
|
||||
max_version = float(max_version or 3)
|
||||
min_major = math.trunc(float(min_version))
|
||||
max_major = math.trunc(float(max_version))
|
||||
versions = range(int(max_major) + 1, int(min_major), -1)
|
||||
service_types = []
|
||||
for version in versions:
|
||||
if version == 1:
|
||||
service_types.append('volume')
|
||||
else:
|
||||
service_types.append('volumev{v}'.format(v=version))
|
||||
else:
|
||||
service_types = [self.get_service_type(service_key)]
|
||||
endpoint = self._get_highest_endpoint(service_types, kwargs)
|
||||
if not endpoint:
|
||||
self.log.warning(
|
||||
"Keystone catalog entry not found ("
|
||||
"service_type=%s,service_name=%s"
|
||||
"interface=%s,region_name=%s)",
|
||||
service_key,
|
||||
kwargs['service_name'],
|
||||
kwargs['interface'],
|
||||
kwargs['region_name'])
|
||||
return endpoint
|
||||
def get_cache_expiration(self):
|
||||
return self.get_cache_expirations()
|
||||
|
||||
def get_legacy_client(
|
||||
self, service_key, client_class=None, interface_key=None,
|
||||
@ -486,107 +228,3 @@ class CloudConfig(object):
|
||||
constructor_kwargs[interface_key] = interface
|
||||
|
||||
return client_class(**constructor_kwargs)
|
||||
|
||||
def get_cache_expiration_time(self):
|
||||
if self._openstack_config:
|
||||
return self._openstack_config.get_cache_expiration_time()
|
||||
|
||||
def get_cache_path(self):
|
||||
if self._openstack_config:
|
||||
return self._openstack_config.get_cache_path()
|
||||
|
||||
def get_cache_class(self):
|
||||
if self._openstack_config:
|
||||
return self._openstack_config.get_cache_class()
|
||||
|
||||
def get_cache_arguments(self):
|
||||
if self._openstack_config:
|
||||
return self._openstack_config.get_cache_arguments()
|
||||
|
||||
def get_cache_expiration(self):
|
||||
if self._openstack_config:
|
||||
return self._openstack_config.get_cache_expiration()
|
||||
|
||||
def get_cache_resource_expiration(self, resource, default=None):
|
||||
"""Get expiration time for a resource
|
||||
|
||||
:param resource: Name of the resource type
|
||||
:param default: Default value to return if not found (optional,
|
||||
defaults to None)
|
||||
|
||||
:returns: Expiration time for the resource type as float or default
|
||||
"""
|
||||
if self._openstack_config:
|
||||
expiration = self._openstack_config.get_cache_expiration()
|
||||
if resource not in expiration:
|
||||
return default
|
||||
return float(expiration[resource])
|
||||
|
||||
def requires_floating_ip(self):
|
||||
"""Return whether or not this cloud requires floating ips.
|
||||
|
||||
|
||||
:returns: True of False if know, None if discovery is needed.
|
||||
If requires_floating_ip is not configured but the cloud is
|
||||
known to not provide floating ips, will return False.
|
||||
"""
|
||||
if self.config['floating_ip_source'] == "None":
|
||||
return False
|
||||
return self.config.get('requires_floating_ip')
|
||||
|
||||
def get_external_networks(self):
|
||||
"""Get list of network names for external networks."""
|
||||
return [
|
||||
net['name'] for net in self.config['networks']
|
||||
if net['routes_externally']]
|
||||
|
||||
def get_external_ipv4_networks(self):
|
||||
"""Get list of network names for external IPv4 networks."""
|
||||
return [
|
||||
net['name'] for net in self.config['networks']
|
||||
if net['routes_ipv4_externally']]
|
||||
|
||||
def get_external_ipv6_networks(self):
|
||||
"""Get list of network names for external IPv6 networks."""
|
||||
return [
|
||||
net['name'] for net in self.config['networks']
|
||||
if net['routes_ipv6_externally']]
|
||||
|
||||
def get_internal_networks(self):
|
||||
"""Get list of network names for internal networks."""
|
||||
return [
|
||||
net['name'] for net in self.config['networks']
|
||||
if not net['routes_externally']]
|
||||
|
||||
def get_internal_ipv4_networks(self):
|
||||
"""Get list of network names for internal IPv4 networks."""
|
||||
return [
|
||||
net['name'] for net in self.config['networks']
|
||||
if not net['routes_ipv4_externally']]
|
||||
|
||||
def get_internal_ipv6_networks(self):
|
||||
"""Get list of network names for internal IPv6 networks."""
|
||||
return [
|
||||
net['name'] for net in self.config['networks']
|
||||
if not net['routes_ipv6_externally']]
|
||||
|
||||
def get_default_network(self):
|
||||
"""Get network used for default interactions."""
|
||||
for net in self.config['networks']:
|
||||
if net['default_interface']:
|
||||
return net['name']
|
||||
return None
|
||||
|
||||
def get_nat_destination(self):
|
||||
"""Get network used for NAT destination."""
|
||||
for net in self.config['networks']:
|
||||
if net['nat_destination']:
|
||||
return net['name']
|
||||
return None
|
||||
|
||||
def get_nat_source(self):
|
||||
"""Get network used for NAT source."""
|
||||
for net in self.config['networks']:
|
||||
if net.get('nat_source'):
|
||||
return net['name']
|
||||
return None
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,41 +12,13 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
|
||||
from openstack.config import defaults
|
||||
|
||||
_json_path = os.path.join(
|
||||
os.path.dirname(os.path.realpath(__file__)), 'defaults.json')
|
||||
_defaults = None
|
||||
_defaults_lock = threading.Lock()
|
||||
|
||||
|
||||
def get_defaults():
|
||||
global _defaults
|
||||
if _defaults is not None:
|
||||
return _defaults.copy()
|
||||
with _defaults_lock:
|
||||
if _defaults is not None:
|
||||
# Did someone else just finish filling it?
|
||||
return _defaults.copy()
|
||||
# Python language specific defaults
|
||||
# These are defaults related to use of python libraries, they are
|
||||
# not qualities of a cloud.
|
||||
#
|
||||
# NOTE(harlowja): update a in-memory dict, before updating
|
||||
# the global one so that other callers of get_defaults do not
|
||||
# see the partially filled one.
|
||||
tmp_defaults = dict(
|
||||
api_timeout=None,
|
||||
verify=True,
|
||||
cacert=None,
|
||||
cert=None,
|
||||
key=None,
|
||||
)
|
||||
with open(_json_path, 'r') as json_file:
|
||||
updates = json.load(json_file)
|
||||
if updates is not None:
|
||||
tmp_defaults.update(updates)
|
||||
_defaults = tmp_defaults
|
||||
return tmp_defaults.copy()
|
||||
return defaults.get_defaults(json_path=_json_path)
|
||||
|
@ -12,9 +12,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack import exceptions
|
||||
|
||||
class OpenStackConfigException(Exception):
|
||||
"""Something went wrong with parsing your OpenStack Config."""
|
||||
OpenStackConfigException = exceptions.ConfigException
|
||||
|
||||
|
||||
class OpenStackConfigVersionException(OpenStackConfigException):
|
||||
|
@ -1,121 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "https://git.openstack.org/cgit/openstack/cloud-data/plain/schema.json#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auth_type": {
|
||||
"name": "Auth Type",
|
||||
"description": "Name of authentication plugin to be used",
|
||||
"default": "password",
|
||||
"type": "string"
|
||||
},
|
||||
"disable_vendor_agent": {
|
||||
"name": "Disable Vendor Agent Properties",
|
||||
"description": "Image properties required to disable vendor agent",
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
},
|
||||
"floating_ip_source": {
|
||||
"name": "Floating IP Source",
|
||||
"description": "Which service provides Floating IPs",
|
||||
"enum": [ "neutron", "nova", "None" ],
|
||||
"default": "neutron"
|
||||
},
|
||||
"image_api_use_tasks": {
|
||||
"name": "Image Task API",
|
||||
"description": "Does the cloud require the Image Task API",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"image_format": {
|
||||
"name": "Image Format",
|
||||
"description": "Format for uploaded Images",
|
||||
"default": "qcow2",
|
||||
"type": "string"
|
||||
},
|
||||
"interface": {
|
||||
"name": "API Interface",
|
||||
"description": "Which API Interface should connections hit",
|
||||
"default": "public",
|
||||
"enum": [ "public", "internal", "admin" ]
|
||||
},
|
||||
"secgroup_source": {
|
||||
"name": "Security Group Source",
|
||||
"description": "Which service provides security groups",
|
||||
"default": "neutron",
|
||||
"enum": [ "neutron", "nova", "None" ]
|
||||
},
|
||||
"baremetal_api_version": {
|
||||
"name": "Baremetal API Service Type",
|
||||
"description": "Baremetal API Service Type",
|
||||
"default": "1",
|
||||
"type": "string"
|
||||
},
|
||||
"compute_api_version": {
|
||||
"name": "Compute API Version",
|
||||
"description": "Compute API Version",
|
||||
"default": "2",
|
||||
"type": "string"
|
||||
},
|
||||
"database_api_version": {
|
||||
"name": "Database API Version",
|
||||
"description": "Database API Version",
|
||||
"default": "1.0",
|
||||
"type": "string"
|
||||
},
|
||||
"dns_api_version": {
|
||||
"name": "DNS API Version",
|
||||
"description": "DNS API Version",
|
||||
"default": "2",
|
||||
"type": "string"
|
||||
},
|
||||
"identity_api_version": {
|
||||
"name": "Identity API Version",
|
||||
"description": "Identity API Version",
|
||||
"default": "2",
|
||||
"type": "string"
|
||||
},
|
||||
"image_api_version": {
|
||||
"name": "Image API Version",
|
||||
"description": "Image API Version",
|
||||
"default": "1",
|
||||
"type": "string"
|
||||
},
|
||||
"network_api_version": {
|
||||
"name": "Network API Version",
|
||||
"description": "Network API Version",
|
||||
"default": "2",
|
||||
"type": "string"
|
||||
},
|
||||
"object_store_api_version": {
|
||||
"name": "Object Storage API Version",
|
||||
"description": "Object Storage API Version",
|
||||
"default": "1",
|
||||
"type": "string"
|
||||
},
|
||||
"volume_api_version": {
|
||||
"name": "Volume API Version",
|
||||
"description": "Volume API Version",
|
||||
"default": "2",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"auth_type",
|
||||
"baremetal_api_version",
|
||||
"compute_api_version",
|
||||
"database_api_version",
|
||||
"disable_vendor_agent",
|
||||
"dns_api_version",
|
||||
"floating_ip_source",
|
||||
"identity_api_version",
|
||||
"image_api_use_tasks",
|
||||
"image_api_version",
|
||||
"image_format",
|
||||
"interface",
|
||||
"network_api_version",
|
||||
"object_store_api_version",
|
||||
"secgroup_source",
|
||||
"volume_api_version"
|
||||
]
|
||||
}
|
@ -215,6 +215,8 @@ class TestCase(base.BaseTestCase):
|
||||
self.no_yaml = _write_yaml(NO_CONF)
|
||||
self.useFixture(fixtures.MonkeyPatch(
|
||||
'os_client_config.__version__', '1.2.3'))
|
||||
self.useFixture(fixtures.MonkeyPatch(
|
||||
'openstack.version.__version__', '3.4.5'))
|
||||
|
||||
# Isolate the test runs from the environment
|
||||
# Do this as two loops because you can't modify the dict in a loop
|
||||
|
@ -16,6 +16,8 @@ from keystoneauth1 import exceptions as ksa_exceptions
|
||||
from keystoneauth1 import session as ksa_session
|
||||
import mock
|
||||
|
||||
from openstack.config import cloud_region
|
||||
|
||||
from os_client_config import cloud_config
|
||||
from os_client_config import defaults
|
||||
from os_client_config import exceptions
|
||||
@ -26,7 +28,6 @@ fake_config_dict = {'a': 1, 'os_b': 2, 'c': 3, 'os_c': 4}
|
||||
fake_services_dict = {
|
||||
'compute_api_version': '2',
|
||||
'compute_endpoint_override': 'http://compute.example.com',
|
||||
'compute_region_name': 'region-bl',
|
||||
'telemetry_endpoint': 'http://telemetry.example.com',
|
||||
'interface': 'public',
|
||||
'image_service_type': 'mage',
|
||||
@ -45,14 +46,14 @@ class TestCloudConfig(base.TestCase):
|
||||
self.assertEqual("region-al", cc.region)
|
||||
|
||||
# Look up straight value
|
||||
self.assertEqual(1, cc.a)
|
||||
self.assertEqual('1', cc.a)
|
||||
|
||||
# Look up prefixed attribute, fail - returns None
|
||||
self.assertIsNone(cc.os_b)
|
||||
|
||||
# Look up straight value, then prefixed value
|
||||
self.assertEqual(3, cc.c)
|
||||
self.assertEqual(3, cc.os_c)
|
||||
self.assertEqual('3', cc.c)
|
||||
self.assertEqual('3', cc.os_c)
|
||||
|
||||
# Lookup mystery attribute
|
||||
self.assertIsNone(cc.x)
|
||||
@ -139,7 +140,6 @@ class TestCloudConfig(base.TestCase):
|
||||
self.assertEqual('admin', cc.get_interface('identity'))
|
||||
self.assertEqual('region-al', cc.get_region_name())
|
||||
self.assertEqual('region-al', cc.get_region_name('image'))
|
||||
self.assertEqual('region-bl', cc.get_region_name('compute'))
|
||||
self.assertIsNone(cc.get_api_version('image'))
|
||||
self.assertEqual('2', cc.get_api_version('compute'))
|
||||
self.assertEqual('mage', cc.get_service_type('image'))
|
||||
@ -194,10 +194,10 @@ class TestCloudConfig(base.TestCase):
|
||||
cc.get_session()
|
||||
mock_session.assert_called_with(
|
||||
auth=mock.ANY,
|
||||
verify=True, cert=None, timeout=None)
|
||||
verify=True, cert=None, timeout=None, discovery_cache=None)
|
||||
self.assertEqual(
|
||||
fake_session.additional_user_agent,
|
||||
[('os-client-config', '1.2.3')])
|
||||
[('os-client-config', '1.2.3'), ('openstacksdk', '3.4.5')],
|
||||
fake_session.additional_user_agent)
|
||||
|
||||
@mock.patch.object(ksa_session, 'Session')
|
||||
def test_get_session_with_app_name(self, mock_session):
|
||||
@ -214,12 +214,12 @@ class TestCloudConfig(base.TestCase):
|
||||
cc.get_session()
|
||||
mock_session.assert_called_with(
|
||||
auth=mock.ANY,
|
||||
verify=True, cert=None, timeout=None)
|
||||
verify=True, cert=None, timeout=None, discovery_cache=None)
|
||||
self.assertEqual(fake_session.app_name, "test_app")
|
||||
self.assertEqual(fake_session.app_version, "test_version")
|
||||
self.assertEqual(
|
||||
fake_session.additional_user_agent,
|
||||
[('os-client-config', '1.2.3')])
|
||||
[('os-client-config', '1.2.3'), ('openstacksdk', '3.4.5')],
|
||||
fake_session.additional_user_agent)
|
||||
|
||||
@mock.patch.object(ksa_session, 'Session')
|
||||
def test_get_session_with_timeout(self, mock_session):
|
||||
@ -234,10 +234,10 @@ class TestCloudConfig(base.TestCase):
|
||||
cc.get_session()
|
||||
mock_session.assert_called_with(
|
||||
auth=mock.ANY,
|
||||
verify=True, cert=None, timeout=9)
|
||||
verify=True, cert=None, timeout=9, discovery_cache=None)
|
||||
self.assertEqual(
|
||||
fake_session.additional_user_agent,
|
||||
[('os-client-config', '1.2.3')])
|
||||
[('os-client-config', '1.2.3'), ('openstacksdk', '3.4.5')],
|
||||
fake_session.additional_user_agent)
|
||||
|
||||
@mock.patch.object(ksa_session, 'Session')
|
||||
def test_override_session_endpoint_override(self, mock_session):
|
||||
@ -259,7 +259,7 @@ class TestCloudConfig(base.TestCase):
|
||||
cc.get_session_endpoint('telemetry'),
|
||||
fake_services_dict['telemetry_endpoint'])
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session')
|
||||
def test_session_endpoint(self, mock_get_session):
|
||||
mock_session = mock.Mock()
|
||||
mock_get_session.return_value = mock_session
|
||||
@ -274,7 +274,7 @@ class TestCloudConfig(base.TestCase):
|
||||
region_name='region-al',
|
||||
service_type='orchestration')
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session')
|
||||
def test_session_endpoint_not_found(self, mock_get_session):
|
||||
exc_to_raise = ksa_exceptions.catalog.EndpointNotFound
|
||||
mock_get_session.return_value.get_endpoint.side_effect = exc_to_raise
|
||||
@ -282,9 +282,9 @@ class TestCloudConfig(base.TestCase):
|
||||
"test1", "region-al", {}, auth_plugin=mock.Mock())
|
||||
self.assertIsNone(cc.get_session_endpoint('notfound'))
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_api_version')
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_auth_args')
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_api_version')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_auth_args')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_object_store_password(
|
||||
self,
|
||||
mock_get_session_endpoint,
|
||||
@ -313,8 +313,8 @@ class TestCloudConfig(base.TestCase):
|
||||
'endpoint_type': 'public',
|
||||
})
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_auth_args')
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_auth_args')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_object_store_password_v2(
|
||||
self, mock_get_session_endpoint, mock_get_auth_args):
|
||||
mock_client = mock.Mock()
|
||||
@ -339,8 +339,8 @@ class TestCloudConfig(base.TestCase):
|
||||
'endpoint_type': 'public',
|
||||
})
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_auth_args')
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_auth_args')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_object_store(
|
||||
self, mock_get_session_endpoint, mock_get_auth_args):
|
||||
mock_client = mock.Mock()
|
||||
@ -360,8 +360,8 @@ class TestCloudConfig(base.TestCase):
|
||||
'endpoint_type': 'public',
|
||||
})
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_auth_args')
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_auth_args')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_object_store_timeout(
|
||||
self, mock_get_session_endpoint, mock_get_auth_args):
|
||||
mock_client = mock.Mock()
|
||||
@ -371,7 +371,8 @@ class TestCloudConfig(base.TestCase):
|
||||
config_dict.update(fake_services_dict)
|
||||
config_dict['api_timeout'] = 9
|
||||
cc = cloud_config.CloudConfig(
|
||||
"test1", "region-al", config_dict, auth_plugin=mock.Mock())
|
||||
name="test1", region_name="region-al", config=config_dict,
|
||||
auth_plugin=mock.Mock())
|
||||
cc.get_legacy_client('object-store', mock_client)
|
||||
mock_client.assert_called_with(
|
||||
session=mock.ANY,
|
||||
@ -382,7 +383,7 @@ class TestCloudConfig(base.TestCase):
|
||||
'endpoint_type': 'public',
|
||||
})
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_auth_args')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_auth_args')
|
||||
def test_legacy_client_object_store_endpoint(
|
||||
self, mock_get_auth_args):
|
||||
mock_client = mock.Mock()
|
||||
@ -402,7 +403,7 @@ class TestCloudConfig(base.TestCase):
|
||||
'endpoint_type': 'public',
|
||||
})
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_image(self, mock_get_session_endpoint):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_session_endpoint.return_value = 'http://example.com/v2'
|
||||
@ -422,7 +423,7 @@ class TestCloudConfig(base.TestCase):
|
||||
service_type='mage'
|
||||
)
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_image_override(self, mock_get_session_endpoint):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_session_endpoint.return_value = 'http://example.com/v2'
|
||||
@ -443,7 +444,7 @@ class TestCloudConfig(base.TestCase):
|
||||
service_type='mage'
|
||||
)
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_image_versioned(self, mock_get_session_endpoint):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_session_endpoint.return_value = 'http://example.com/v2'
|
||||
@ -465,7 +466,7 @@ class TestCloudConfig(base.TestCase):
|
||||
service_type='mage'
|
||||
)
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_image_unversioned(self, mock_get_session_endpoint):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_session_endpoint.return_value = 'http://example.com/'
|
||||
@ -487,7 +488,7 @@ class TestCloudConfig(base.TestCase):
|
||||
service_type='mage'
|
||||
)
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_image_argument(self, mock_get_session_endpoint):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_session_endpoint.return_value = 'http://example.com/v3'
|
||||
@ -509,7 +510,7 @@ class TestCloudConfig(base.TestCase):
|
||||
service_type='mage'
|
||||
)
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_network(self, mock_get_session_endpoint):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_session_endpoint.return_value = 'http://example.com/v2'
|
||||
@ -527,7 +528,7 @@ class TestCloudConfig(base.TestCase):
|
||||
session=mock.ANY,
|
||||
service_name=None)
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_compute(self, mock_get_session_endpoint):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_session_endpoint.return_value = 'http://example.com/v2'
|
||||
@ -545,7 +546,7 @@ class TestCloudConfig(base.TestCase):
|
||||
session=mock.ANY,
|
||||
service_name=None)
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_identity(self, mock_get_session_endpoint):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_session_endpoint.return_value = 'http://example.com/v2'
|
||||
@ -564,7 +565,7 @@ class TestCloudConfig(base.TestCase):
|
||||
session=mock.ANY,
|
||||
service_name='locks')
|
||||
|
||||
@mock.patch.object(cloud_config.CloudConfig, 'get_session_endpoint')
|
||||
@mock.patch.object(cloud_region.CloudRegion, 'get_session_endpoint')
|
||||
def test_legacy_client_identity_v3(self, mock_get_session_endpoint):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_session_endpoint.return_value = 'http://example.com'
|
||||
|
@ -21,9 +21,10 @@ import fixtures
|
||||
import testtools
|
||||
import yaml
|
||||
|
||||
from openstack.config import defaults
|
||||
|
||||
from os_client_config import cloud_config
|
||||
from os_client_config import config
|
||||
from os_client_config import defaults
|
||||
from os_client_config import exceptions
|
||||
from os_client_config.tests import base
|
||||
|
||||
@ -967,13 +968,6 @@ class TestConfigDefault(base.TestCase):
|
||||
self._assert_cloud_details(cc)
|
||||
self.assertEqual('password', cc.auth_type)
|
||||
|
||||
def test_set_default_before_init(self):
|
||||
config.set_default('identity_api_version', '4')
|
||||
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
|
||||
vendor_files=[self.vendor_yaml])
|
||||
cc = c.get_one_cloud(cloud='_test-cloud_', argparse=None)
|
||||
self.assertEqual('4', cc.identity_api_version)
|
||||
|
||||
|
||||
class TestBackwardsCompatibility(base.TestCase):
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
|
||||
import jsonschema
|
||||
from testtools import content
|
||||
|
||||
from os_client_config import defaults
|
||||
from os_client_config.tests import base
|
||||
|
||||
|
||||
class TestConfig(base.TestCase):
|
||||
|
||||
def json_diagnostics(self, exc_info):
|
||||
self.addDetail('filename', content.text_content(self.filename))
|
||||
for error in sorted(self.validator.iter_errors(self.json_data)):
|
||||
self.addDetail('jsonschema', content.text_content(str(error)))
|
||||
|
||||
def test_defaults_valid_json(self):
|
||||
_schema_path = os.path.join(
|
||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
||||
'schema.json')
|
||||
schema = json.load(open(_schema_path, 'r'))
|
||||
self.validator = jsonschema.Draft4Validator(schema)
|
||||
self.addOnException(self.json_diagnostics)
|
||||
|
||||
self.filename = os.path.join(
|
||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
||||
'defaults.json')
|
||||
self.json_data = json.load(open(self.filename, 'r'))
|
||||
|
||||
self.assertTrue(self.validator.is_valid(self.json_data))
|
||||
|
||||
def test_vendors_valid_json(self):
|
||||
_schema_path = os.path.join(
|
||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
||||
'vendor-schema.json')
|
||||
schema = json.load(open(_schema_path, 'r'))
|
||||
self.validator = jsonschema.Draft4Validator(schema)
|
||||
self.addOnException(self.json_diagnostics)
|
||||
|
||||
_vendors_path = os.path.join(
|
||||
os.path.dirname(os.path.realpath(defaults.__file__)),
|
||||
'vendors')
|
||||
for self.filename in glob.glob(os.path.join(_vendors_path, '*.json')):
|
||||
self.json_data = json.load(open(self.filename, 'r'))
|
||||
|
||||
self.assertTrue(self.validator.is_valid(self.json_data))
|
@ -1,223 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "https://git.openstack.org/cgit/openstack/cloud-data/plain/vendor-schema.json#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"profile": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auth": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auth_url": {
|
||||
"name": "Auth URL",
|
||||
"description": "URL of the primary Keystone endpoint",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth_type": {
|
||||
"name": "Auth Type",
|
||||
"description": "Name of authentication plugin to be used",
|
||||
"default": "password",
|
||||
"type": "string"
|
||||
},
|
||||
"disable_vendor_agent": {
|
||||
"name": "Disable Vendor Agent Properties",
|
||||
"description": "Image properties required to disable vendor agent",
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
},
|
||||
"floating_ip_source": {
|
||||
"name": "Floating IP Source",
|
||||
"description": "Which service provides Floating IPs",
|
||||
"enum": [ "neutron", "nova", "None" ],
|
||||
"default": "neutron"
|
||||
},
|
||||
"image_api_use_tasks": {
|
||||
"name": "Image Task API",
|
||||
"description": "Does the cloud require the Image Task API",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"image_format": {
|
||||
"name": "Image Format",
|
||||
"description": "Format for uploaded Images",
|
||||
"default": "qcow2",
|
||||
"type": "string"
|
||||
},
|
||||
"interface": {
|
||||
"name": "API Interface",
|
||||
"description": "Which API Interface should connections hit",
|
||||
"default": "public",
|
||||
"enum": [ "public", "internal", "admin" ]
|
||||
},
|
||||
"message": {
|
||||
"name": "Status message",
|
||||
"description": "Optional message with information related to status",
|
||||
"type": "string"
|
||||
},
|
||||
"requires_floating_ip": {
|
||||
"name": "Requires Floating IP",
|
||||
"description": "Whether the cloud requires a floating IP to route traffic off of the cloud",
|
||||
"default": null,
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"secgroup_source": {
|
||||
"name": "Security Group Source",
|
||||
"description": "Which service provides security groups",
|
||||
"enum": [ "neutron", "nova", "None" ],
|
||||
"default": "neutron"
|
||||
},
|
||||
"status": {
|
||||
"name": "Vendor status",
|
||||
"description": "Status of the vendor's cloud",
|
||||
"enum": [ "active", "deprecated", "shutdown"],
|
||||
"default": "active"
|
||||
},
|
||||
"compute_service_name": {
|
||||
"name": "Compute API Service Name",
|
||||
"description": "Compute API Service Name",
|
||||
"type": "string"
|
||||
},
|
||||
"database_service_name": {
|
||||
"name": "Database API Service Name",
|
||||
"description": "Database API Service Name",
|
||||
"type": "string"
|
||||
},
|
||||
"dns_service_name": {
|
||||
"name": "DNS API Service Name",
|
||||
"description": "DNS API Service Name",
|
||||
"type": "string"
|
||||
},
|
||||
"identity_service_name": {
|
||||
"name": "Identity API Service Name",
|
||||
"description": "Identity API Service Name",
|
||||
"type": "string"
|
||||
},
|
||||
"image_service_name": {
|
||||
"name": "Image API Service Name",
|
||||
"description": "Image API Service Name",
|
||||
"type": "string"
|
||||
},
|
||||
"volume_service_name": {
|
||||
"name": "Volume API Service Name",
|
||||
"description": "Volume API Service Name",
|
||||
"type": "string"
|
||||
},
|
||||
"network_service_name": {
|
||||
"name": "Network API Service Name",
|
||||
"description": "Network API Service Name",
|
||||
"type": "string"
|
||||
},
|
||||
"object_service_name": {
|
||||
"name": "Object Storage API Service Name",
|
||||
"description": "Object Storage API Service Name",
|
||||
"type": "string"
|
||||
},
|
||||
"baremetal_service_name": {
|
||||
"name": "Baremetal API Service Name",
|
||||
"description": "Baremetal API Service Name",
|
||||
"type": "string"
|
||||
},
|
||||
"compute_service_type": {
|
||||
"name": "Compute API Service Type",
|
||||
"description": "Compute API Service Type",
|
||||
"type": "string"
|
||||
},
|
||||
"database_service_type": {
|
||||
"name": "Database API Service Type",
|
||||
"description": "Database API Service Type",
|
||||
"type": "string"
|
||||
},
|
||||
"dns_service_type": {
|
||||
"name": "DNS API Service Type",
|
||||
"description": "DNS API Service Type",
|
||||
"type": "string"
|
||||
},
|
||||
"identity_service_type": {
|
||||
"name": "Identity API Service Type",
|
||||
"description": "Identity API Service Type",
|
||||
"type": "string"
|
||||
},
|
||||
"image_service_type": {
|
||||
"name": "Image API Service Type",
|
||||
"description": "Image API Service Type",
|
||||
"type": "string"
|
||||
},
|
||||
"volume_service_type": {
|
||||
"name": "Volume API Service Type",
|
||||
"description": "Volume API Service Type",
|
||||
"type": "string"
|
||||
},
|
||||
"network_service_type": {
|
||||
"name": "Network API Service Type",
|
||||
"description": "Network API Service Type",
|
||||
"type": "string"
|
||||
},
|
||||
"object_service_type": {
|
||||
"name": "Object Storage API Service Type",
|
||||
"description": "Object Storage API Service Type",
|
||||
"type": "string"
|
||||
},
|
||||
"baremetal_service_type": {
|
||||
"name": "Baremetal API Service Type",
|
||||
"description": "Baremetal API Service Type",
|
||||
"type": "string"
|
||||
},
|
||||
"compute_api_version": {
|
||||
"name": "Compute API Version",
|
||||
"description": "Compute API Version",
|
||||
"type": "string"
|
||||
},
|
||||
"database_api_version": {
|
||||
"name": "Database API Version",
|
||||
"description": "Database API Version",
|
||||
"type": "string"
|
||||
},
|
||||
"dns_api_version": {
|
||||
"name": "DNS API Version",
|
||||
"description": "DNS API Version",
|
||||
"type": "string"
|
||||
},
|
||||
"identity_api_version": {
|
||||
"name": "Identity API Version",
|
||||
"description": "Identity API Version",
|
||||
"type": "string"
|
||||
},
|
||||
"image_api_version": {
|
||||
"name": "Image API Version",
|
||||
"description": "Image API Version",
|
||||
"type": "string"
|
||||
},
|
||||
"volume_api_version": {
|
||||
"name": "Volume API Version",
|
||||
"description": "Volume API Version",
|
||||
"type": "string"
|
||||
},
|
||||
"network_api_version": {
|
||||
"name": "Network API Version",
|
||||
"description": "Network API Version",
|
||||
"type": "string"
|
||||
},
|
||||
"object_api_version": {
|
||||
"name": "Object Storage API Version",
|
||||
"description": "Object Storage API Version",
|
||||
"type": "string"
|
||||
},
|
||||
"baremetal_api_version": {
|
||||
"name": "Baremetal API Version",
|
||||
"description": "Baremetal API Version",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"profile"
|
||||
]
|
||||
}
|
24
os_client_config/vendors/__init__.py
vendored
24
os_client_config/vendors/__init__.py
vendored
@ -12,26 +12,4 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
|
||||
import yaml
|
||||
|
||||
_vendors_path = os.path.dirname(os.path.realpath(__file__))
|
||||
_vendor_defaults = None
|
||||
|
||||
|
||||
def get_profile(profile_name):
|
||||
global _vendor_defaults
|
||||
if _vendor_defaults is None:
|
||||
_vendor_defaults = {}
|
||||
for vendor in glob.glob(os.path.join(_vendors_path, '*.yaml')):
|
||||
with open(vendor, 'r') as f:
|
||||
vendor_data = yaml.safe_load(f)
|
||||
_vendor_defaults[vendor_data['name']] = vendor_data['profile']
|
||||
for vendor in glob.glob(os.path.join(_vendors_path, '*.json')):
|
||||
with open(vendor, 'r') as f:
|
||||
vendor_data = json.load(f)
|
||||
_vendor_defaults[vendor_data['name']] = vendor_data['profile']
|
||||
return _vendor_defaults.get(profile_name)
|
||||
from openstack.config.vendors import get_profile # noqa
|
||||
|
11
os_client_config/vendors/auro.json
vendored
11
os_client_config/vendors/auro.json
vendored
@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "auro",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://api.van1.auro.io:5000/v2.0"
|
||||
},
|
||||
"identity_api_version": "2",
|
||||
"region_name": "van1",
|
||||
"requires_floating_ip": true
|
||||
}
|
||||
}
|
14
os_client_config/vendors/betacloud.json
vendored
14
os_client_config/vendors/betacloud.json
vendored
@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "betacloud",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://api-1.betacloud.io:5000/v3"
|
||||
},
|
||||
"regions": [
|
||||
"betacloud-1"
|
||||
],
|
||||
"identity_api_version": "3",
|
||||
"image_format": "raw",
|
||||
"volume_api_version": "3"
|
||||
}
|
||||
}
|
7
os_client_config/vendors/bluebox.json
vendored
7
os_client_config/vendors/bluebox.json
vendored
@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "bluebox",
|
||||
"profile": {
|
||||
"volume_api_version": "1",
|
||||
"region_name": "RegionOne"
|
||||
}
|
||||
}
|
15
os_client_config/vendors/catalyst.json
vendored
15
os_client_config/vendors/catalyst.json
vendored
@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "catalyst",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://api.cloud.catalyst.net.nz:5000/v2.0"
|
||||
},
|
||||
"regions": [
|
||||
"nz-por-1",
|
||||
"nz_wlg_2"
|
||||
],
|
||||
"image_api_version": "1",
|
||||
"volume_api_version": "1",
|
||||
"image_format": "raw"
|
||||
}
|
||||
}
|
19
os_client_config/vendors/citycloud.json
vendored
19
os_client_config/vendors/citycloud.json
vendored
@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "citycloud",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://identity1.citycloud.com:5000/v3/"
|
||||
},
|
||||
"regions": [
|
||||
"Buf1",
|
||||
"La1",
|
||||
"Fra1",
|
||||
"Lon1",
|
||||
"Sto2",
|
||||
"Kna1"
|
||||
],
|
||||
"requires_floating_ip": true,
|
||||
"volume_api_version": "1",
|
||||
"identity_api_version": "3"
|
||||
}
|
||||
}
|
14
os_client_config/vendors/conoha.json
vendored
14
os_client_config/vendors/conoha.json
vendored
@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "conoha",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://identity.{region_name}.conoha.io"
|
||||
},
|
||||
"regions": [
|
||||
"sin1",
|
||||
"sjc1",
|
||||
"tyo1"
|
||||
],
|
||||
"identity_api_version": "2"
|
||||
}
|
||||
}
|
11
os_client_config/vendors/dreamcompute.json
vendored
11
os_client_config/vendors/dreamcompute.json
vendored
@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "dreamcompute",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://iad2.dream.io:5000"
|
||||
},
|
||||
"identity_api_version": "3",
|
||||
"region_name": "RegionOne",
|
||||
"image_format": "raw"
|
||||
}
|
||||
}
|
13
os_client_config/vendors/dreamhost.json
vendored
13
os_client_config/vendors/dreamhost.json
vendored
@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "dreamhost",
|
||||
"profile": {
|
||||
"status": "deprecated",
|
||||
"message": "The dreamhost profile is deprecated. Please use the dreamcompute profile instead",
|
||||
"auth": {
|
||||
"auth_url": "https://keystone.dream.io"
|
||||
},
|
||||
"identity_api_version": "3",
|
||||
"region_name": "RegionOne",
|
||||
"image_format": "raw"
|
||||
}
|
||||
}
|
10
os_client_config/vendors/elastx.json
vendored
10
os_client_config/vendors/elastx.json
vendored
@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "elastx",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://ops.elastx.net:5000"
|
||||
},
|
||||
"identity_api_version": "3",
|
||||
"region_name": "regionOne"
|
||||
}
|
||||
}
|
16
os_client_config/vendors/entercloudsuite.json
vendored
16
os_client_config/vendors/entercloudsuite.json
vendored
@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "entercloudsuite",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://api.entercloudsuite.com/"
|
||||
},
|
||||
"identity_api_version": "3",
|
||||
"image_api_version": "1",
|
||||
"volume_api_version": "1",
|
||||
"regions": [
|
||||
"it-mil1",
|
||||
"nl-ams1",
|
||||
"de-fra1"
|
||||
]
|
||||
}
|
||||
}
|
15
os_client_config/vendors/fuga.json
vendored
15
os_client_config/vendors/fuga.json
vendored
@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "fuga",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://identity.api.fuga.io:5000",
|
||||
"user_domain_name": "Default",
|
||||
"project_domain_name": "Default"
|
||||
},
|
||||
"regions": [
|
||||
"cystack"
|
||||
],
|
||||
"identity_api_version": "3",
|
||||
"volume_api_version": "3"
|
||||
}
|
||||
}
|
13
os_client_config/vendors/ibmcloud.json
vendored
13
os_client_config/vendors/ibmcloud.json
vendored
@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "ibmcloud",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://identity.open.softlayer.com"
|
||||
},
|
||||
"volume_api_version": "2",
|
||||
"identity_api_version": "3",
|
||||
"regions": [
|
||||
"london"
|
||||
]
|
||||
}
|
||||
}
|
17
os_client_config/vendors/internap.json
vendored
17
os_client_config/vendors/internap.json
vendored
@ -1,17 +0,0 @@
|
||||
{
|
||||
"name": "internap",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://identity.api.cloud.iweb.com"
|
||||
},
|
||||
"regions": [
|
||||
"ams01",
|
||||
"da01",
|
||||
"nyj01",
|
||||
"sin01",
|
||||
"sjc01"
|
||||
],
|
||||
"identity_api_version": "3",
|
||||
"floating_ip_source": "None"
|
||||
}
|
||||
}
|
13
os_client_config/vendors/otc.json
vendored
13
os_client_config/vendors/otc.json
vendored
@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "otc",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://iam.%(region_name)s.otc.t-systems.com/v3"
|
||||
},
|
||||
"regions": [
|
||||
"eu-de"
|
||||
],
|
||||
"identity_api_version": "3",
|
||||
"image_format": "vhd"
|
||||
}
|
||||
}
|
15
os_client_config/vendors/ovh.json
vendored
15
os_client_config/vendors/ovh.json
vendored
@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "ovh",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://auth.cloud.ovh.net/"
|
||||
},
|
||||
"regions": [
|
||||
"BHS1",
|
||||
"GRA1",
|
||||
"SBG1"
|
||||
],
|
||||
"identity_api_version": "3",
|
||||
"floating_ip_source": "None"
|
||||
}
|
||||
}
|
29
os_client_config/vendors/rackspace.json
vendored
29
os_client_config/vendors/rackspace.json
vendored
@ -1,29 +0,0 @@
|
||||
{
|
||||
"name": "rackspace",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://identity.api.rackspacecloud.com/v2.0/"
|
||||
},
|
||||
"regions": [
|
||||
"DFW",
|
||||
"HKG",
|
||||
"IAD",
|
||||
"ORD",
|
||||
"SYD",
|
||||
"LON"
|
||||
],
|
||||
"database_service_type": "rax:database",
|
||||
"compute_service_name": "cloudServersOpenStack",
|
||||
"image_api_use_tasks": true,
|
||||
"image_format": "vhd",
|
||||
"floating_ip_source": "None",
|
||||
"secgroup_source": "None",
|
||||
"requires_floating_ip": false,
|
||||
"volume_api_version": "1",
|
||||
"disable_vendor_agent": {
|
||||
"vm_mode": "hvm",
|
||||
"xenapi_use_agent": false
|
||||
},
|
||||
"has_network": false
|
||||
}
|
||||
}
|
15
os_client_config/vendors/switchengines.json
vendored
15
os_client_config/vendors/switchengines.json
vendored
@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "switchengines",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://keystone.cloud.switch.ch:5000/v2.0"
|
||||
},
|
||||
"regions": [
|
||||
"LS",
|
||||
"ZH"
|
||||
],
|
||||
"volume_api_version": "1",
|
||||
"image_api_use_tasks": true,
|
||||
"image_format": "raw"
|
||||
}
|
||||
}
|
11
os_client_config/vendors/ultimum.json
vendored
11
os_client_config/vendors/ultimum.json
vendored
@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "ultimum",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://console.ultimum-cloud.com:5000/"
|
||||
},
|
||||
"identity_api_version": "3",
|
||||
"volume_api_version": "1",
|
||||
"region-name": "RegionOne"
|
||||
}
|
||||
}
|
16
os_client_config/vendors/unitedstack.json
vendored
16
os_client_config/vendors/unitedstack.json
vendored
@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "unitedstack",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://identity.api.ustack.com/v3"
|
||||
},
|
||||
"regions": [
|
||||
"bj1",
|
||||
"gd1"
|
||||
],
|
||||
"volume_api_version": "1",
|
||||
"identity_api_version": "3",
|
||||
"image_format": "raw",
|
||||
"floating_ip_source": "None"
|
||||
}
|
||||
}
|
16
os_client_config/vendors/vexxhost.json
vendored
16
os_client_config/vendors/vexxhost.json
vendored
@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "vexxhost",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://auth.vexxhost.net"
|
||||
},
|
||||
"regions": [
|
||||
"ca-ymq-1"
|
||||
],
|
||||
"dns_api_version": "1",
|
||||
"identity_api_version": "3",
|
||||
"image_format": "raw",
|
||||
"floating_ip_source": "None",
|
||||
"requires_floating_ip": false
|
||||
}
|
||||
}
|
13
os_client_config/vendors/zetta.json
vendored
13
os_client_config/vendors/zetta.json
vendored
@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "zetta",
|
||||
"profile": {
|
||||
"auth": {
|
||||
"auth_url": "https://identity.api.zetta.io/v3"
|
||||
},
|
||||
"regions": [
|
||||
"no-osl1"
|
||||
],
|
||||
"identity_api_version": "3",
|
||||
"dns_api_version": "2"
|
||||
}
|
||||
}
|
13
releasenotes/notes/thin-shim-62c8e6f6942b83a5.yaml
Normal file
13
releasenotes/notes/thin-shim-62c8e6f6942b83a5.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
prelude: >
|
||||
os-client-config is now a thin shim around openstacksdk. It exists and
|
||||
will continue to exist provide backward compatibility.
|
||||
upgrade:
|
||||
- |
|
||||
``get_region_name`` no longer supports pre-service region name overrides.
|
||||
An ``os_client_config.cloud_config.CloudConfig`` object represents a region
|
||||
of a cloud. The support was originally added for compatibility with the
|
||||
similar feature in openstacksdk's ``Profile``. Both the support for
|
||||
service regions and the ``Profile`` object have been removed from
|
||||
openstacksdk, so there is no need to attempt to add a compatibility layer
|
||||
here as there is nothing that has the ability to consume it.
|
@ -1,7 +1,4 @@
|
||||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
PyYAML>=3.12 # MIT
|
||||
appdirs>=1.3.0 # MIT License
|
||||
keystoneauth1>=3.4.0 # Apache-2.0
|
||||
requestsexceptions>=1.2.0 # Apache-2.0
|
||||
openstacksdk>=0.13.0 # Apache-2.0
|
||||
|
Loading…
x
Reference in New Issue
Block a user