Example #1
0
    def setUp(self):
        super(TestDatastoreVersion, self).setUp()
        util.init_db()
        models.update_datastore(name='test_ds', default_version=None)
        models.update_datastore_version(
            'test_ds', 'test_vr1', 'mysql',
            '154b350d-4d86-4214-9067-9c54b230c0da', 'pkg-1', 1)
        models.update_datastore_version(
            'test_ds', 'test_vr2', 'mysql',
            '154b350d-4d86-4214-9067-9c54b230c0da', 'pkg-1', 1)
        self.ds = models.Datastore.load('test_ds')
        self.ds_version2 = models.DatastoreVersion.load(self.ds, 'test_vr2')

        self.context = trove_testtools.TroveTestContext(self)
        self.req = Mock()
        self.req.environ = Mock()
        self.req.environ.__getitem__ = Mock(return_value=self.context)
        self.tenant_id = Mock()
        self.version_controller = DatastoreVersionController()
Example #2
0
    def setUp(self):
        super(TestDatastoreVersionController, self).setUp()
        self.controller = DatastoreVersionController()

        self.version = {
            "version": {
                "datastore_name": "test_dsx",
                "name": "test_vr1",
                "datastore_manager": "mysql",
                "image": "154b350d-4d86-4214-9067-9c54b230c0da",
                "packages": ["mysql-server-5.7"],
                "active": True,
                "default": False
            }
        }

        self.tenant_id = Mock()
        context = trove_testtools.TroveTestContext(self)
        self.req = Mock()
        self.req.environ = Mock()
        self.req.environ.__getitem__ = Mock(return_value=context)
Example #3
0
    def get_resources(self):
        resources = []

        instances = extensions.ResourceExtension(
            '{tenant_id}/mgmt/instances',
            MgmtInstanceController(),
            member_actions={'root': 'GET',
                            'diagnostics': 'GET',
                            'hwinfo': 'GET',
                            'rpc_ping': 'GET',
                            'action': 'POST'})
        resources.append(instances)

        clusters = extensions.ResourceExtension(
            '{tenant_id}/mgmt/clusters',
            MgmtClusterController(),
            member_actions={'action': 'POST'})
        resources.append(clusters)

        quota = extensions.ResourceExtension(
            '{tenant_id}/mgmt/quotas',
            QuotaController(),
            member_actions={})
        resources.append(quota)

        upgrade = extensions.ResourceExtension(
            '{tenant_id}/mgmt/instances/{instance_id}/upgrade',
            UpgradeController(),
            member_actions={})
        resources.append(upgrade)

        datastore_configuration_parameters = extensions.ResourceExtension(
            '{tenant_id}/mgmt/datastores/versions/{version_id}/parameters',
            conf_service.ConfigurationsParameterController(),
            member_actions={})
        resources.append(datastore_configuration_parameters)

        datastore_version = extensions.ResourceExtension(
            '{tenant_id}/mgmt/datastore-versions',
            DatastoreVersionController(),
            member_actions={})
        resources.append(datastore_version)

        return resources
Example #4
0
    def setUp(self):
        super(TestDatastoreVersion, self).setUp()
        util.init_db()
        models.update_datastore(name='test_ds', default_version=None)
        models.update_datastore_version(
            'test_ds', 'test_vr1', 'mysql',
            '154b350d-4d86-4214-9067-9c54b230c0da', 'pkg-1', '1')
        models.update_datastore_version(
            'test_ds', 'test_vr2', 'mysql',
            '154b350d-4d86-4214-9067-9c54b230c0da', 'pkg-1', '1')
        self.ds = models.Datastore.load('test_ds')
        self.ds_version2 = models.DatastoreVersion.load(self.ds, 'test_vr2')

        self.context = Mock()
        self.req = Mock()
        self.req.environ = Mock()
        self.req.environ.__getitem__ = Mock(return_value=self.context)
        self.tenant_id = Mock()
        self.version_controller = DatastoreVersionController()
    def setUp(self):
        super(TestDatastoreVersionController, self).setUp()
        self.controller = DatastoreVersionController()

        self.version = {
            "version": {
                "datastore_name": "test_dsx",
                "name": "test_vr1",
                "datastore_manager": "mysql",
                "image": "154b350d-4d86-4214-9067-9c54b230c0da",
                "packages": ["mysql-server-5.6"],
                "active": True,
                "default": False
            }
        }

        self.tenant_id = Mock()
        context = trove_testtools.TroveTestContext(self)
        self.req = Mock()
        self.req.environ = Mock()
        self.req.environ.__getitem__ = Mock(return_value=context)
