High level interface
High level interface using the connection classes to access the various services. Only identity projects and list_flavors in compute are implemented: projects = conn.identity.list_projects() The service filter has a valid_versions added to it to map the module name to the version component of the endpoint URL. For example, the v2.0 endpoint path is supported by the v2 SDK network module: https://region-a.geo-1.network.hpcloudsvc.com/v2.0/ is supported by the SDK module openstack.network.v2. Implements: blueprint highlevel-interface Change-Id: Ie52986a9da84c8f3395757c08de7a01be30e0f2a
This commit is contained in:
parent
76313512a4
commit
8baa156ea6
@ -25,12 +25,25 @@ filter to match a service.
|
||||
from openstack import exceptions
|
||||
|
||||
|
||||
class ValidVersion(object):
|
||||
|
||||
def __init__(self, module, path=None):
|
||||
"""" Valid service version.
|
||||
|
||||
:param string module: Module associated with version.
|
||||
:param string path: URL path version.
|
||||
"""
|
||||
self.module = module
|
||||
self.path = path or module
|
||||
|
||||
|
||||
class ServiceFilter(object):
|
||||
ANY = 'any'
|
||||
PUBLIC = 'public'
|
||||
INTERNAL = 'internal'
|
||||
ADMIN = 'admin'
|
||||
VISIBILITY = [PUBLIC, INTERNAL, ADMIN]
|
||||
valid_versions = []
|
||||
|
||||
def __init__(self, service_type=ANY, visibility=PUBLIC, region=None,
|
||||
service_name=None, version=None):
|
||||
@ -115,3 +128,20 @@ class ServiceFilter(object):
|
||||
msg = "Visibility <%s> not in %s" % (visibility, self.VISIBILITY)
|
||||
raise exceptions.SDKException(msg)
|
||||
self.visibility = visibility
|
||||
|
||||
def get_module(self):
|
||||
"""Get the full module name associated with the service."""
|
||||
module = self.__class__.__module__.split('.')
|
||||
module = ".".join(module[:-1])
|
||||
# NOTE(thowe): Only support for one valid version right now.
|
||||
module = module + "." + self.valid_versions[0].module
|
||||
return module
|
||||
|
||||
def get_service_module(self):
|
||||
"""Get the module version of the service name.
|
||||
|
||||
This would often be the same as the service type except in cases like
|
||||
object store where the service type is `object-store` and the module
|
||||
is `object_store`.
|
||||
"""
|
||||
return self.__class__.__module__.split('.')[1]
|
||||
|
@ -16,6 +16,8 @@ from openstack.auth import service_filter
|
||||
class ComputeService(service_filter.ServiceFilter):
|
||||
"""The compute service."""
|
||||
|
||||
valid_versions = [service_filter.ValidVersion('v2')]
|
||||
|
||||
def __init__(self):
|
||||
"""Create an compute service."""
|
||||
super(ComputeService, self).__init__(service_type='compute')
|
||||
|
22
openstack/compute/v2/_proxy.py
Normal file
22
openstack/compute/v2/_proxy.py
Normal file
@ -0,0 +1,22 @@
|
||||
# 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 openstack.compute.v2 import flavor
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
||||
|
||||
def list_flavors(self, **params):
|
||||
return flavor.Flavor.list(self.session, **params)
|
@ -58,6 +58,8 @@ try to find it and if that fails, you would create it::
|
||||
network = conn.network.create_network({"name": "jenkins"})
|
||||
|
||||
"""
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from stevedore import driver
|
||||
|
||||
@ -68,6 +70,7 @@ from openstack import transport as xport
|
||||
|
||||
USER_AGENT = 'OSPythonSDK'
|
||||
"""Default value for the HTTP User-Agent header"""
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Connection(object):
|
||||
@ -128,6 +131,7 @@ class Connection(object):
|
||||
**auth_args)
|
||||
self.session = session.Session(self.transport, self.authenticator,
|
||||
preference)
|
||||
self._open()
|
||||
|
||||
def _create_transport(self, transport, verify, user_agent):
|
||||
if transport:
|
||||
@ -157,3 +161,21 @@ class Connection(object):
|
||||
valid_list = plugin.valid_options
|
||||
args = dict((n, auth_args[n]) for n in valid_list if n in auth_args)
|
||||
return plugin(**args)
|
||||
|
||||
def _open(self):
|
||||
"""Open the connection.
|
||||
|
||||
NOTE(thowe): Have this set up some lazy loader instead.
|
||||
"""
|
||||
for service in self.session.get_services():
|
||||
self._load(service)
|
||||
|
||||
def _load(self, service):
|
||||
attr_name = service.get_service_module()
|
||||
module = service.get_module() + "._proxy"
|
||||
try:
|
||||
__import__(module)
|
||||
proxy = getattr(sys.modules[module], "Proxy")
|
||||
setattr(self, attr_name, proxy(self.session))
|
||||
except Exception as e:
|
||||
_logger.warn("Unable to load %s: %s" % (module, e))
|
||||
|
@ -16,6 +16,8 @@ from openstack.auth import service_filter
|
||||
class DatabaseService(service_filter.ServiceFilter):
|
||||
"""The database service."""
|
||||
|
||||
valid_versions = [service_filter.ValidVersion('v1')]
|
||||
|
||||
def __init__(self):
|
||||
"""Create an database service."""
|
||||
super(DatabaseService, self).__init__(service_type='database')
|
||||
|
17
openstack/database/v1/_proxy.py
Normal file
17
openstack/database/v1/_proxy.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
@ -16,6 +16,11 @@ from openstack.auth import service_filter
|
||||
class IdentityService(service_filter.ServiceFilter):
|
||||
"""The identity service."""
|
||||
|
||||
valid_versions = [
|
||||
service_filter.ValidVersion('v3'),
|
||||
service_filter.ValidVersion('v2'),
|
||||
]
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""Create an identity service."""
|
||||
kwargs['service_type'] = 'identity'
|
||||
|
17
openstack/identity/v2/_proxy.py
Normal file
17
openstack/identity/v2/_proxy.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
43
openstack/identity/v3/_proxy.py
Normal file
43
openstack/identity/v3/_proxy.py
Normal file
@ -0,0 +1,43 @@
|
||||
# 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 openstack.identity.v3 import project
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
||||
|
||||
def create_project(self, **data):
|
||||
obj = project.Project(**data)
|
||||
obj.create(self.session)
|
||||
return obj
|
||||
|
||||
def get_project(self, r_id):
|
||||
obj = project.Project({'id': r_id})
|
||||
obj.get(self.session)
|
||||
return obj
|
||||
|
||||
def update_project(self, **data):
|
||||
obj = project.Project(**data)
|
||||
obj.update(self.session)
|
||||
|
||||
def delete_project(self, r_id):
|
||||
obj = project.Project({'id': r_id})
|
||||
obj.delete(self.session)
|
||||
|
||||
def list_projects(self, **params):
|
||||
return project.Project.list(self.session, **params)
|
||||
|
||||
def find_project(self, name_or_id):
|
||||
return project.Project.find(self.session, name_or_id)
|
@ -16,6 +16,8 @@ from openstack.auth import service_filter
|
||||
class ImageService(service_filter.ServiceFilter):
|
||||
"""The image service."""
|
||||
|
||||
valid_versions = [service_filter.ValidVersion('v1')]
|
||||
|
||||
def __init__(self):
|
||||
"""Create an image service."""
|
||||
super(ImageService, self).__init__(service_type='image')
|
||||
|
17
openstack/image/v1/_proxy.py
Normal file
17
openstack/image/v1/_proxy.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
@ -16,6 +16,8 @@ from openstack.auth import service_filter
|
||||
class NetworkService(service_filter.ServiceFilter):
|
||||
"""The network service."""
|
||||
|
||||
valid_versions = [service_filter.ValidVersion('v2', 'v2.0')]
|
||||
|
||||
def __init__(self):
|
||||
"""Create an network service."""
|
||||
super(NetworkService, self).__init__(service_type='network')
|
||||
|
17
openstack/network/v2/_proxy.py
Normal file
17
openstack/network/v2/_proxy.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
@ -16,6 +16,8 @@ from openstack.auth import service_filter
|
||||
class ObjectStoreService(service_filter.ServiceFilter):
|
||||
"""The object store service."""
|
||||
|
||||
valid_versions = [service_filter.ValidVersion('v1')]
|
||||
|
||||
def __init__(self):
|
||||
"""Create an object store service."""
|
||||
super(ObjectStoreService, self).__init__(service_type='object-store')
|
||||
|
17
openstack/object_store/v1/_proxy.py
Normal file
17
openstack/object_store/v1/_proxy.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
@ -16,6 +16,8 @@ from openstack.auth import service_filter
|
||||
class OrchestrationService(service_filter.ServiceFilter):
|
||||
"""The orchestration service."""
|
||||
|
||||
valid_versions = [service_filter.ValidVersion('v1')]
|
||||
|
||||
def __init__(self):
|
||||
"""Create an orchestration service."""
|
||||
super(OrchestrationService, self).__init__(
|
||||
|
17
openstack/orchestration/v1/_proxy.py
Normal file
17
openstack/orchestration/v1/_proxy.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
@ -16,6 +16,8 @@ from openstack.auth import service_filter
|
||||
class TelemetryService(service_filter.ServiceFilter):
|
||||
"""The telemetry service."""
|
||||
|
||||
valid_versions = [service_filter.ValidVersion('v2')]
|
||||
|
||||
def __init__(self):
|
||||
"""Create a telemetry service."""
|
||||
super(TelemetryService, self).__init__(service_type='metering')
|
||||
|
17
openstack/telemetry/v2/_proxy.py
Normal file
17
openstack/telemetry/v2/_proxy.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
@ -15,6 +15,7 @@ import testtools
|
||||
|
||||
from openstack.auth import service_filter as filt
|
||||
from openstack import exceptions
|
||||
from openstack.identity import identity_service
|
||||
|
||||
|
||||
class TestServiceFilter(testtools.TestCase):
|
||||
@ -124,3 +125,15 @@ class TestServiceFilter(testtools.TestCase):
|
||||
self.assertEqual('internal', sot.visibility)
|
||||
sot.set_visibility("ADMINURL")
|
||||
self.assertEqual('admin', sot.visibility)
|
||||
|
||||
def test_get_module(self):
|
||||
sot = identity_service.IdentityService()
|
||||
self.assertEqual('openstack.identity.v3', sot.get_module())
|
||||
self.assertEqual('identity', sot.get_service_module())
|
||||
|
||||
|
||||
class TestValidVersion(testtools.TestCase):
|
||||
def test_constructor(self):
|
||||
sot = filt.ValidVersion('v1.0', 'v1')
|
||||
self.assertEqual('v1.0', sot.module)
|
||||
self.assertEqual('v1', sot.path)
|
||||
|
@ -23,3 +23,6 @@ class TestComputeService(testtools.TestCase):
|
||||
self.assertEqual('public', sot.visibility)
|
||||
self.assertIsNone(sot.region)
|
||||
self.assertIsNone(sot.service_name)
|
||||
self.assertEqual(1, len(sot.valid_versions))
|
||||
self.assertEqual('v2', sot.valid_versions[0].module)
|
||||
self.assertEqual('v2', sot.valid_versions[0].path)
|
||||
|
@ -23,3 +23,6 @@ class TestDatabaseService(testtools.TestCase):
|
||||
self.assertEqual('public', sot.visibility)
|
||||
self.assertIsNone(sot.region)
|
||||
self.assertIsNone(sot.service_name)
|
||||
self.assertEqual(1, len(sot.valid_versions))
|
||||
self.assertEqual('v1', sot.valid_versions[0].module)
|
||||
self.assertEqual('v1', sot.valid_versions[0].path)
|
||||
|
@ -23,6 +23,11 @@ class TestIdentityService(testtools.TestCase):
|
||||
self.assertEqual('public', sot.visibility)
|
||||
self.assertIsNone(sot.region)
|
||||
self.assertIsNone(sot.service_name)
|
||||
self.assertEqual(2, len(sot.valid_versions))
|
||||
self.assertEqual('v3', sot.valid_versions[0].module)
|
||||
self.assertEqual('v3', sot.valid_versions[0].path)
|
||||
self.assertEqual('v2', sot.valid_versions[1].module)
|
||||
self.assertEqual('v2', sot.valid_versions[1].path)
|
||||
|
||||
def test_admin_service(self):
|
||||
sot = identity_service.AdminService()
|
||||
|
@ -23,3 +23,6 @@ class TestImageService(testtools.TestCase):
|
||||
self.assertEqual('public', sot.visibility)
|
||||
self.assertIsNone(sot.region)
|
||||
self.assertIsNone(sot.service_name)
|
||||
self.assertEqual(1, len(sot.valid_versions))
|
||||
self.assertEqual('v1', sot.valid_versions[0].module)
|
||||
self.assertEqual('v1', sot.valid_versions[0].path)
|
||||
|
@ -23,3 +23,6 @@ class TestNetworkService(testtools.TestCase):
|
||||
self.assertEqual('public', sot.visibility)
|
||||
self.assertIsNone(sot.region)
|
||||
self.assertIsNone(sot.service_name)
|
||||
self.assertEqual(1, len(sot.valid_versions))
|
||||
self.assertEqual('v2', sot.valid_versions[0].module)
|
||||
self.assertEqual('v2.0', sot.valid_versions[0].path)
|
||||
|
@ -23,3 +23,6 @@ class TestObjectStoreService(testtools.TestCase):
|
||||
self.assertEqual('public', sot.visibility)
|
||||
self.assertIsNone(sot.region)
|
||||
self.assertIsNone(sot.service_name)
|
||||
self.assertEqual(1, len(sot.valid_versions))
|
||||
self.assertEqual('v1', sot.valid_versions[0].module)
|
||||
self.assertEqual('v1', sot.valid_versions[0].path)
|
||||
|
@ -23,3 +23,6 @@ class TestOrchestrationService(testtools.TestCase):
|
||||
self.assertEqual('public', sot.visibility)
|
||||
self.assertIsNone(sot.region)
|
||||
self.assertIsNone(sot.service_name)
|
||||
self.assertEqual(1, len(sot.valid_versions))
|
||||
self.assertEqual('v1', sot.valid_versions[0].module)
|
||||
self.assertEqual('v1', sot.valid_versions[0].path)
|
||||
|
@ -23,3 +23,6 @@ class TestTelemetryService(testtools.TestCase):
|
||||
self.assertEqual('public', sot.visibility)
|
||||
self.assertIsNone(sot.region)
|
||||
self.assertIsNone(sot.service_name)
|
||||
self.assertEqual(1, len(sot.valid_versions))
|
||||
self.assertEqual('v2', sot.valid_versions[0].module)
|
||||
self.assertEqual('v2', sot.valid_versions[0].path)
|
||||
|
@ -10,12 +10,21 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack.auth.identity import v2
|
||||
from openstack import connection
|
||||
from openstack import exceptions
|
||||
from openstack.tests import base
|
||||
from openstack import transport
|
||||
from openstack import user_preference
|
||||
|
||||
|
||||
class TestConnection(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestConnection, self).setUp()
|
||||
self.xport = transport.Transport()
|
||||
self.auth = v2.Auth(auth_url='http://127.0.0.1/v2', token='b')
|
||||
self.pref = user_preference.UserPreference()
|
||||
|
||||
def test_create_transport(self):
|
||||
conn = connection.Connection(authenticator='2', verify=True,
|
||||
user_agent='1')
|
||||
@ -73,8 +82,28 @@ class TestConnection(base.TestCase):
|
||||
)
|
||||
|
||||
def test_create_session(self):
|
||||
args = {'transport': '0', 'authenticator': '1', 'preference': '2'}
|
||||
args = {
|
||||
'transport': self.xport,
|
||||
'authenticator': self.auth,
|
||||
'preference': self.pref,
|
||||
}
|
||||
conn = connection.Connection(**args)
|
||||
self.assertEqual('0', conn.session.transport)
|
||||
self.assertEqual('1', conn.session.authenticator)
|
||||
self.assertEqual('2', conn.session.preference)
|
||||
self.assertEqual(self.xport, conn.session.transport)
|
||||
self.assertEqual(self.auth, conn.session.authenticator)
|
||||
self.assertEqual(self.pref, conn.session.preference)
|
||||
self.assertEqual('openstack.compute.v2._proxy',
|
||||
conn.compute.__class__.__module__)
|
||||
self.assertEqual('openstack.database.v1._proxy',
|
||||
conn.database.__class__.__module__)
|
||||
self.assertEqual('openstack.identity.v3._proxy',
|
||||
conn.identity.__class__.__module__)
|
||||
self.assertEqual('openstack.image.v1._proxy',
|
||||
conn.image.__class__.__module__)
|
||||
self.assertEqual('openstack.network.v2._proxy',
|
||||
conn.network.__class__.__module__)
|
||||
self.assertEqual('openstack.object_store.v1._proxy',
|
||||
conn.object_store.__class__.__module__)
|
||||
self.assertEqual('openstack.orchestration.v1._proxy',
|
||||
conn.orchestration.__class__.__module__)
|
||||
self.assertEqual('openstack.telemetry.v2._proxy',
|
||||
conn.telemetry.__class__.__module__)
|
||||
|
Loading…
Reference in New Issue
Block a user