Datastores improvements
List of improvements: - added default_version field in datastore show output - admin can list deactivated versions too - admin can see extanded info about datastore version (image_id, packages) - add possibility to retrive version by uuid (without specified datastore) Implements: blueprint datastore-type-version-followon Change-Id: I9b0c3547fb6a881a01db9e6e3d8d72077bc5ee29
This commit is contained in:
parent
68a5481911
commit
2296bdfcea
10
run_tests.py
10
run_tests.py
@ -74,17 +74,17 @@ def datastore_init():
|
||||
# Adds the datastore for mysql (needed to make most calls work).
|
||||
from trove.datastore import models
|
||||
|
||||
models.DBDatastore.create(id="a00000a0-00a0-0a00-00a0-000a000000aa",
|
||||
models.DBDatastore.create(id=CONFIG.dbaas_datastore_id,
|
||||
name=CONFIG.dbaas_datastore,
|
||||
default_version_id=
|
||||
"b00000b0-00b0-0b00-00b0-000b000000bb")
|
||||
CONFIG.dbaas_datastore_version_id)
|
||||
models.DBDatastore.create(id="e00000e0-00e0-0e00-00e0-000e000000ee",
|
||||
name='Test_Datastore_1',
|
||||
default_version_id=None)
|
||||
|
||||
models.DBDatastoreVersion.create(id="b00000b0-00b0-0b00-00b0-000b000000bb",
|
||||
models.DBDatastoreVersion.create(id=CONFIG.dbaas_datastore_version_id,
|
||||
datastore_id=
|
||||
"a00000a0-00a0-0a00-00a0-000a000000aa",
|
||||
CONFIG.dbaas_datastore_id,
|
||||
name=CONFIG.dbaas_datastore_version,
|
||||
manager="mysql",
|
||||
image_id=
|
||||
@ -93,7 +93,7 @@ def datastore_init():
|
||||
active=1)
|
||||
models.DBDatastoreVersion.create(id="d00000d0-00d0-0d00-00d0-000d000000dd",
|
||||
datastore_id=
|
||||
"a00000a0-00a0-0a00-00a0-000a000000aa",
|
||||
CONFIG.dbaas_datastore_id,
|
||||
name='mysql_inactive_version',
|
||||
manager="mysql",
|
||||
image_id=
|
||||
|
@ -49,6 +49,9 @@ class API(wsgi.Router):
|
||||
mapper.connect("/{tenant_id}/datastores/{datastore}/versions/{id}",
|
||||
controller=datastore_resource,
|
||||
action="version_show")
|
||||
mapper.connect("/{tenant_id}/datastores/versions/{uuid}",
|
||||
controller=datastore_resource,
|
||||
action="version_show_by_uuid")
|
||||
|
||||
def _instance_router(self, mapper):
|
||||
instance_resource = InstanceController().create_resource()
|
||||
|
@ -130,6 +130,12 @@ class DatastoreDefaultVersionNotFound(TroveError):
|
||||
message = _("Default version for datastore '%(datastore)s' not found.")
|
||||
|
||||
|
||||
class NoUniqueMatch(TroveError):
|
||||
|
||||
message = _("Multiple matches found for '%(name)s', i"
|
||||
"use an UUID to be more specific.")
|
||||
|
||||
|
||||
class OverLimit(TroveError):
|
||||
|
||||
internal_message = _("The server rejected the request due to its size or "
|
||||
|
@ -95,14 +95,25 @@ class DatastoreVersion(object):
|
||||
self.db_info = db_info
|
||||
|
||||
@classmethod
|
||||
def load(cls, id_or_name):
|
||||
def load(cls, datastore, id_or_name):
|
||||
try:
|
||||
return cls(DBDatastoreVersion.find_by(id=id_or_name))
|
||||
return cls(DBDatastoreVersion.find_by(datastore_id=datastore.id,
|
||||
id=id_or_name))
|
||||
except exception.ModelNotFoundError:
|
||||
try:
|
||||
return cls(DBDatastoreVersion.find_by(name=id_or_name))
|
||||
except exception.ModelNotFoundError:
|
||||
versions = DBDatastoreVersion.find_all(datastore_id=datastore.id,
|
||||
name=id_or_name)
|
||||
if versions.count() == 0:
|
||||
raise exception.DatastoreVersionNotFound(version=id_or_name)
|
||||
if versions.count() > 1:
|
||||
raise exception.NoUniqueMatch(name=id_or_name)
|
||||
return cls(versions.first())
|
||||
|
||||
@classmethod
|
||||
def load_by_uuid(cls, uuid):
|
||||
try:
|
||||
return cls(DBDatastoreVersion.find_by(id=uuid))
|
||||
except exception.ModelNotFoundError:
|
||||
raise exception.DatastoreVersionNotFound(version=uuid)
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
@ -139,10 +150,14 @@ class DatastoreVersions(object):
|
||||
self.db_info = db_info
|
||||
|
||||
@classmethod
|
||||
def load(cls, id_or_name, active=True):
|
||||
def load(cls, id_or_name, only_active=True):
|
||||
datastore = Datastore.load(id_or_name)
|
||||
return cls(DBDatastoreVersion.find_all(datastore_id=datastore.id,
|
||||
active=active))
|
||||
if only_active:
|
||||
versions = DBDatastoreVersion.find_all(datastore_id=datastore.id,
|
||||
active=True)
|
||||
else:
|
||||
versions = DBDatastoreVersion.find_all(datastore_id=datastore.id)
|
||||
return cls(versions)
|
||||
|
||||
def __iter__(self):
|
||||
for item in self.db_info:
|
||||
@ -158,7 +173,7 @@ def get_datastore_version(type=None, version=None):
|
||||
if not version:
|
||||
raise exception.DatastoreDefaultVersionNotFound(datastore=
|
||||
datastore.name)
|
||||
datastore_version = DatastoreVersion.load(version)
|
||||
datastore_version = DatastoreVersion.load(datastore, version)
|
||||
if datastore_version.datastore_id != datastore.id:
|
||||
raise exception.DatastoreNoVersion(datastore=datastore.name,
|
||||
version=datastore_version.name)
|
||||
@ -170,13 +185,14 @@ def get_datastore_version(type=None, version=None):
|
||||
|
||||
def update_datastore(name, default_version):
|
||||
db_api.configure_db(CONF)
|
||||
if default_version:
|
||||
version = DatastoreVersion.load(default_version)
|
||||
if not version.active:
|
||||
raise exception.DatastoreVersionInactive(version=
|
||||
version.name)
|
||||
try:
|
||||
datastore = DBDatastore.find_by(name=name)
|
||||
if default_version:
|
||||
version = DatastoreVersion.load(datastore, default_version)
|
||||
if not version.active:
|
||||
raise exception.DatastoreVersionInactive(version=
|
||||
version.name)
|
||||
datastore.default_version_id = version.id
|
||||
except exception.ModelNotFoundError:
|
||||
# Create a new one
|
||||
datastore = DBDatastore()
|
||||
@ -192,13 +208,14 @@ def update_datastore_version(datastore, name, manager, image_id, packages,
|
||||
db_api.configure_db(CONF)
|
||||
datastore = Datastore.load(datastore)
|
||||
try:
|
||||
version = DBDatastoreVersion.find_by(name=name)
|
||||
version = DBDatastoreVersion.find_by(datastore_id=datastore.id,
|
||||
name=name)
|
||||
except exception.ModelNotFoundError:
|
||||
# Create a new one
|
||||
version = DBDatastoreVersion()
|
||||
version.id = utils.generate_uuid()
|
||||
version.name = name
|
||||
version.datastore_id = datastore.id
|
||||
version.datastore_id = datastore.id
|
||||
version.manager = manager
|
||||
version.image_id = image_id
|
||||
version.packages = packages
|
||||
|
@ -34,13 +34,23 @@ class DatastoreController(wsgi.Controller):
|
||||
200)
|
||||
|
||||
def version_show(self, req, tenant_id, datastore, id):
|
||||
datastore, datastore_version = models.get_datastore_version(datastore,
|
||||
id)
|
||||
datastore = models.Datastore.load(datastore)
|
||||
datastore_version = models.DatastoreVersion.load(datastore, id)
|
||||
return wsgi.Result(views.DatastoreVersionView(datastore_version,
|
||||
req).data(), 200)
|
||||
|
||||
def version_show_by_uuid(self, req, tenant_id, uuid):
|
||||
datastore_version = models.DatastoreVersion.load_by_uuid(uuid)
|
||||
return wsgi.Result(views.DatastoreVersionView(datastore_version,
|
||||
req).data(), 200)
|
||||
|
||||
def version_index(self, req, tenant_id, datastore):
|
||||
datastore_versions = models.DatastoreVersions.load(datastore)
|
||||
context = req.environ[wsgi.CONTEXT_KEY]
|
||||
only_active = True
|
||||
if context.is_admin:
|
||||
only_active = False
|
||||
datastore_versions = models.DatastoreVersions.load(datastore,
|
||||
only_active)
|
||||
return wsgi.Result(views.
|
||||
DatastoreVersionsView(datastore_versions,
|
||||
req).data(), 200)
|
||||
|
@ -16,6 +16,7 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from trove.common import wsgi
|
||||
from trove.common.views import create_links
|
||||
|
||||
|
||||
@ -31,6 +32,9 @@ class DatastoreView(object):
|
||||
"name": self.datastore.name,
|
||||
"links": self._build_links(),
|
||||
}
|
||||
default_version = self.datastore.default_version_id
|
||||
if default_version:
|
||||
datastore_dict["default_version"] = default_version
|
||||
|
||||
return {"datastore": datastore_dict}
|
||||
|
||||
@ -61,14 +65,20 @@ class DatastoreVersionView(object):
|
||||
def __init__(self, datastore_version, req=None):
|
||||
self.datastore_version = datastore_version
|
||||
self.req = req
|
||||
self.context = req.environ[wsgi.CONTEXT_KEY]
|
||||
|
||||
def data(self):
|
||||
datastore_version_dict = {
|
||||
"id": self.datastore_version.id,
|
||||
"name": self.datastore_version.name,
|
||||
"datastore": self.datastore_version.datastore_id,
|
||||
"links": self._build_links(),
|
||||
}
|
||||
|
||||
if self.context.is_admin:
|
||||
datastore_version_dict['active'] = self.datastore_version.active
|
||||
datastore_version_dict['packages'] = (self.datastore_version.
|
||||
packages)
|
||||
datastore_version_dict['image'] = self.datastore_version.image_id
|
||||
return {"version": datastore_version_dict}
|
||||
|
||||
def _build_links(self):
|
||||
|
@ -0,0 +1,33 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
#
|
||||
# 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 sqlalchemy.schema import MetaData
|
||||
|
||||
from trove.db.sqlalchemy.migrate_repo.schema import Table
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
datastore_versions = Table('datastore_versions', meta, autoload=True)
|
||||
#modify column
|
||||
datastore_versions.c.name.alter(unique=False)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
# modify column:
|
||||
datastore_versions = Table('datastore_versions', meta, autoload=True)
|
||||
datastore_versions.c.name.alter(unique=True)
|
@ -122,7 +122,7 @@ class SimpleInstance(object):
|
||||
self.service_status = service_status
|
||||
self.root_pass = root_password
|
||||
self.ds_version = (datastore_models.DatastoreVersion.
|
||||
load(self.db_info.datastore_version_id))
|
||||
load_by_uuid(self.db_info.datastore_version_id))
|
||||
self.ds = (datastore_models.Datastore.
|
||||
load(self.ds_version.datastore_id))
|
||||
|
||||
|
@ -86,18 +86,20 @@ class Datastores(object):
|
||||
with TypeCheck('DatastoreVersion', version) as check:
|
||||
check.has_field("id", basestring)
|
||||
check.has_field("name", basestring)
|
||||
check.has_field("datastore", basestring)
|
||||
check.has_field("links", list)
|
||||
assert_equal(version.name, test_config.dbaas_datastore_version)
|
||||
|
||||
@test
|
||||
def test_datastore_version_datastore_not_found(self):
|
||||
try:
|
||||
assert_raises(exceptions.NotFound,
|
||||
self.rd_client.datastore_versions.get,
|
||||
NAME, NAME)
|
||||
except exceptions.BadRequest as e:
|
||||
assert_equal(e.message,
|
||||
"Datastore '%s' cannot be found." % NAME)
|
||||
def test_datastore_version_get_by_uuid_attrs(self):
|
||||
version = self.rd_client.datastore_versions.get_by_uuid(
|
||||
test_config.dbaas_datastore_version_id)
|
||||
with TypeCheck('DatastoreVersion', version) as check:
|
||||
check.has_field("id", basestring)
|
||||
check.has_field("name", basestring)
|
||||
check.has_field("datastore", basestring)
|
||||
check.has_field("links", list)
|
||||
assert_equal(version.name, test_config.dbaas_datastore_version)
|
||||
|
||||
@test
|
||||
def test_datastore_version_not_found(self):
|
||||
|
@ -52,7 +52,7 @@ class ResizeTestBase(TestCase):
|
||||
flavor_id=OLD_FLAVOR_ID,
|
||||
tenant_id=999,
|
||||
volume_size=None,
|
||||
datastore_version_id=test_config.dbaas_datastore_version,
|
||||
datastore_version_id=test_config.dbaas_datastore_version_id,
|
||||
task_status=InstanceTasks.RESIZING)
|
||||
self.server = self.mock.CreateMock(Server)
|
||||
self.instance = models.BuiltInstanceTasks(context,
|
||||
|
@ -52,7 +52,7 @@ class MgmtInstanceBase(object):
|
||||
self.db_info = DBInstance.create(
|
||||
name="instance",
|
||||
flavor_id=1,
|
||||
datastore_version_id=test_config.dbaas_datastore_version,
|
||||
datastore_version_id=test_config.dbaas_datastore_version_id,
|
||||
tenant_id=self.tenant_id,
|
||||
volume_size=None,
|
||||
task_status=InstanceTasks.NONE)
|
||||
|
@ -71,7 +71,10 @@ class TestConfig(object):
|
||||
'version_url': "http://localhost:8775/",
|
||||
'nova_url': "http://localhost:8774/v1.1",
|
||||
'dbaas_datastore': "mysql",
|
||||
'dbaas_datastore_id': "a00000a0-00a0-0a00-00a0-000a000000aa",
|
||||
'dbaas_datastore_version': "mysql-5.5",
|
||||
'dbaas_datastore_version_id': "b00000b0-00b0-0b00-00b0-"
|
||||
"000b000000bb",
|
||||
'instance_create_time': 16 * 60,
|
||||
'mysql_connection_method': {"type": "direct"},
|
||||
'typical_nova_image_name': None,
|
||||
|
@ -32,7 +32,7 @@ class FakeDBInstance(object):
|
||||
def __init__(self):
|
||||
self.id = None
|
||||
self.deleted = False
|
||||
self.datastore_version_id = test_config.dbaas_datastore_version
|
||||
self.datastore_version_id = test_config.dbaas_datastore_version_id
|
||||
self.server_status = "ACTIVE"
|
||||
self.task_status = FakeInstanceTask()
|
||||
|
||||
|
@ -65,7 +65,7 @@ class MockMgmtInstanceTest(TestCase):
|
||||
id='1',
|
||||
flavor_id='flavor_1',
|
||||
datastore_version_id=
|
||||
test_config.dbaas_datastore_version,
|
||||
test_config.dbaas_datastore_version_id,
|
||||
compute_instance_id='compute_id_1',
|
||||
server_id='server_id_1',
|
||||
tenant_id='tenant_id_1',
|
||||
@ -205,7 +205,11 @@ class TestNovaNotificationTransformer(MockMgmtInstanceTest):
|
||||
stub_datastore_version.id = "stub_datastore_version"
|
||||
stub_datastore_version.manager = "m0ng0"
|
||||
when(datastore_models.
|
||||
DatastoreVersion).load(any()).thenReturn(stub_datastore_version)
|
||||
DatastoreVersion).load(any(), any()).thenReturn(
|
||||
stub_datastore_version)
|
||||
when(datastore_models.
|
||||
DatastoreVersion).load_by_uuid(any()).thenReturn(
|
||||
stub_datastore_version)
|
||||
|
||||
stub_datastore = mock()
|
||||
stub_datastore.default_datastore_version = "stub_datastore_version"
|
||||
|
@ -140,7 +140,9 @@ class FreshInstanceTasksTest(testtools.TestCase):
|
||||
when(taskmanager_models.FreshInstanceTasks).name().thenReturn(
|
||||
'name')
|
||||
when(datastore_models.
|
||||
DatastoreVersion).load(any()).thenReturn(mock())
|
||||
DatastoreVersion).load(any(), any()).thenReturn(mock())
|
||||
when(datastore_models.
|
||||
DatastoreVersion).load_by_uuid(any()).thenReturn(mock())
|
||||
when(datastore_models.
|
||||
Datastore).load(any()).thenReturn(mock())
|
||||
taskmanager_models.FreshInstanceTasks.nova_client = fake_nova_client()
|
||||
|
Loading…
Reference in New Issue
Block a user