Example #6
0
    def setUpClass(cls):
        util.init_db()
        cls.ds_name = cls.random_name('datastore')
        cls.ds_version_number = '5.7.30'
        models.update_datastore(name=cls.ds_name, default_version=None)

        models.update_datastore_version(cls.ds_name, 'test_vr1', 'mysql',
                                        cls.random_uuid(), '', 'pkg-1', 1)
        models.update_datastore_version(cls.ds_name,
                                        'test_vr2',
                                        'mysql',
                                        cls.random_uuid(),
                                        '',
                                        'pkg-1',
                                        1,
                                        version=cls.ds_version_number)

        cls.ds = models.Datastore.load(cls.ds_name)
        cls.ds_version1 = models.DatastoreVersion.load(cls.ds, 'test_vr1')
        cls.ds_version2 = models.DatastoreVersion.load(
            cls.ds, 'test_vr2', version=cls.ds_version_number)
        cls.version_controller = DatastoreVersionController()

        super(TestDatastoreVersionController, cls).setUpClass()
Example #7
0
class TestDatastoreVersion(trove_testtools.TestCase):
    def setUp(self):
        super(TestDatastoreVersion, self).setUp()
        util.init_db()
        models.update_datastore(name='test_ds', default_version=None)
        models.update_datastore_version(
            'test_ds', 'test_vr1', 'mysql',
            '154b350d-4d86-4214-9067-9c54b230c0da', 'pkg-1', 1)
        models.update_datastore_version(
            'test_ds', 'test_vr2', 'mysql',
            '154b350d-4d86-4214-9067-9c54b230c0da', 'pkg-1', 1)
        self.ds = models.Datastore.load('test_ds')
        self.ds_version2 = models.DatastoreVersion.load(self.ds, 'test_vr2')

        self.context = trove_testtools.TroveTestContext(self)
        self.req = Mock()
        self.req.environ = Mock()
        self.req.environ.__getitem__ = Mock(return_value=self.context)
        self.tenant_id = Mock()
        self.version_controller = DatastoreVersionController()

    def tearDown(self):
        super(TestDatastoreVersion, self).tearDown()

    @patch.object(glance_remote, 'create_glance_client')
    def test_version_create(self, mock_glance_client):
        body = {
            "version": {
                "datastore_name": "test_ds",
                "name": "test_vr",
                "datastore_manager": "mysql",
                "image": "image-id",
                "packages": "test-pkg",
                "active": True,
                "default": True
            }
        }
        output = self.version_controller.create(self.req, body, self.tenant_id)
        self.assertEqual(202, output.status)

    @patch.object(glance_remote, 'create_glance_client')
    @patch.object(models.DatastoreVersion, 'load')
    def test_fail_already_exists_version_create(self, mock_load,
                                                mock_glance_client):
        body = {
            "version": {
                "datastore_name": "test_ds",
                "name": "test_new_vr",
                "datastore_manager": "mysql",
                "image": "image-id",
                "packages": "test-pkg",
                "active": True,
                "default": True
            }
        }
        self.assertRaisesRegex(
            exception.DatastoreVersionAlreadyExists,
            "A datastore version with the name 'test_new_vr' already exists",
            self.version_controller.create, self.req, body, self.tenant_id)

    @patch.object(glance_remote, 'create_glance_client')
    def test_fail_image_not_found_version_create(self, mock_glance_client):
        mock_glance_client.return_value.images.get = Mock(
            side_effect=glance_exceptions.HTTPNotFound())
        body = {
            "version": {
                "datastore_name": "test_ds",
                "name": "test_vr",
                "datastore_manager": "mysql",
                "image": "image-id",
                "packages": "test-pkg",
                "active": True,
                "default": True
            }
        }
        self.assertRaisesRegex(exception.ImageNotFound,
                               "Image image-id cannot be found.",
                               self.version_controller.create, self.req, body,
                               self.tenant_id)

    def test_version_delete(self):
        ds_version1 = models.DatastoreVersion.load(self.ds, 'test_vr1')

        output = self.version_controller.delete(self.req, self.tenant_id,
                                                ds_version1.id)
        err_msg = ("Datastore version '%s' cannot be found." % ds_version1.id)

        self.assertEqual(202, output.status)

        # Try to find deleted version, this should raise exception.
        self.assertRaisesRegex(exception.DatastoreVersionNotFound, err_msg,
                               models.DatastoreVersion.load_by_uuid,
                               ds_version1.id)

    @patch.object(glance_remote, 'create_glance_client')
    def test_version_update(self, mock_client):
        body = {"image": "c022f4dc-76ed-4e3f-a25e-33e031f43f8b"}
        output = self.version_controller.edit(self.req, body, self.tenant_id,
                                              self.ds_version2.id)
        self.assertEqual(202, output.status)

        # Find the details of version updated and match the updated attribute.
        test_ds_version = models.DatastoreVersion.load_by_uuid(
            self.ds_version2.id)
        self.assertEqual(body['image'], test_ds_version.image_id)

    @patch.object(glance_remote, 'create_glance_client')
    def test_version_update_fail_image_not_found(self, mock_glance_client):
        mock_glance_client.return_value.images.get = Mock(
            side_effect=glance_exceptions.HTTPNotFound())
        body = {"image": "non-existent-image-id"}

        self.assertRaisesRegex(exception.ImageNotFound,
                               "Image non-existent-image-id cannot be found.",
                               self.version_controller.edit, self.req, body,
                               self.tenant_id, self.ds_version2.id)

    @patch.object(models.DatastoreVersion, 'load_by_uuid')
    def test_version_index(self, mock_load):
        output = self.version_controller.index(self.req, self.tenant_id)
        self.assertEqual(200, output.status)

    def test_version_show(self):
        output = self.version_controller.show(self.req, self.tenant_id,
                                              self.ds_version2.id)
        self.assertEqual(200, output.status)
        self.assertEqual(self.ds_version2.id, output._data['version']['id'])
        self.assertEqual(self.ds_version2.name,
                         output._data['version']['name'])
        self.assertEqual(self.ds_version2.datastore_id,
                         output._data['version']['datastore_id'])
        self.assertEqual(self.ds_version2.datastore_name,
                         output._data['version']['datastore_name'])
        self.assertEqual(self.ds_version2.manager,
                         output._data['version']['datastore_manager'])
        self.assertEqual(self.ds_version2.image_id,
                         output._data['version']['image'])
        self.assertEqual(self.ds_version2.packages.split(','),
                         output._data['version']['packages'])
        self.assertEqual(self.ds_version2.active,
                         output._data['version']['active'])
