diff --git a/tobiko/config.py b/tobiko/config.py index e4d81c807..2bc6904b9 100644 --- a/tobiko/config.py +++ b/tobiko/config.py @@ -24,7 +24,8 @@ import tobiko LOG = log.getLogger(__name__) -CONFIG_MODULES = ['tobiko.openstack.keystone.config', +CONFIG_MODULES = ['tobiko.openstack.glance.config', + 'tobiko.openstack.keystone.config', 'tobiko.openstack.neutron.config', 'tobiko.openstack.nova.config', 'tobiko.shell.ssh.config', diff --git a/tobiko/openstack/glance/__init__.py b/tobiko/openstack/glance/__init__.py new file mode 100644 index 000000000..ecdb7dd67 --- /dev/null +++ b/tobiko/openstack/glance/__init__.py @@ -0,0 +1,25 @@ +# Copyright 2019 Red Hat +# +# 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 __future__ import absolute_import + +from tobiko.openstack.glance import _client +from tobiko.openstack.glance import _image + +glance_client = _client.glance_client +get_glance_client = _client.get_glance_client +GlanceClientFixture = _client.GlanceClientFixture +find_image = _client.find_image +list_images = _client.list_images + +GlanceImageFixture = _image.GlanceImageFixture diff --git a/tobiko/openstack/glance/_client.py b/tobiko/openstack/glance/_client.py new file mode 100644 index 000000000..5dfa52e59 --- /dev/null +++ b/tobiko/openstack/glance/_client.py @@ -0,0 +1,70 @@ +# Copyright 2019 Red Hat +# +# 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 __future__ import absolute_import + +from glanceclient.v2 import client as glanceclient + +import tobiko +from tobiko.openstack import _client +from tobiko.openstack import _find + + +class GlanceClientFixture(_client.OpenstackClientFixture): + + def init_client(self, session): + return glanceclient.Client(session=session) + + +class GlanceClientManager(_client.OpenstackClientManager): + + def create_client(self, session): + return GlanceClientFixture(session=session) + + +CLIENTS = GlanceClientManager() + + +def glance_client(obj): + if not obj: + return get_glance_client() + + if isinstance(obj, glanceclient.Client): + return obj + + fixture = tobiko.setup_fixture(obj) + if isinstance(fixture, GlanceClientFixture): + return fixture.client + + message = "Object {!r} is not a NovaClientFixture".format(obj) + raise TypeError(message) + + +def get_glance_client(session=None, shared=True, init_client=None, + manager=None): + manager = manager or CLIENTS + client = manager.get_client(session=session, shared=shared, + init_client=init_client) + tobiko.setup_fixture(client) + return client.client + + +def find_image(obj=None, properties=None, client=None, **params): + """Look for the unique network matching some property values""" + return _find.find_resource( + obj=obj, resource_type='image', properties=properties, + resources=list_images(client=client, **params), **params) + + +def list_images(client=None, **params): + return list(glance_client(client).images.list(**params)) diff --git a/tobiko/openstack/glance/_image.py b/tobiko/openstack/glance/_image.py new file mode 100644 index 000000000..6b3eb8d7f --- /dev/null +++ b/tobiko/openstack/glance/_image.py @@ -0,0 +1,59 @@ +# Copyright 2019 Red Hat +# +# 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 __future__ import absolute_import + +import tobiko +from tobiko.openstack.glance import _client +from tobiko.openstack import _find + + +class GlanceImageFixture(tobiko.SharedFixture): + + client = None + image = None + image_details = None + + def __init__(self, client=None, image=None): + super(GlanceImageFixture, self).__init__() + if client: + self.client = client + if image: + self.image = image + elif not self.image: + self.image = self.fixture_name + + def setup_fixture(self): + self.setup_client() + self.setup_image() + + def setup_client(self): + self.client = _client.glance_client(self.client) + + def setup_image(self): + try: + self.image_details = _client.find_image(self.image, + client=self.client) + except _find.ResourceNotFound: + self.image_details = self.create_image() + + def create_image(self): + raise NotImplementedError + + @property + def image_id(self): + return self.image_details['id'] + + @property + def image_name(self): + return self.image_details['name'] diff --git a/tobiko/openstack/glance/config.py b/tobiko/openstack/glance/config.py new file mode 100644 index 000000000..f7bcdef8e --- /dev/null +++ b/tobiko/openstack/glance/config.py @@ -0,0 +1,22 @@ +# Copyright 2019 Red Hat +# +# 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 __future__ import absolute_import + +from oslo_config import cfg + + +def register_tobiko_options(conf): + conf.register_opts( + group=cfg.OptGroup('glance'), + opts=[]) diff --git a/tobiko/openstack/images/__init__.py b/tobiko/openstack/images/__init__.py new file mode 100644 index 000000000..7cd3d609a --- /dev/null +++ b/tobiko/openstack/images/__init__.py @@ -0,0 +1,19 @@ +# Copyright 2019 Red Hat +# +# 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 __future__ import absolute_import + + +from tobiko.openstack.images import _cirros + +CirrosImageFixture = _cirros.CirrosImageFixture diff --git a/tobiko/openstack/images/_cirros.py b/tobiko/openstack/images/_cirros.py new file mode 100644 index 000000000..5802d252d --- /dev/null +++ b/tobiko/openstack/images/_cirros.py @@ -0,0 +1,41 @@ +# Copyright 2019 Red Hat +# +# 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 __future__ import absolute_import + + +from tobiko import config +from tobiko.openstack import glance + +CONF = config.CONF + + +class CirrosImageFixture(glance.GlanceImageFixture): + + @property + def image(self): + """glance image used to create a Nova server instance""" + return CONF.tobiko.nova.image + + @property + def username(self): + """username used to login to a Nova server instance""" + return CONF.tobiko.nova.username + + @property + def password(self): + """password used to login to a Nova server instance""" + return CONF.tobiko.nova.password + + def create_image(self): + raise NotImplementedError diff --git a/tobiko/tests/functional/openstack/test_glance.py b/tobiko/tests/functional/openstack/test_glance.py new file mode 100644 index 000000000..190d19450 --- /dev/null +++ b/tobiko/tests/functional/openstack/test_glance.py @@ -0,0 +1,37 @@ +# Copyright (c) 2019 Red Hat, Inc. +# +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from __future__ import absolute_import + +import testtools + +import tobiko +from tobiko.openstack import glance +from tobiko.openstack import images + + +class GlanceApiTestCase(testtools.TestCase): + """Tests network creation""" + + #: Stack of resources with a network with a gateway router + fixture = tobiko.required_setup_fixture(images.CirrosImageFixture) + + def test_find_image_with_id(self): + image = glance.find_image(self.fixture.image_id) + self.assertEqual(self.fixture.image_id, image['id']) + + def test_find_image_with_name(self): + image = glance.find_image(self.fixture.image_name) + self.assertEqual(self.fixture.image_name, image['name'])