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:
Monty Taylor 2018-03-02 10:42:37 +01:00
parent cf5f446f27
commit 5c2eae8f82
No known key found for this signature in database
GPG Key ID: 7BAE94BC7141A594
40 changed files with 101 additions and 2788 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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):

View File

@ -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"
]
}

View File

@ -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

View File

@ -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'

View File

@ -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):

View File

@ -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))

View File

@ -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"
]
}

View File

@ -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

View File

@ -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
}
}

View File

@ -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"
}
}

View File

@ -1,7 +0,0 @@
{
"name": "bluebox",
"profile": {
"volume_api_version": "1",
"region_name": "RegionOne"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -1,14 +0,0 @@
{
"name": "conoha",
"profile": {
"auth": {
"auth_url": "https://identity.{region_name}.conoha.io"
},
"regions": [
"sin1",
"sjc1",
"tyo1"
],
"identity_api_version": "2"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -1,10 +0,0 @@
{
"name": "elastx",
"profile": {
"auth": {
"auth_url": "https://ops.elastx.net:5000"
},
"identity_api_version": "3",
"region_name": "regionOne"
}
}

View File

@ -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"
]
}
}

View File

@ -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"
}
}

View File

@ -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"
]
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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"
}
}

View File

@ -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
}
}

View File

@ -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"
}
}

View 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.

View File

@ -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