Example #8
0
class TestDatastoreVersion(trove_testtools.TestCase):

    def setUp(self):
        super(TestDatastoreVersion, self).setUp()
        util.init_db()
        models.update_datastore(name='test_ds', default_version=None)
        models.update_datastore_version(
            'test_ds', 'test_vr1', 'mysql',
            '154b350d-4d86-4214-9067-9c54b230c0da', 'pkg-1', '1')
        models.update_datastore_version(
            'test_ds', 'test_vr2', 'mysql',
            '154b350d-4d86-4214-9067-9c54b230c0da', 'pkg-1', '1')
        self.ds = models.Datastore.load('test_ds')
        self.ds_version2 = models.DatastoreVersion.load(self.ds, 'test_vr2')

        self.context = Mock()
        self.req = Mock()
        self.req.environ = Mock()
        self.req.environ.__getitem__ = Mock(return_value=self.context)
        self.tenant_id = Mock()
        self.version_controller = DatastoreVersionController()

    def tearDown(self):
        super(TestDatastoreVersion, self).tearDown()

    @patch.object(remote, 'create_nova_client')
    def test_version_create(self, mock_nova_client):
        body = {"version": {
            "datastore_name": "test_ds",
            "name": "test_vr",
            "datastore_manager": "mysql",
            "image": "image-id",
            "packages": "test-pkg",
            "active": True,
            "default": True}}
        output = self.version_controller.create(
            self.req, body, self.tenant_id)
        self.assertEqual(202, output.status)

    @patch.object(remote, 'create_nova_client')
    @patch.object(models.DatastoreVersion, 'load')
    def test_fail_already_exists_version_create(self, mock_load,
                                                mock_nova_client):
        body = {"version": {
            "datastore_name": "test_ds",
            "name": "test_new_vr",
            "datastore_manager": "mysql",
            "image": "image-id",
            "packages": "test-pkg",
            "active": True,
            "default": True}}
        self.assertRaisesRegexp(
            exception.DatastoreVersionAlreadyExists,
            "A datastore version with the name 'test_new_vr' already exists",
            self.version_controller.create, self.req, body, self.tenant_id)

    @patch.object(remote, 'create_nova_client')
    def test_fail_image_not_found_version_create(self, mock_nova_client):
        mock_nova_client.return_value.images.get = Mock(
            side_effect=nova_exceptions.NotFound(404,
                                                 "Image id not found image-id"
                                                 ))
        body = {"version": {
            "datastore_name": "test_ds",
            "name": "test_vr",
            "datastore_manager": "mysql",
            "image": "image-id",
            "packages": "test-pkg",
            "active": True,
            "default": True}}
        self.assertRaisesRegexp(
            exception.ImageNotFound,
            "Image image-id cannot be found.",
            self.version_controller.create, self.req, body, self.tenant_id)

    def test_version_delete(self):
        ds_version1 = models.DatastoreVersion.load(self.ds, 'test_vr1')

        output = self.version_controller.delete(self.req,
                                                self.tenant_id,
                                                ds_version1.id)
        err_msg = ("Datastore version '%s' cannot be found." %
                   ds_version1.id)

        self.assertEqual(202, output.status)

        # Try to find deleted version, this should raise exception.
        self.assertRaisesRegexp(
            exception.DatastoreVersionNotFound,
            err_msg, models.DatastoreVersion.load_by_uuid, ds_version1.id)

    @patch.object(remote, 'create_nova_client')
    def test_version_update(self, mock_client):
        body = {"image": "c022f4dc-76ed-4e3f-a25e-33e031f43f8b"}
        output = self.version_controller.edit(self.req, body,
                                              self.tenant_id,
                                              self.ds_version2.id)
        self.assertEqual(202, output.status)

        # Find the details of version updated and match the updated attribute.
        test_ds_version = models.DatastoreVersion.load_by_uuid(
            self.ds_version2.id)
        self.assertEqual(body['image'], test_ds_version.image_id)

    @patch.object(remote, 'create_nova_client')
    def test_version_update_fail_image_not_found(self, mock_nova_client):
        mock_nova_client.return_value.images.get = Mock(
            side_effect=nova_exceptions.NotFound(404,
                                                 "Image id not found image-id"
                                                 ))
        body = {"image": "non-existent-image-id"}

        self.assertRaisesRegexp(
            exception.ImageNotFound,
            "Image non-existent-image-id cannot be found.",
            self.version_controller.edit, self.req, body,
            self.tenant_id, self.ds_version2.id)

    @patch.object(models.DatastoreVersion, 'load_by_uuid')
    def test_version_index(self, mock_load):
        output = self.version_controller.index(
            self.req, self.tenant_id)
        self.assertEqual(200, output.status)

    def test_version_show(self):
        output = self.version_controller.show(
            self.req, self.tenant_id, self.ds_version2.id)
        self.assertEqual(200, output.status)
        self.assertEqual(self.ds_version2.id,
                         output._data['version']['id'])
        self.assertEqual(self.ds_version2.name,
                         output._data['version']['name'])
        self.assertEqual(self.ds_version2.datastore_id,
                         output._data['version']['datastore_id'])
        self.assertEqual(self.ds_version2.datastore_name,
                         output._data['version']['datastore_name'])
        self.assertEqual(self.ds_version2.manager,
                         output._data['version']['datastore_manager'])
        self.assertEqual(self.ds_version2.image_id,
                         output._data['version']['image'])
        self.assertEqual(self.ds_version2.packages.split(','),
                         output._data['version']['packages'])
        self.assertEqual(self.ds_version2.active,
                         output._data['version']['active'])
