diff --git a/smaug/tests/fullstack/smaug_base.py b/smaug/tests/fullstack/smaug_base.py index 1ed543e5..72c277fe 100644 --- a/smaug/tests/fullstack/smaug_base.py +++ b/smaug/tests/fullstack/smaug_base.py @@ -18,6 +18,10 @@ import os_client_config from oslotest import base from time import sleep +import utils + +PLAN_NORMAL_NAME = "My plan1" +PLAN_NORMAL_PARAM = {"OS::Nova::Server": {"consistency": "os"}} def _get_cloud_config(cloud='devstack-admin'): @@ -90,7 +94,7 @@ def _get_cinder_client_from_creds(): def _get_nova_client_from_creds(): - api_version = "2.29" + api_version = "2.26" cloud_config = _get_cloud_config() keystone_session = cloud_config.get_session_client("compute") keystone_auth = cloud_config.get_auth() @@ -114,6 +118,19 @@ def _get_nova_client_from_creds(): return client +def _get_keystone_endpoint_from_creds(): + cloud_config = _get_cloud_config() + keystone_session = cloud_config.get_session_client("identity") + keystone_auth = cloud_config.get_auth() + region_name = cloud_config.get_region_name() + service_type = "identity" + endpoint = keystone_auth.get_endpoint( + keystone_session, + service_type=service_type, + region_name=region_name) + return endpoint + + class SmaugBaseTest(base.BaseTestCase): """Basic class for Smaug fullstack testing @@ -121,16 +138,19 @@ class SmaugBaseTest(base.BaseTestCase): including the various clients (smaug) and common setup/cleanup code. """ + def setUp(self): super(SmaugBaseTest, self).setUp() self.cinder_client = _get_cinder_client_from_creds() self.nova_client = _get_nova_client_from_creds() self.smaug_client = _get_smaug_client_from_creds() + self.keystone_endpoint = _get_keystone_endpoint_from_creds() def tearDown(self): self.cleanup_plans() self.cleanup_volumes() self.cleanup_backup_volumes() + self.cleanup_novas() super(SmaugBaseTest, self).tearDown() def provider_list(self): @@ -145,6 +165,51 @@ class SmaugBaseTest(base.BaseTestCase): self.cinder_client.volumes.delete(volume_id) sleep(30) + def create_plan(self, plan_name, provider_id, volume, parameters): + resources = [{"id": volume.id, + "type": "OS::Cinder::Volume", + "name": volume.name}] + plan = self.smaug_client.plans.create(plan_name, provider_id, + resources, parameters) + return plan + + def check_volume_status(self, volume_id): + volume = self.cinder_client.volumes.get(volume_id) + if hasattr(volume, "status"): + if "available" == volume.status: + return True + else: + return False + else: + return False + + def create_checkpoint(self, provider_id, plan_id, volume_id): + checkpoint = self.smaug_client.checkpoints.create(provider_id, plan_id) + sleep(15) + utils.wait_until_true( + lambda: self.check_volume_status(volume_id), + timeout=320, + sleep=30, + exception=Exception("Create Checkpoint Failed.") + ) + # wait for sync + sleep(120) + return checkpoint + + def delete_checkpoint(self, provider_id, checkpoint_id): + self.smaug_client.checkpoints.delete(provider_id, checkpoint_id) + sleep(60) + + def create_restore(self, provider_id, checkpoint_id, + restore_target, parameters): + restore = self.smaug_client.restores.create(provider_id, + checkpoint_id, + restore_target, + parameters) + # wait for sync + sleep(190) + return restore + def cleanup_plans(self): plans = self.smaug_client.plans.list() for plan in plans: @@ -163,3 +228,10 @@ class SmaugBaseTest(base.BaseTestCase): if "available" == backup.status: self.cinder_client.backups.delete(backup.id) sleep(18) + + def cleanup_novas(self): + novas = self.nova_client.servers.list() + for nova in novas: + if "available" == nova.status: + self.nova_client.servers.delete(nova.id) + sleep(20) diff --git a/smaug/tests/fullstack/test_checkpoints.py b/smaug/tests/fullstack/test_checkpoints.py new file mode 100644 index 00000000..6650690c --- /dev/null +++ b/smaug/tests/fullstack/test_checkpoints.py @@ -0,0 +1,71 @@ +# 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 smaug.tests.fullstack import smaug_base + + +class CheckpointsTest(smaug_base.SmaugBaseTest): + """Test Checkpoints operation """ + + def test_checkpoint_create(self): + providers = self.provider_list() + self.assertTrue(len(providers)) + provider_id = providers[0].id + + volume = self.create_volume(1, "Volume1") + plan = self.create_plan(smaug_base.PLAN_NORMAL_NAME, + provider_id, + volume, + smaug_base.PLAN_NORMAL_PARAM) + plan_id = plan.get("id") + + backups = self.cinder_client.backups.list() + before_num = len(backups) + + checkpoint = self.create_checkpoint(provider_id, plan_id, volume.id) + + backups_ = self.cinder_client.backups.list() + after_num = len(backups_) + self.assertEqual(1, after_num - before_num) + + # cleanup + self.delete_checkpoint(provider_id, checkpoint["id"]) + self.smaug_client.plans.delete(plan_id) + self.delete_volume(volume.id) + + def test_checkpoint_delete(self): + providers = self.provider_list() + self.assertTrue(len(providers)) + provider_id = providers[0].id + + volume = self.create_volume(1, "Volume1") + plan = self.create_plan(smaug_base.PLAN_NORMAL_NAME, + provider_id, + volume, + smaug_base.PLAN_NORMAL_PARAM) + plan_id = plan.get("id") + + backups = self.smaug_client.checkpoints.list(provider_id) + before_num = len(backups) + + checkpoint = self.create_checkpoint(provider_id, plan_id, volume.id) + # checkpoint_ = self.smaug_client.checkpoints.get(provider_id, + # checkpoint['id']) + # self.assertEqual("committed", checkpoint_.status) + self.delete_checkpoint(provider_id, checkpoint["id"]) + backups_ = self.smaug_client.checkpoints.list(provider_id) + after_num = len(backups_) + self.assertEqual(before_num, after_num) + + # cleanup + self.smaug_client.plans.delete(plan_id) + self.delete_volume(volume.id) diff --git a/smaug/tests/fullstack/test_plans.py b/smaug/tests/fullstack/test_plans.py index fad1ab39..aae6a7c1 100644 --- a/smaug/tests/fullstack/test_plans.py +++ b/smaug/tests/fullstack/test_plans.py @@ -16,106 +16,129 @@ from smaug.tests.fullstack import smaug_base class PlansTest(smaug_base.SmaugBaseTest): """Test Plans operation""" - def create_plan(self, provider_id, volume_id): - plan1 = self.smaug_client.plans.create( - "My plan app1", - provider_id, - [{"id": volume_id, - "type": "OS::Cinder::Volume", - "name": "fake_name"}], - {"OS::Nova::Server": {"consistency": "os"}}) - plan2 = self.smaug_client.plans.create( - "My plan app2", - provider_id, - [{"id": volume_id, - "type": "OS::Cinder::Volume", - "name": "fake_name"}], - {"OS::Nova::Server": {"consistency": "os"}}) - return plan1, plan2 - def test_plans_create(self): - # retrieve providers providers = self.provider_list() self.assertTrue(len(providers)) - # create volume - volume = self.create_volume(1) - # get num of plans before creating + provider_id = providers[0].id + plans = self.smaug_client.plans.list() before_num = len(plans) - # create plan - plan1, plan2 = self.create_plan(providers[0].id, volume.id) - # get num of plans after creating + + volume = self.create_volume(1) + plan1 = self.create_plan(smaug_base.PLAN_NORMAL_NAME, + provider_id, + volume, + smaug_base.PLAN_NORMAL_PARAM) + plan2 = self.create_plan(smaug_base.PLAN_NORMAL_NAME, + provider_id, + volume, + smaug_base.PLAN_NORMAL_PARAM) + plans_ = self.smaug_client.plans.list() after_num = len(plans_) self.assertEqual(2, after_num - before_num) + + # cleanup self.smaug_client.plans.delete(plan1.get("id")) self.smaug_client.plans.delete(plan2.get("id")) self.delete_volume(volume.id) def test_plans_list(self): self.cleanup_plans() - # retrieve providers + providers = self.provider_list() self.assertTrue(len(providers)) - # create plan + provider_id = providers[0].id + volume = self.create_volume(1) - plan1, plan2 = self.create_plan(providers[0].id, volume.id) - # list plans after creating + plan1 = self.create_plan(smaug_base.PLAN_NORMAL_NAME, + provider_id, + volume, + smaug_base.PLAN_NORMAL_PARAM) + plan2 = self.create_plan(smaug_base.PLAN_NORMAL_NAME, + provider_id, + volume, + smaug_base.PLAN_NORMAL_PARAM) + plan_item = self.smaug_client.plans.list() self.assertEqual(2, len(plan_item)) + + # cleanup self.smaug_client.plans.delete(plan1.get("id")) self.smaug_client.plans.delete(plan2.get("id")) self.delete_volume(volume.id) def test_plans_get(self): - # retrieve providers providers = self.provider_list() self.assertTrue(len(providers)) - # create plan + provider_id = providers[0].id + volume = self.create_volume(1) - plan1, plan2 = self.create_plan(providers[0].id, volume.id) - # get plan + plan1 = self.create_plan("My plan app1", + provider_id, + volume, + smaug_base.PLAN_NORMAL_PARAM) + plan2 = self.create_plan("My plan app2", + provider_id, + volume, + smaug_base.PLAN_NORMAL_PARAM) + plan_item1 = self.smaug_client.plans.get(plan1.get("id")) self.assertEqual("My plan app1", plan_item1.name) plan_item2 = self.smaug_client.plans.get(plan2.get("id")) self.assertEqual("My plan app2", plan_item2.name) + + # cleanup self.smaug_client.plans.delete(plan1.get("id")) self.smaug_client.plans.delete(plan2.get("id")) self.delete_volume(volume.id) def test_plans_update(self): - # retrieve providers providers = self.provider_list() self.assertTrue(len(providers)) - # create plan - volume = self.create_volume(1, "Volume1") - plan1, plan2 = self.create_plan(providers[0].id, volume.id) - # get old plan + provider_id = providers[0].id + + volume1 = self.create_volume(1, "Volume1") + volume2 = self.create_volume(1, "Volume2") + plan1 = self.create_plan("My plan app1", + provider_id, + volume1, + smaug_base.PLAN_NORMAL_PARAM) + plan2 = self.create_plan("My plan app2", + provider_id, + volume2, + smaug_base.PLAN_NORMAL_PARAM) + plan_old = self.smaug_client.plans.get(plan1.get("id")) self.assertEqual("My plan app1", plan_old.name) self.assertEqual("suspended", plan_old.status) - self.assertEqual([{"id": volume.id, + self.assertEqual([{"id": volume1.id, "type": "OS::Cinder::Volume", - "name": "fake_name"}], + "name": volume1.name}], plan_old.resources) + # update name data = {"name": "fake_plan"} plan_item = self.smaug_client.plans.update(plan1.get("id"), data) self.assertEqual("fake_plan", plan_item.name) + # update resources - data = {"resources": [{"id": volume.id, + data = {"resources": [{"id": volume2.id, "type": "OS::Cinder::Volume", - "name": volume.name}]} + "name": volume2.name}]} plan_item = self.smaug_client.plans.update(plan1.get("id"), data) - self.assertEqual([{"id": volume.id, + self.assertEqual([{"id": volume2.id, "type": "OS::Cinder::Volume", - "name": volume.name}], + "name": volume2.name}], plan_item.resources) + # update status data = {"status": "started"} plan_item = self.smaug_client.plans.update(plan1.get("id"), data) self.assertEqual("started", plan_item.status) + # cleanup self.smaug_client.plans.delete(plan1.get("id")) self.smaug_client.plans.delete(plan2.get("id")) - self.delete_volume(volume.id) + self.delete_volume(volume1.id) + self.delete_volume(volume2.id) diff --git a/smaug/tests/fullstack/test_protectables.py b/smaug/tests/fullstack/test_protectables.py index 632a4ee7..fdaef105 100644 --- a/smaug/tests/fullstack/test_protectables.py +++ b/smaug/tests/fullstack/test_protectables.py @@ -10,22 +10,34 @@ # License for the specific language governing permissions and limitations # under the License. - from smaug.tests.fullstack import smaug_base -import time +from time import sleep class ProtectablesTest(smaug_base.SmaugBaseTest): - """Test Protectables operation""" + """Test Protectables operation """ - def create_volume(self, size): - volume = self.cinder_client.volumes.create(size) - time.sleep(5) - return volume + def create_nova(self, name, image, flavor, key_name=None): + nova = self.nova_client.servers.create(name, image, flavor, + key_name=key_name) + sleep(50) + return nova - def delete_volume(self, volume_id): - self.cinder_client.volumes.delete(volume_id) - time.sleep(15) + def delete_nova(self, instance_id): + self.nova_client.servers.delete(instance_id) + sleep(50) + + def create_server_volume(self, server_id, volume_id, device=None): + attach_volume = self.nova_client.volumes.create_server_volume( + server_id, volume_id, device) + sleep(85) + return attach_volume + + def delete_server_volume(self, server_id, volume_id): + detach_volume = self.nova_client.volumes.delete_server_volume( + server_id, volume_id) + sleep(85) + return detach_volume def test_protectables_list(self): res = self.smaug_client.protectables.list() @@ -34,18 +46,57 @@ class ProtectablesTest(smaug_base.SmaugBaseTest): def test_protectables_get_with_project(self): protectable_type = 'OS::Keystone::Project' res = self.smaug_client.protectables.get(protectable_type) - dependent_types = ['OS::Cinder::Volume', 'OS::Nova::Server'] - self.assertEqual(dependent_types, res.dependent_types) + self.assertTrue(len(res.dependent_types)) def test_protectables_list_instances(self): res_list = self.smaug_client.protectables.list_instances( 'OS::Cinder::Volume') before_num = len(res_list) - volume_1 = self.create_volume(1) - volume_2 = self.create_volume(1) + volume_1 = self.create_volume(1, "volume1-L") + volume_2 = self.create_volume(1, "volume2-L") res = self.smaug_client.protectables.list_instances( 'OS::Cinder::Volume') after_num = len(res) self.assertEqual(2, after_num - before_num) self.delete_volume(volume_1.id) self.delete_volume(volume_2.id) + + def test_protectables_get_with_server(self): + res_list = self.smaug_client.protectables.list_instances( + 'OS::Nova::Server') + flavors = self.nova_client.flavors.list() + images = self.nova_client.images.list() + ins_before = self.nova_client.servers.list() + oskey = self.nova_client.keypairs.create("oskeypriv") + instance = self.create_nova("osinstance", + images[0], + flavors[0], + key_name=oskey.name) + server_list = self.smaug_client.protectables.list_instances( + 'OS::Nova::Server') + self.assertEqual(1, len(server_list) - len(res_list)) + ins_list = self.nova_client.servers.list() + self.assertEqual(1, len(ins_list) - len(ins_before)) + self.nova_client.keypairs.delete(oskey.name) + self.delete_nova(instance.id) + + def test_protectables_get_with_attach_volume(self): + flavors = self.nova_client.flavors.list() + images = self.nova_client.images.list() + volume = self.create_volume(1, "fake_name") + oskey = self.nova_client.keypairs.create("oskeypriv") + instance = self.create_nova("osinstance", + images[0], + flavors[0], + key_name=oskey.name) + self.create_server_volume(instance.id, volume.id, r"/dev/vdc") + volume_res = self.cinder_client.volumes.get(volume.id) + ins_res = self.smaug_client.protectables.get_instance( + 'OS::Nova::Server', volume_res.attachments[0]["server_id"]) + self.assertTrue(ins_res.dependent_resources) + self.assertEqual('OS::Cinder::Volume', + ins_res.dependent_resources[0]["type"]) + self.delete_server_volume(instance.id, volume.id) + self.nova_client.keypairs.delete(oskey.name) + self.delete_volume(volume.id) + self.delete_nova(instance.id) diff --git a/tox.ini b/tox.ini index cd7eb823..a022b7b0 100644 --- a/tox.ini +++ b/tox.ini @@ -15,6 +15,7 @@ commands = python setup.py test --slowest --testr-args='{posargs}' [testenv:fullstack] basepython = python2.7 setenv = OS_TEST_PATH=./smaug/tests/fullstack + OS_TEST_TIMEOUT=1800 commands = python setup.py test --slowest --testr-args="--concurrency=1" [testenv:pep8]