Add utils to work with OpenStack components
Add utils to do basic actions with nova and keystone. We decide to store in utils/openstack/%service_name.py service specific clients in classes named like Climate%service_name%Client. In this classes we define service client with specific variables. Also, we redefine __getattr__ like this: def __getattr__(self, name): fn = getattr(self.%service_name, name) return fn Change-Id: I47e0d8689f1d8ca8aba0372eb5e7a4a80f2f9be5
This commit is contained in:
parent
df1b79d636
commit
19cc43f79a
@ -13,22 +13,31 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
|
||||
from climate import context
|
||||
from climate import exceptions
|
||||
from climate import policy
|
||||
|
||||
|
||||
def ctx_from_headers(headers):
|
||||
try:
|
||||
service_catalog = json.loads(headers['X-Service-Catalog'])
|
||||
except KeyError:
|
||||
raise exceptions.ServiceCatalogNotFound()
|
||||
except TypeError:
|
||||
raise exceptions.WrongFormat()
|
||||
|
||||
ctx = context.ClimateContext(
|
||||
user_id=headers['X-User-Id'],
|
||||
tenant_id=headers['X-Tenant-Id'],
|
||||
auth_token=headers['X-Auth-Token'],
|
||||
service_catalog=headers['X-Service-Catalog'],
|
||||
service_catalog=service_catalog,
|
||||
user_name=headers['X-User-Name'],
|
||||
tenant_name=headers['X-Tenant-Name'],
|
||||
roles=map(unicode.strip, headers['X-Roles'].split(',')),
|
||||
)
|
||||
target = {'tenant_id': ctx.tenant_id, 'user_id': ctx.user_id}
|
||||
if policy.enforce(ctx, "admin", target, do_raise=False):
|
||||
return ctx.elevated()
|
||||
else:
|
||||
return ctx
|
||||
ctx.is_admin = True
|
||||
return ctx
|
||||
|
@ -68,3 +68,11 @@ class PolicyNotAuthorized(NotAuthorized):
|
||||
|
||||
class ConfigNotFound(ClimateException):
|
||||
msg_fmt = _("Could not find config at %(path)s")
|
||||
|
||||
|
||||
class ServiceCatalogNotFound(NotFound):
|
||||
msg_fmt = _("Could not find service catalog")
|
||||
|
||||
|
||||
class WrongFormat(ClimateException):
|
||||
msg_fmt = _("Unenxpectable object format")
|
||||
|
@ -71,3 +71,23 @@ class HostHavingServers(exceptions.ClimateException):
|
||||
class CantAddExtraCapability(exceptions.ClimateException):
|
||||
code = 409
|
||||
msg_fmt = _("Can't add extracapabilities %(keys)s to Host %(host)s")
|
||||
|
||||
|
||||
class EndpointsNotFound(exceptions.NotFound):
|
||||
code = 404
|
||||
msg_fmt = _("No endpoints for %(service)s")
|
||||
|
||||
|
||||
class ServiceNotFound(exceptions.NotFound):
|
||||
code = 404
|
||||
msg_fmt = _("Service %(service)s not found")
|
||||
|
||||
|
||||
class WrongClientVersion(exceptions.ClimateException):
|
||||
code = 400
|
||||
msg_fmt = _("Unfortunately you use wrong client version")
|
||||
|
||||
|
||||
class NoManagementUrl(exceptions.NotFound):
|
||||
code = 404
|
||||
msg_fmt = _("You haven't management url for service")
|
||||
|
@ -13,8 +13,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
|
||||
from climate.api import context as api_context
|
||||
from climate import context
|
||||
from climate import exceptions
|
||||
from climate import policy
|
||||
from climate import tests
|
||||
|
||||
@ -26,24 +29,42 @@ class ContextTestCase(tests.TestCase):
|
||||
self.fake_headers = {u'X-User-Id': u'1',
|
||||
u'X-Tenant-Id': u'1',
|
||||
u'X-Auth-Token': u'111-111-111',
|
||||
u'X-Service-Catalog': u'catalog',
|
||||
u'X-User-Name': u'user_name',
|
||||
u'X-Tenant-Name': u'tenant_name',
|
||||
u'X-Roles': u'user_name0, user_name1'}
|
||||
|
||||
def test_ctx_from_headers(self):
|
||||
self.context = self.patch(context, 'ClimateContext')
|
||||
catalog = json.dumps({'nova': 'catalog'})
|
||||
self.fake_headers[u'X-Service-Catalog'] = catalog
|
||||
api_context.ctx_from_headers(self.fake_headers)
|
||||
self.context.assert_called_once_with(user_id=u'1',
|
||||
roles=[u'user_name0',
|
||||
u'user_name1'],
|
||||
tenant_name=u'tenant_name',
|
||||
auth_token=u'111-111-111',
|
||||
service_catalog=u'catalog',
|
||||
service_catalog={
|
||||
u'nova': u'catalog'},
|
||||
tenant_id=u'1',
|
||||
user_name=u'user_name')
|
||||
|
||||
def test_ctx_from_headers_with_admin(self):
|
||||
catalog = json.dumps({'nova': 'catalog'})
|
||||
self.fake_headers[u'X-Service-Catalog'] = catalog
|
||||
self.patch(policy, 'enforce').return_value = True
|
||||
ctx = api_context.ctx_from_headers(self.fake_headers)
|
||||
self.assertEqual(True, ctx.is_admin)
|
||||
|
||||
def test_ctx_from_headers_no_catalog(self):
|
||||
self.assertRaises(
|
||||
exceptions.ServiceCatalogNotFound,
|
||||
api_context.ctx_from_headers,
|
||||
self.fake_headers)
|
||||
|
||||
def test_ctx_from_headers_wrong_format(self):
|
||||
catalog = ['etc']
|
||||
self.fake_headers[u'X-Service-Catalog'] = catalog
|
||||
self.assertRaises(
|
||||
exceptions.WrongFormat,
|
||||
api_context.ctx_from_headers,
|
||||
self.fake_headers)
|
||||
|
0
climate/tests/utils/__init__.py
Normal file
0
climate/tests/utils/__init__.py
Normal file
0
climate/tests/utils/openstack/__init__.py
Normal file
0
climate/tests/utils/openstack/__init__.py
Normal file
78
climate/tests/utils/openstack/test_base.py
Normal file
78
climate/tests/utils/openstack/test_base.py
Normal file
@ -0,0 +1,78 @@
|
||||
# Copyright (c) 2013 Mirantis Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from climate.manager import exceptions
|
||||
from climate import tests
|
||||
from climate.utils.openstack import base
|
||||
|
||||
|
||||
class TestBaseStackUtils(tests.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestBaseStackUtils, self).setUp()
|
||||
|
||||
self.base = base
|
||||
|
||||
self.service_type = 'fake_service'
|
||||
self.url = 'http://%s-net.com'
|
||||
|
||||
def test_url_for_good_v3(self):
|
||||
#TODO(n.s.):Can't find v3 endpoint example. Fix it later.
|
||||
pass
|
||||
|
||||
def test_url_for_good_v2_public(self):
|
||||
service_catalog =\
|
||||
[{"endpoints": [{"adminURL": self.url % 'admin',
|
||||
"region": "RegionOne",
|
||||
"internalURL": self.url % 'internal',
|
||||
"publicURL": self.url % 'public'}],
|
||||
"type": "fake_service",
|
||||
"name": "foo"}]
|
||||
|
||||
url = self.base.url_for(service_catalog, self.service_type)
|
||||
self.assertEqual(url, self.url % 'public')
|
||||
|
||||
def test_url_for_good_v2_admin(self):
|
||||
service_catalog =\
|
||||
[{"endpoints": [{"adminURL": self.url % 'admin',
|
||||
"region": "RegionOne",
|
||||
"internalURL": self.url % 'internal',
|
||||
"publicURL": self.url % 'public'}],
|
||||
"type": "fake_service",
|
||||
"name": "foo"}]
|
||||
|
||||
url = self.base.url_for(service_catalog, self.service_type,
|
||||
endpoint_interface='admin')
|
||||
self.assertEqual(url, self.url % 'admin')
|
||||
|
||||
def test_url_for_no_service(self):
|
||||
service_catalog =\
|
||||
[{"endpoints": [{"adminURL": self.url % 'admin',
|
||||
"region": "RegionOne",
|
||||
"internalURL": self.url % 'internal',
|
||||
"publicURL": self.url % 'public'}],
|
||||
"type": "foo_service",
|
||||
"name": "foo"}]
|
||||
|
||||
self.assertRaises(exceptions.ServiceNotFound, self.base.url_for,
|
||||
service_catalog, self.service_type)
|
||||
|
||||
def test_url_for_no_endpoints(self):
|
||||
service_catalog =\
|
||||
[{"type": "fake_service",
|
||||
"name": "foo"}]
|
||||
|
||||
self.assertRaises(exceptions.EndpointsNotFound, self.base.url_for,
|
||||
service_catalog, self.service_type)
|
76
climate/tests/utils/openstack/test_keystone.py
Normal file
76
climate/tests/utils/openstack/test_keystone.py
Normal file
@ -0,0 +1,76 @@
|
||||
# Copyright (c) 2013 Mirantis Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from keystoneclient import client as keystone_client
|
||||
|
||||
from climate import context
|
||||
from climate import tests
|
||||
from climate.utils.openstack import base
|
||||
from climate.utils.openstack import keystone
|
||||
|
||||
|
||||
class TestCKClient(tests.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCKClient, self).setUp()
|
||||
|
||||
self.keystone = keystone
|
||||
self.context = context
|
||||
self.k_client = keystone_client
|
||||
self.base = base
|
||||
|
||||
self.ctx = self.patch(self.context, 'current')
|
||||
self.client = self.patch(self.k_client, 'Client')
|
||||
self.patch(self.base, 'url_for').return_value = 'http://fake.com/'
|
||||
|
||||
self.version = '1'
|
||||
self.username = 'fake_user'
|
||||
self.token = 'fake_token'
|
||||
self.password = 'fake_pass'
|
||||
self.tenant_name = 'fake_tenant'
|
||||
self.auth_url = 'fake_url'
|
||||
self.trust = 'fake_trust'
|
||||
self.mgmt_url = 'fake_url'
|
||||
|
||||
def test_client_from_kwargs(self):
|
||||
|
||||
self.ctx.side_effect = RuntimeError
|
||||
|
||||
self.keystone.ClimateKeystoneClient(version=self.version,
|
||||
username=self.username,
|
||||
password=self.password,
|
||||
tenant_name=self.tenant_name,
|
||||
auth_url=self.auth_url)
|
||||
|
||||
self.client.assert_called_once_with(version=self.version,
|
||||
tenant_name=self.tenant_name,
|
||||
username=self.username,
|
||||
password=self.password,
|
||||
auth_url=self.auth_url)
|
||||
|
||||
def test_client_from_ctx(self):
|
||||
|
||||
self.keystone.ClimateKeystoneClient()
|
||||
|
||||
self.client.assert_called_once_with(version='3',
|
||||
username=self.ctx().user_name,
|
||||
token=self.ctx().auth_token,
|
||||
tenant_name=self.ctx().tenant_name,
|
||||
auth_url='http://fake.com/',
|
||||
endpoint='http://fake.com/')
|
||||
|
||||
def test_getattr(self):
|
||||
#TODO(n.s.): Will be done as soon as pypi package will be updated
|
||||
pass
|
77
climate/tests/utils/openstack/test_nova.py
Normal file
77
climate/tests/utils/openstack/test_nova.py
Normal file
@ -0,0 +1,77 @@
|
||||
# Copyright (c) 2013 Mirantis Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from novaclient import client as nova_client
|
||||
|
||||
from climate import context
|
||||
from climate import tests
|
||||
from climate.utils.openstack import base
|
||||
from climate.utils.openstack import nova
|
||||
|
||||
|
||||
class TestCNClient(tests.TestCase):
|
||||
def setUp(self):
|
||||
super(TestCNClient, self).setUp()
|
||||
|
||||
self.nova = nova
|
||||
self.context = context
|
||||
self.n_client = nova_client
|
||||
self.base = base
|
||||
|
||||
self.ctx = self.patch(self.context, 'current')
|
||||
self.client = self.patch(self.n_client, 'Client')
|
||||
self.patch(self.base, 'url_for').return_value = 'http://fake.com/'
|
||||
|
||||
self.version = '2'
|
||||
self.username = 'fake_user'
|
||||
self.api_key = self.ctx().auth_token
|
||||
self.project_id = self.ctx().tenant_id
|
||||
self.auth_url = 'fake_auth'
|
||||
self.mgmt_url = 'fake_mgmt'
|
||||
|
||||
def test_client_from_kwargs(self):
|
||||
self.ctx.side_effect = RuntimeError
|
||||
|
||||
kwargs = {'version': self.version,
|
||||
'username': self.username,
|
||||
'api_key': self.api_key,
|
||||
'project_id': self.project_id,
|
||||
'auth_url': self.auth_url,
|
||||
'mgmt_url': self.mgmt_url}
|
||||
|
||||
self.nova.ClimateNovaClient(**kwargs)
|
||||
|
||||
self.client.assert_called_once_with(version=self.version,
|
||||
username=self.username,
|
||||
api_key=self.api_key,
|
||||
project_id=self.project_id,
|
||||
auth_url=self.auth_url)
|
||||
|
||||
def test_client_from_ctx(self):
|
||||
|
||||
kwargs = {'version': self.version}
|
||||
|
||||
self.nova.ClimateNovaClient(**kwargs)
|
||||
|
||||
self.client.assert_called_once_with(version=self.version,
|
||||
username=self.ctx().user_name,
|
||||
api_key=None,
|
||||
auth_token=self.ctx().auth_token,
|
||||
project_id=self.ctx().tenant_id,
|
||||
auth_url='http://fake.com/')
|
||||
|
||||
def test_getattr(self):
|
||||
#TODO(n.s.): Will be done as soon as pypi package will be updated
|
||||
pass
|
0
climate/utils/openstack/__init__.py
Normal file
0
climate/utils/openstack/__init__.py
Normal file
51
climate/utils/openstack/base.py
Normal file
51
climate/utils/openstack/base.py
Normal file
@ -0,0 +1,51 @@
|
||||
# Copyright (c) 2013 Mirantis Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from climate.manager import exceptions
|
||||
|
||||
|
||||
def url_for(service_catalog, service_type, admin=False,
|
||||
endpoint_interface=None):
|
||||
"""Gets url of the service to communicate through.
|
||||
service_catalog - dict contains info about specific OpenStack service
|
||||
service_type - OpenStack service type specification
|
||||
"""
|
||||
if not endpoint_interface:
|
||||
endpoint_interface = 'public'
|
||||
if admin:
|
||||
endpoint_interface = 'admin'
|
||||
|
||||
service = None
|
||||
for srv in service_catalog:
|
||||
if srv['type'] == service_type:
|
||||
service = srv
|
||||
|
||||
if service:
|
||||
try:
|
||||
endpoints = service['endpoints']
|
||||
except KeyError:
|
||||
raise exceptions.EndpointsNotFound(
|
||||
"No endpoints for %s" % service['type'])
|
||||
try:
|
||||
# if Keystone API v3 endpoints returned
|
||||
endpoint = [e for e in endpoints
|
||||
if e['interface'] == endpoint_interface][0]
|
||||
return endpoint['url']
|
||||
except KeyError:
|
||||
# otherwise
|
||||
return endpoints[0]['%sURL' % endpoint_interface]
|
||||
else:
|
||||
raise exceptions.ServiceNotFound(
|
||||
'Service "%s" not found' % service_type)
|
111
climate/utils/openstack/keystone.py
Normal file
111
climate/utils/openstack/keystone.py
Normal file
@ -0,0 +1,111 @@
|
||||
# Copyright (c) 2013 Mirantis Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from keystoneclient import client as keystone_client
|
||||
from keystoneclient import exceptions as keystone_exception
|
||||
from oslo.config import cfg
|
||||
|
||||
from climate import context
|
||||
from climate.manager import exceptions as manager_exceptions
|
||||
from climate.utils.openstack import base
|
||||
|
||||
|
||||
opts = [
|
||||
cfg.StrOpt('identity_service',
|
||||
default='identityv3',
|
||||
help='Identity service to use.')
|
||||
]
|
||||
|
||||
keystone_opts = [
|
||||
cfg.StrOpt('keystone_client_version',
|
||||
default='3',
|
||||
help='Keystoneclient version'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_cli_opts(opts)
|
||||
CONF.register_opts(keystone_opts)
|
||||
|
||||
|
||||
class ClimateKeystoneClient(object):
|
||||
def __init__(self, **kwargs):
|
||||
"""Return Keystone client for defined in 'identity_service' conf.
|
||||
NOTE: We will use tenant_name until we start using keystone V3
|
||||
client for all our needs.
|
||||
|
||||
:param version: service client version which we will use
|
||||
:type version: str
|
||||
|
||||
:param username: username
|
||||
:type username: str
|
||||
|
||||
:param password: password
|
||||
:type password: str
|
||||
|
||||
:param tenant_name: tenant_name
|
||||
:type tenant_name: str
|
||||
|
||||
:param auth_url: auth_url
|
||||
:type auth_url: str
|
||||
|
||||
:param ctx: climate context object
|
||||
:type ctx: dict
|
||||
|
||||
:param auth_url: keystone auth url
|
||||
:type auth_url: string
|
||||
|
||||
:param endpoint: keystone management (endpoint) url
|
||||
:type endpoint: string
|
||||
|
||||
:param token: user token to use for authentication
|
||||
:type token: string
|
||||
"""
|
||||
|
||||
ctx = kwargs.pop('ctx', None)
|
||||
if ctx is None:
|
||||
try:
|
||||
ctx = context.current()
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
kwargs.setdefault('version', cfg.CONF.keystone_client_version)
|
||||
if ctx is not None:
|
||||
kwargs.setdefault('username', ctx.user_name)
|
||||
kwargs.setdefault('tenant_name', ctx.tenant_name)
|
||||
if not kwargs.get('auth_url'):
|
||||
kwargs['auth_url'] = base.url_for(
|
||||
ctx.service_catalog, CONF.identity_service)
|
||||
if not kwargs.get('password'):
|
||||
kwargs.setdefault('token', ctx.auth_token)
|
||||
if kwargs['token'] and not kwargs.get('endpoint'):
|
||||
try:
|
||||
kwargs['endpoint'] = base.url_for(
|
||||
ctx.service_catalog, CONF.identity_service,
|
||||
endpoint_interface='admin')
|
||||
except AttributeError:
|
||||
raise manager_exceptions.NoManagementUrl()
|
||||
|
||||
try:
|
||||
#NOTE(n.s.): we shall remove this try: except: clause when
|
||||
#https://review.openstack.org/#/c/66494/ will be merged
|
||||
self.keystone = keystone_client.Client(**kwargs)
|
||||
except AttributeError:
|
||||
raise manager_exceptions.WrongClientVersion()
|
||||
|
||||
self.exceptions = keystone_exception
|
||||
|
||||
def __getattr__(self, name):
|
||||
func = getattr(self.keystone, name)
|
||||
return func
|
107
climate/utils/openstack/nova.py
Normal file
107
climate/utils/openstack/nova.py
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2013 Mirantis Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from novaclient import client as nova_client
|
||||
from novaclient import exceptions as nova_exception
|
||||
from oslo.config import cfg
|
||||
|
||||
from climate import context
|
||||
from climate.manager import exceptions as manager_exceptions
|
||||
from climate.utils.openstack import base
|
||||
|
||||
|
||||
nova_opts = [
|
||||
cfg.StrOpt('nova_client_version',
|
||||
default='2',
|
||||
help='Novaclient version'),
|
||||
cfg.StrOpt('compute_service',
|
||||
default='compute',
|
||||
help='Nova name in keystone'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(nova_opts)
|
||||
CONF.import_opt('identity_service', 'climate.utils.openstack.keystone')
|
||||
|
||||
|
||||
class ClimateNovaClient(object):
|
||||
def __init__(self, **kwargs):
|
||||
"""We suppose that in future we may want to use CNC in some places
|
||||
where context will be available, so we create 2 different ways of
|
||||
creating client from context(future) and kwargs(we use it now).
|
||||
|
||||
:param version: service client version which we will use
|
||||
:type version: str
|
||||
|
||||
:param username: username
|
||||
:type username: str
|
||||
|
||||
:param api_key: password
|
||||
:type api_key: str
|
||||
|
||||
:param auth_token: keystone auth token
|
||||
:type auth_token: str
|
||||
|
||||
:param project_id: project_id
|
||||
:type api_key: str
|
||||
|
||||
:param auth_url: auth_url
|
||||
:type auth_url: str
|
||||
|
||||
:param mgmt_url: management url
|
||||
:type mgmt_url: str
|
||||
"""
|
||||
|
||||
ctx = kwargs.pop('ctx', None)
|
||||
|
||||
if ctx is None:
|
||||
try:
|
||||
ctx = context.current()
|
||||
except RuntimeError:
|
||||
pass
|
||||
kwargs.setdefault('version', cfg.CONF.nova_client_version)
|
||||
if ctx is not None:
|
||||
kwargs.setdefault('username', ctx.user_name)
|
||||
kwargs.setdefault('api_key', None)
|
||||
kwargs.setdefault('auth_token', ctx.auth_token)
|
||||
kwargs.setdefault('project_id', ctx.tenant_id)
|
||||
if not kwargs.get('auth_url'):
|
||||
kwargs['auth_url'] = base.url_for(
|
||||
ctx.service_catalog, CONF.identity_service)
|
||||
|
||||
try:
|
||||
mgmt_url = kwargs.pop('mgmt_url', None) or base.url_for(
|
||||
ctx.service_catalog, CONF.compute_service)
|
||||
except AttributeError:
|
||||
raise manager_exceptions.NoManagementUrl()
|
||||
|
||||
self.nova = nova_client.Client(**kwargs)
|
||||
|
||||
self.nova.client.management_url = mgmt_url
|
||||
self.exceptions = nova_exception
|
||||
|
||||
def _image_create(self, instance_id):
|
||||
instance = self.nova.servers.get(instance_id)
|
||||
instance_name = instance.name
|
||||
self.nova.servers.create_image(instance_id,
|
||||
"reserved_%s" % instance_name)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name == 'create_image':
|
||||
func = self._image_create
|
||||
else:
|
||||
func = getattr(self.nova, name)
|
||||
|
||||
return func
|
Loading…
x
Reference in New Issue
Block a user