Example #9
0
class TestDatastoreVersionController(trove_testtools.TestCase):
    def setUp(self):
        super(TestDatastoreVersionController, self).setUp()
        self.controller = DatastoreVersionController()

        self.version = {
            "version": {
                "datastore_name": "test_dsx",
                "name": "test_vr1",
                "datastore_manager": "mysql",
                "image": "154b350d-4d86-4214-9067-9c54b230c0da",
                "packages": ["mysql-server-5.7"],
                "active": True,
                "default": False
            }
        }

        self.tenant_id = Mock()
        context = trove_testtools.TroveTestContext(self)
        self.req = Mock()
        self.req.environ = Mock()
        self.req.environ.__getitem__ = Mock(return_value=context)

    def test_get_schema_create(self):
        schema = self.controller.get_schema('create', self.version)
        self.assertIsNotNone(schema)
        self.assertIn('version', schema['properties'])

    def test_validate_create(self):
        body = self.version
        schema = self.controller.get_schema('create', body)
        validator = jsonschema.Draft4Validator(schema)
        self.assertTrue(validator.is_valid(body))

    def test_validate_create_blankname(self):
        body = self.version
        body['version']['name'] = "     "
        schema = self.controller.get_schema('create', body)
        validator = jsonschema.Draft4Validator(schema)
        self.assertFalse(validator.is_valid(body))
        errors = sorted(validator.iter_errors(body), key=lambda e: e.path)
        self.assertThat(len(errors), Is(1))
        self.assertThat(errors[0].message,
                        Equals("'     ' does not match '^.*[0-9a-zA-Z]+.*$'"))

    def test_validate_create_blank_datastore(self):
        body = self.version
        body['version']['datastore_name'] = ""
        schema = self.controller.get_schema('create', body)
        validator = jsonschema.Draft4Validator(schema)
        self.assertFalse(validator.is_valid(body))
        errors = sorted(validator.iter_errors(body), key=lambda e: e.path)
        error_messages = [error.message for error in errors]
        self.assertThat(len(errors), Is(2))
        self.assertIn("'' is too short", error_messages)
        self.assertIn("'' does not match '^.*[0-9a-zA-Z]+.*$'", error_messages)

    @patch.object(clients, 'create_glance_client')
    @patch.object(datastore_models.Datastore, 'load')
    @patch.object(datastore_models.DatastoreVersion,
                  'load',
                  side_effect=exception.DatastoreVersionNotFound)
    @patch.object(datastore_models, 'update_datastore_version')
    def test_create_datastore_versions(self, mock_ds_version_create,
                                       mock_ds_version_load, mock_ds_load,
                                       mock_glance_client):
        body = self.version
        mock_ds_load.return_value.name = 'test_dsx'

        self.controller.create(self.req, body, self.tenant_id)
        mock_ds_version_create.assert_called_with(
            'test_dsx', 'test_vr1', 'mysql',
            '154b350d-4d86-4214-9067-9c54b230c0da', 'mysql-server-5.7', True)

    @patch.object(datastore_models.DatastoreVersion, 'load_by_uuid')
    def test_show_ds_version(self, mock_ds_version_load):
        id = Mock()

        self.controller.show(self.req, self.tenant_id, id)
        mock_ds_version_load.assert_called_with(id)

    @patch('trove.configuration.models.DBConfiguration.find_all')
    @patch('trove.backup.models.DBBackup.find_all')
    @patch('trove.instance.models.DBInstance.find_all')
    @patch.object(datastore_models.Datastore, 'load')
    @patch.object(datastore_models.DatastoreVersion, 'load_by_uuid')
    def test_delete_ds_version(self, mock_ds_version_load, mock_ds_load,
                               mock_instance_find, mock_backup_find,
                               mock_config_find):
        ds_version_id = Mock()
        ds_version = Mock()
        mock_ds_version_load.return_value = ds_version
        self.controller.delete(self.req, self.tenant_id, ds_version_id)
        ds_version.delete.assert_called_with()

    @patch('trove.instance.models.DBInstance.find_all')
    def test_delete_ds_version_instance_in_use(self, mock_instance_find):
        mock_instance_find.return_value.all.return_value = [Mock()]

        self.assertRaises(exception.DatastoreVersionsInUse,
                          self.controller.delete, self.req, self.tenant_id,
                          'fake_version_id')

    @patch('trove.backup.models.DBBackup.find_all')
    @patch('trove.instance.models.DBInstance.find_all')
    def test_delete_ds_version_backup_in_use(self, mock_instance_find,
                                             mock_backup_find):
        mock_backup_find.return_value.all.return_value = [Mock()]

        self.assertRaises(exception.DatastoreVersionsInUse,
                          self.controller.delete, self.req, self.tenant_id,
                          'fake_version_id')

    @patch('trove.configuration.models.DBConfiguration.find_all')
    @patch('trove.backup.models.DBBackup.find_all')
    @patch('trove.instance.models.DBInstance.find_all')
    def test_delete_ds_version_config_in_use(self, mock_instance_find,
                                             mock_backup_find,
                                             mock_config_find):
        mock_config_find.return_value.all.return_value = [Mock()]

        self.assertRaises(exception.DatastoreVersionsInUse,
                          self.controller.delete, self.req, self.tenant_id,
                          'fake_version_id')

    @patch.object(datastore_models.DatastoreVersion, 'load_by_uuid')
    @patch.object(datastore_models.DatastoreVersions, 'load_all')
    def test_index_ds_version(self, mock_ds_version_load_all,
                              mock_ds_version_load_by_uuid):
        mock_id = Mock()
        mock_ds_version = Mock()
        mock_ds_version.id = mock_id
        mock_ds_version_load_all.return_value = [mock_ds_version]

        self.controller.index(self.req, self.tenant_id)
        mock_ds_version_load_all.assert_called_with(only_active=False)
        mock_ds_version_load_by_uuid.assert_called_with(mock_id)

    @patch.object(clients, 'create_glance_client')
    @patch.object(datastore_models.DatastoreVersion, 'load_by_uuid')
    @patch.object(datastore_models, 'update_datastore_version')
    def test_edit_datastore_versions(self, mock_ds_version_update,
                                     mock_ds_version_load, mock_glance_client):
        body = {'image': '21c8805a-a800-4bca-a192-3a5a2519044d'}

        mock_ds_version = MagicMock()
        type(mock_ds_version).datastore_name = PropertyMock(
            return_value=self.version['version']['datastore_name'])
        type(mock_ds_version).name = PropertyMock(
            return_value=self.version['version']['name'])
        type(mock_ds_version).image_id = PropertyMock(
            return_value=self.version['version']['image'])
        type(mock_ds_version).packages = PropertyMock(
            return_value=self.version['version']['packages'])
        type(mock_ds_version).active = PropertyMock(
            return_value=self.version['version']['active'])
        type(mock_ds_version).manager = PropertyMock(
            return_value=self.version['version']['datastore_manager'])
        mock_ds_version_load.return_value = mock_ds_version

        self.controller.edit(self.req, body, self.tenant_id, Mock())
        mock_ds_version_update.assert_called_with(
            'test_dsx', 'test_vr1', 'mysql',
            '21c8805a-a800-4bca-a192-3a5a2519044d', 'mysql-server-5.7', True)
