Merge "Datastores improvements"
This commit is contained in:
commit
dbf31a7447
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).
|
# Adds the datastore for mysql (needed to make most calls work).
|
||||||
from trove.datastore import models
|
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,
|
name=CONFIG.dbaas_datastore,
|
||||||
default_version_id=
|
default_version_id=
|
||||||
"b00000b0-00b0-0b00-00b0-000b000000bb")
|
CONFIG.dbaas_datastore_version_id)
|
||||||
models.DBDatastore.create(id="e00000e0-00e0-0e00-00e0-000e000000ee",
|
models.DBDatastore.create(id="e00000e0-00e0-0e00-00e0-000e000000ee",
|
||||||
name='Test_Datastore_1',
|
name='Test_Datastore_1',
|
||||||
default_version_id=None)
|
default_version_id=None)
|
||||||
|
|
||||||
models.DBDatastoreVersion.create(id="b00000b0-00b0-0b00-00b0-000b000000bb",
|
models.DBDatastoreVersion.create(id=CONFIG.dbaas_datastore_version_id,
|
||||||
datastore_id=
|
datastore_id=
|
||||||
"a00000a0-00a0-0a00-00a0-000a000000aa",
|
CONFIG.dbaas_datastore_id,
|
||||||
name=CONFIG.dbaas_datastore_version,
|
name=CONFIG.dbaas_datastore_version,
|
||||||
manager="mysql",
|
manager="mysql",
|
||||||
image_id=
|
image_id=
|
||||||
@ -93,7 +93,7 @@ def datastore_init():
|
|||||||
active=1)
|
active=1)
|
||||||
models.DBDatastoreVersion.create(id="d00000d0-00d0-0d00-00d0-000d000000dd",
|
models.DBDatastoreVersion.create(id="d00000d0-00d0-0d00-00d0-000d000000dd",
|
||||||
datastore_id=
|
datastore_id=
|
||||||
"a00000a0-00a0-0a00-00a0-000a000000aa",
|
CONFIG.dbaas_datastore_id,
|
||||||
name='mysql_inactive_version',
|
name='mysql_inactive_version',
|
||||||
manager="mysql",
|
manager="mysql",
|
||||||
image_id=
|
image_id=
|
||||||
|
@ -49,6 +49,9 @@ class API(wsgi.Router):
|
|||||||
mapper.connect("/{tenant_id}/datastores/{datastore}/versions/{id}",
|
mapper.connect("/{tenant_id}/datastores/{datastore}/versions/{id}",
|
||||||
controller=datastore_resource,
|
controller=datastore_resource,
|
||||||
action="version_show")
|
action="version_show")
|
||||||
|
mapper.connect("/{tenant_id}/datastores/versions/{uuid}",
|
||||||
|
controller=datastore_resource,
|
||||||
|
action="version_show_by_uuid")
|
||||||
|
|
||||||
def _instance_router(self, mapper):
|
def _instance_router(self, mapper):
|
||||||
instance_resource = InstanceController().create_resource()
|
instance_resource = InstanceController().create_resource()
|
||||||
|
@ -130,6 +130,12 @@ class DatastoreDefaultVersionNotFound(TroveError):
|
|||||||
message = _("Default version for datastore '%(datastore)s' not found.")
|
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):
|
class OverLimit(TroveError):
|
||||||
|
|
||||||
internal_message = _("The server rejected the request due to its size or "
|
internal_message = _("The server rejected the request due to its size or "
|
||||||
|
@ -95,14 +95,25 @@ class DatastoreVersion(object):
|
|||||||
self.db_info = db_info
|
self.db_info = db_info
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, id_or_name):
|
def load(cls, datastore, id_or_name):
|
||||||
try:
|
try:
|
||||||
return cls(DBDatastoreVersion.find_by(id=id_or_name))
|
return cls(DBDatastoreVersion.find_by(datastore_id=datastore.id,
|
||||||
except exception.ModelNotFoundError:
|
id=id_or_name))
|
||||||
try:
|
|
||||||
return cls(DBDatastoreVersion.find_by(name=id_or_name))
|
|
||||||
except exception.ModelNotFoundError:
|
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)
|
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
|
@property
|
||||||
def id(self):
|
def id(self):
|
||||||
@ -139,10 +150,14 @@ class DatastoreVersions(object):
|
|||||||
self.db_info = db_info
|
self.db_info = db_info
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, id_or_name, active=True):
|
def load(cls, id_or_name, only_active=True):
|
||||||
datastore = Datastore.load(id_or_name)
|
datastore = Datastore.load(id_or_name)
|
||||||
return cls(DBDatastoreVersion.find_all(datastore_id=datastore.id,
|
if only_active:
|
||||||
active=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):
|
def __iter__(self):
|
||||||
for item in self.db_info:
|
for item in self.db_info:
|
||||||
@ -158,7 +173,7 @@ def get_datastore_version(type=None, version=None):
|
|||||||
if not version:
|
if not version:
|
||||||
raise exception.DatastoreDefaultVersionNotFound(datastore=
|
raise exception.DatastoreDefaultVersionNotFound(datastore=
|
||||||
datastore.name)
|
datastore.name)
|
||||||
datastore_version = DatastoreVersion.load(version)
|
datastore_version = DatastoreVersion.load(datastore, version)
|
||||||
if datastore_version.datastore_id != datastore.id:
|
if datastore_version.datastore_id != datastore.id:
|
||||||
raise exception.DatastoreNoVersion(datastore=datastore.name,
|
raise exception.DatastoreNoVersion(datastore=datastore.name,
|
||||||
version=datastore_version.name)
|
version=datastore_version.name)
|
||||||
@ -170,13 +185,14 @@ def get_datastore_version(type=None, version=None):
|
|||||||
|
|
||||||
def update_datastore(name, default_version):
|
def update_datastore(name, default_version):
|
||||||
db_api.configure_db(CONF)
|
db_api.configure_db(CONF)
|
||||||
|
try:
|
||||||
|
datastore = DBDatastore.find_by(name=name)
|
||||||
if default_version:
|
if default_version:
|
||||||
version = DatastoreVersion.load(default_version)
|
version = DatastoreVersion.load(datastore, default_version)
|
||||||
if not version.active:
|
if not version.active:
|
||||||
raise exception.DatastoreVersionInactive(version=
|
raise exception.DatastoreVersionInactive(version=
|
||||||
version.name)
|
version.name)
|
||||||
try:
|
datastore.default_version_id = version.id
|
||||||
datastore = DBDatastore.find_by(name=name)
|
|
||||||
except exception.ModelNotFoundError:
|
except exception.ModelNotFoundError:
|
||||||
# Create a new one
|
# Create a new one
|
||||||
datastore = DBDatastore()
|
datastore = DBDatastore()
|
||||||
@ -192,7 +208,8 @@ def update_datastore_version(datastore, name, manager, image_id, packages,
|
|||||||
db_api.configure_db(CONF)
|
db_api.configure_db(CONF)
|
||||||
datastore = Datastore.load(datastore)
|
datastore = Datastore.load(datastore)
|
||||||
try:
|
try:
|
||||||
version = DBDatastoreVersion.find_by(name=name)
|
version = DBDatastoreVersion.find_by(datastore_id=datastore.id,
|
||||||
|
name=name)
|
||||||
except exception.ModelNotFoundError:
|
except exception.ModelNotFoundError:
|
||||||
# Create a new one
|
# Create a new one
|
||||||
version = DBDatastoreVersion()
|
version = DBDatastoreVersion()
|
||||||
|
@ -34,13 +34,23 @@ class DatastoreController(wsgi.Controller):
|
|||||||
200)
|
200)
|
||||||
|
|
||||||
def version_show(self, req, tenant_id, datastore, id):
|
def version_show(self, req, tenant_id, datastore, id):
|
||||||
datastore, datastore_version = models.get_datastore_version(datastore,
|
datastore = models.Datastore.load(datastore)
|
||||||
id)
|
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,
|
return wsgi.Result(views.DatastoreVersionView(datastore_version,
|
||||||
req).data(), 200)
|
req).data(), 200)
|
||||||
|
|
||||||
def version_index(self, req, tenant_id, datastore):
|
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.
|
return wsgi.Result(views.
|
||||||
DatastoreVersionsView(datastore_versions,
|
DatastoreVersionsView(datastore_versions,
|
||||||
req).data(), 200)
|
req).data(), 200)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from trove.common import wsgi
|
||||||
from trove.common.views import create_links
|
from trove.common.views import create_links
|
||||||
|
|
||||||
|
|
||||||
@ -31,6 +32,9 @@ class DatastoreView(object):
|
|||||||
"name": self.datastore.name,
|
"name": self.datastore.name,
|
||||||
"links": self._build_links(),
|
"links": self._build_links(),
|
||||||
}
|
}
|
||||||
|
default_version = self.datastore.default_version_id
|
||||||
|
if default_version:
|
||||||
|
datastore_dict["default_version"] = default_version
|
||||||
|
|
||||||
return {"datastore": datastore_dict}
|
return {"datastore": datastore_dict}
|
||||||
|
|
||||||
@ -61,14 +65,20 @@ class DatastoreVersionView(object):
|
|||||||
def __init__(self, datastore_version, req=None):
|
def __init__(self, datastore_version, req=None):
|
||||||
self.datastore_version = datastore_version
|
self.datastore_version = datastore_version
|
||||||
self.req = req
|
self.req = req
|
||||||
|
self.context = req.environ[wsgi.CONTEXT_KEY]
|
||||||
|
|
||||||
def data(self):
|
def data(self):
|
||||||
datastore_version_dict = {
|
datastore_version_dict = {
|
||||||
"id": self.datastore_version.id,
|
"id": self.datastore_version.id,
|
||||||
"name": self.datastore_version.name,
|
"name": self.datastore_version.name,
|
||||||
|
"datastore": self.datastore_version.datastore_id,
|
||||||
"links": self._build_links(),
|
"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}
|
return {"version": datastore_version_dict}
|
||||||
|
|
||||||
def _build_links(self):
|
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.service_status = service_status
|
||||||
self.root_pass = root_password
|
self.root_pass = root_password
|
||||||
self.ds_version = (datastore_models.DatastoreVersion.
|
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.
|
self.ds = (datastore_models.Datastore.
|
||||||
load(self.ds_version.datastore_id))
|
load(self.ds_version.datastore_id))
|
||||||
|
|
||||||
|
@ -86,18 +86,20 @@ class Datastores(object):
|
|||||||
with TypeCheck('DatastoreVersion', version) as check:
|
with TypeCheck('DatastoreVersion', version) as check:
|
||||||
check.has_field("id", basestring)
|
check.has_field("id", basestring)
|
||||||
check.has_field("name", basestring)
|
check.has_field("name", basestring)
|
||||||
|
check.has_field("datastore", basestring)
|
||||||
check.has_field("links", list)
|
check.has_field("links", list)
|
||||||
assert_equal(version.name, test_config.dbaas_datastore_version)
|
assert_equal(version.name, test_config.dbaas_datastore_version)
|
||||||
|
|
||||||
@test
|
@test
|
||||||
def test_datastore_version_datastore_not_found(self):
|
def test_datastore_version_get_by_uuid_attrs(self):
|
||||||
try:
|
version = self.rd_client.datastore_versions.get_by_uuid(
|
||||||
assert_raises(exceptions.NotFound,
|
test_config.dbaas_datastore_version_id)
|
||||||
self.rd_client.datastore_versions.get,
|
with TypeCheck('DatastoreVersion', version) as check:
|
||||||
NAME, NAME)
|
check.has_field("id", basestring)
|
||||||
except exceptions.BadRequest as e:
|
check.has_field("name", basestring)
|
||||||
assert_equal(e.message,
|
check.has_field("datastore", basestring)
|
||||||
"Datastore '%s' cannot be found." % NAME)
|
check.has_field("links", list)
|
||||||
|
assert_equal(version.name, test_config.dbaas_datastore_version)
|
||||||
|
|
||||||
@test
|
@test
|
||||||
def test_datastore_version_not_found(self):
|
def test_datastore_version_not_found(self):
|
||||||
|
@ -52,7 +52,7 @@ class ResizeTestBase(TestCase):
|
|||||||
flavor_id=OLD_FLAVOR_ID,
|
flavor_id=OLD_FLAVOR_ID,
|
||||||
tenant_id=999,
|
tenant_id=999,
|
||||||
volume_size=None,
|
volume_size=None,
|
||||||
datastore_version_id=test_config.dbaas_datastore_version,
|
datastore_version_id=test_config.dbaas_datastore_version_id,
|
||||||
task_status=InstanceTasks.RESIZING)
|
task_status=InstanceTasks.RESIZING)
|
||||||
self.server = self.mock.CreateMock(Server)
|
self.server = self.mock.CreateMock(Server)
|
||||||
self.instance = models.BuiltInstanceTasks(context,
|
self.instance = models.BuiltInstanceTasks(context,
|
||||||
|
@ -52,7 +52,7 @@ class MgmtInstanceBase(object):
|
|||||||
self.db_info = DBInstance.create(
|
self.db_info = DBInstance.create(
|
||||||
name="instance",
|
name="instance",
|
||||||
flavor_id=1,
|
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,
|
tenant_id=self.tenant_id,
|
||||||
volume_size=None,
|
volume_size=None,
|
||||||
task_status=InstanceTasks.NONE)
|
task_status=InstanceTasks.NONE)
|
||||||
|
@ -71,7 +71,10 @@ class TestConfig(object):
|
|||||||
'version_url': "http://localhost:8775/",
|
'version_url': "http://localhost:8775/",
|
||||||
'nova_url': "http://localhost:8774/v1.1",
|
'nova_url': "http://localhost:8774/v1.1",
|
||||||
'dbaas_datastore': "mysql",
|
'dbaas_datastore': "mysql",
|
||||||
|
'dbaas_datastore_id': "a00000a0-00a0-0a00-00a0-000a000000aa",
|
||||||
'dbaas_datastore_version': "mysql-5.5",
|
'dbaas_datastore_version': "mysql-5.5",
|
||||||
|
'dbaas_datastore_version_id': "b00000b0-00b0-0b00-00b0-"
|
||||||
|
"000b000000bb",
|
||||||
'instance_create_time': 16 * 60,
|
'instance_create_time': 16 * 60,
|
||||||
'mysql_connection_method': {"type": "direct"},
|
'mysql_connection_method': {"type": "direct"},
|
||||||
'typical_nova_image_name': None,
|
'typical_nova_image_name': None,
|
||||||
|
@ -32,7 +32,7 @@ class FakeDBInstance(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.id = None
|
self.id = None
|
||||||
self.deleted = False
|
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.server_status = "ACTIVE"
|
||||||
self.task_status = FakeInstanceTask()
|
self.task_status = FakeInstanceTask()
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class MockMgmtInstanceTest(TestCase):
|
|||||||
id='1',
|
id='1',
|
||||||
flavor_id='flavor_1',
|
flavor_id='flavor_1',
|
||||||
datastore_version_id=
|
datastore_version_id=
|
||||||
test_config.dbaas_datastore_version,
|
test_config.dbaas_datastore_version_id,
|
||||||
compute_instance_id='compute_id_1',
|
compute_instance_id='compute_id_1',
|
||||||
server_id='server_id_1',
|
server_id='server_id_1',
|
||||||
tenant_id='tenant_id_1',
|
tenant_id='tenant_id_1',
|
||||||
@ -205,7 +205,11 @@ class TestNovaNotificationTransformer(MockMgmtInstanceTest):
|
|||||||
stub_datastore_version.id = "stub_datastore_version"
|
stub_datastore_version.id = "stub_datastore_version"
|
||||||
stub_datastore_version.manager = "m0ng0"
|
stub_datastore_version.manager = "m0ng0"
|
||||||
when(datastore_models.
|
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 = mock()
|
||||||
stub_datastore.default_datastore_version = "stub_datastore_version"
|
stub_datastore.default_datastore_version = "stub_datastore_version"
|
||||||
|
@ -140,7 +140,9 @@ class FreshInstanceTasksTest(testtools.TestCase):
|
|||||||
when(taskmanager_models.FreshInstanceTasks).name().thenReturn(
|
when(taskmanager_models.FreshInstanceTasks).name().thenReturn(
|
||||||
'name')
|
'name')
|
||||||
when(datastore_models.
|
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.
|
when(datastore_models.
|
||||||
Datastore).load(any()).thenReturn(mock())
|
Datastore).load(any()).thenReturn(mock())
|
||||||
taskmanager_models.FreshInstanceTasks.nova_client = fake_nova_client()
|
taskmanager_models.FreshInstanceTasks.nova_client = fake_nova_client()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user