class TestDatastoreVersionController(trove_testtools.TestCase):
    def setUp(self):
        super(TestDatastoreVersionController, self).setUp()
        self.controller = DatastoreVersionController()

        self.version = {
            "version": {
                "datastore_name": "test_dsx",
                "name": "test_vr1",
                "datastore_manager": "mysql",
                "image": "154b350d-4d86-4214-9067-9c54b230c0da",
                "packages": ["mysql-server-5.6"],
                "active": True,
                "default": False
            }
        }

        self.tenant_id = Mock()
        context = trove_testtools.TroveTestContext(self)
        self.req = Mock()
        self.req.environ = Mock()
        self.req.environ.__getitem__ = Mock(return_value=context)

    def test_get_schema_create(self):
        schema = self.controller.get_schema('create', self.version)
        self.assertIsNotNone(schema)
        self.assertTrue('version' in schema['properties'])

    def test_validate_create(self):
        body = self.version
        schema = self.controller.get_schema('create', body)
        validator = jsonschema.Draft4Validator(schema)
        self.assertTrue(validator.is_valid(body))

    def test_validate_create_blankname(self):
        body = self.version
        body['version']['name'] = "     "
        schema = self.controller.get_schema('create', body)
        validator = jsonschema.Draft4Validator(schema)
        self.assertFalse(validator.is_valid(body))
        errors = sorted(validator.iter_errors(body), key=lambda e: e.path)
        self.assertThat(len(errors), Is(1))
        self.assertThat(errors[0].message,
                        Equals("'     ' does not match '^.*[0-9a-zA-Z]+.*$'"))

    def test_validate_create_blank_datastore(self):
        body = self.version
        body['version']['datastore_name'] = ""
        schema = self.controller.get_schema('create', body)
        validator = jsonschema.Draft4Validator(schema)
        self.assertFalse(validator.is_valid(body))
        errors = sorted(validator.iter_errors(body), key=lambda e: e.path)
        error_messages = [error.message for error in errors]
        self.assertThat(len(errors), Is(2))
        self.assertIn("'' is too short", error_messages)
        self.assertIn("'' does not match '^.*[0-9a-zA-Z]+.*$'", error_messages)

    @patch.object(remote, 'create_nova_client')
    @patch.object(datastore_models.Datastore, 'load')
    @patch.object(datastore_models.DatastoreVersion, 'load',
                  side_effect=exception.DatastoreVersionNotFound)
    @patch.object(datastore_models, 'update_datastore_version')
    def test_create_datastore_versions(self, mock_ds_version_create,
                                       mock_ds_version_load,
                                       mock_ds_load, mock_nova_client):
        body = self.version
        mock_ds_load.return_value.name = 'test_dsx'

        self.controller.create(self.req, body, self.tenant_id)
        mock_ds_version_create.assert_called_with(
            'test_dsx', 'test_vr1', 'mysql',
            '154b350d-4d86-4214-9067-9c54b230c0da',
            'mysql-server-5.6', True)

    @patch.object(datastore_models.DatastoreVersion, 'load_by_uuid')
    def test_show_ds_version(self, mock_ds_version_load):
        id = Mock()

        self.controller.show(self.req, self.tenant_id, id)
        mock_ds_version_load.assert_called_with(id)

    @patch.object(datastore_models.Datastore, 'load')
    @patch.object(datastore_models.DatastoreVersion, 'load_by_uuid')
    def test_delete_ds_version(self, mock_ds_version_load, mock_ds_load):
        ds_version_id = Mock()
        ds_version = Mock()
        mock_ds_version_load.return_value = ds_version
        self.controller.delete(self.req, self.tenant_id, ds_version_id)
        ds_version.delete.assert_called_with()

    @patch.object(datastore_models.DatastoreVersion, 'load_by_uuid')
    @patch.object(datastore_models.DatastoreVersions, 'load_all')
    def test_index_ds_version(self, mock_ds_version_load_all,
                              mock_ds_version_load_by_uuid):
        mock_id = Mock()
        mock_ds_version = Mock()
        mock_ds_version.id = mock_id
        mock_ds_version_load_all.return_value = [mock_ds_version]

        self.controller.index(self.req, self.tenant_id)
        mock_ds_version_load_all.assert_called_with(only_active=False)
        mock_ds_version_load_by_uuid.assert_called_with(mock_id)

    @patch.object(remote, 'create_nova_client')
    @patch.object(datastore_models.DatastoreVersion, 'load_by_uuid')
    @patch.object(datastore_models, 'update_datastore_version')
    def test_edit_datastore_versions(self, mock_ds_version_update,
                                     mock_ds_version_load,
                                     mock_nova_client):
        body = {'image': '21c8805a-a800-4bca-a192-3a5a2519044d'}

        mock_ds_version = MagicMock()
        type(mock_ds_version).datastore_name = PropertyMock(
            return_value=self.version['version']['datastore_name'])
        type(mock_ds_version).name = PropertyMock(
            return_value=self.version['version']['name'])
        type(mock_ds_version).image_id = PropertyMock(
            return_value=self.version['version']['image'])
        type(mock_ds_version).packages = PropertyMock(
            return_value=self.version['version']['packages'])
        type(mock_ds_version).active = PropertyMock(
            return_value=self.version['version']['active'])
        type(mock_ds_version).manager = PropertyMock(
            return_value=self.version['version']['datastore_manager'])
        mock_ds_version_load.return_value = mock_ds_version

        self.controller.edit(self.req, body, self.tenant_id, Mock())
        mock_ds_version_update.assert_called_with(
            'test_dsx', 'test_vr1', 'mysql',
            '21c8805a-a800-4bca-a192-3a5a2519044d',
            'mysql-server-5.6', True)