summaryrefslogtreecommitdiff
path: root/trove/datastore
diff options
context:
space:
mode:
authorRiddhi Shah <ridhi.j.shah@gmail.com>2014-07-26 14:23:27 -0500
committerMayuri Ganguly <mayuri.ganguly@hp.com>2015-08-11 23:13:02 -0700
commit8f59f8ef41e97f9b27db2690ccb78353040b4c9b (patch)
treebcf35e9f38988b4d5aa7e329740e05a088513f9a /trove/datastore
parent84b30e4d98abd9ca15590ed1dd2a65745082dcb9 (diff)
downloadtrove-8f59f8ef41e97f9b27db2690ccb78353040b4c9b.tar.gz
Associate flavor types with datastore versions
This feature provides the ability to associate flavor types with datastore versions.The trove-manage util will provide the ability to add or delete this information. All nova flavors are permitted for a datastore-version unless one or more entries are found in datastore_version_metadata, in which case only those are permitted. partially implements blueprint associate-flavors-datastores Change-Id: Ib012401f89d07c502f93d5ee1cd4abb6b738953a
Diffstat (limited to 'trove/datastore')
-rw-r--r--trove/datastore/models.py133
-rw-r--r--trove/datastore/service.py14
2 files changed, 146 insertions, 1 deletions
diff --git a/trove/datastore/models.py b/trove/datastore/models.py
index 81d8ee10..04da5f57 100644
--- a/trove/datastore/models.py
+++ b/trove/datastore/models.py
@@ -14,15 +14,16 @@
# 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 oslo_log import log as logging
from trove.common import cfg
from trove.common import exception
+from trove.common.remote import create_nova_client
from trove.common import utils
from trove.db import get_db_api
from trove.db import models as dbmodels
+from trove.flavor.models import Flavor as flavor_model
LOG = logging.getLogger(__name__)
@@ -36,6 +37,7 @@ def persisted_models():
'capabilities': DBCapabilities,
'datastore_version': DBDatastoreVersion,
'capability_overrides': DBCapabilityOverrides,
+ 'datastore_version_metadata': DBDatastoreVersionMetadata
}
@@ -60,6 +62,13 @@ class DBDatastoreVersion(dbmodels.DatabaseModelBase):
'packages', 'active']
+class DBDatastoreVersionMetadata(dbmodels.DatabaseModelBase):
+
+ _data_fields = ['id', 'datastore_version_id', 'key', 'value',
+ 'created', 'deleted', 'deleted_at', 'updated_at']
+ preserve_on_delete = True
+
+
class Capabilities(object):
def __init__(self, datastore_version_id=None):
@@ -526,4 +535,126 @@ def update_datastore_version(datastore, name, manager, image_id, packages,
version.image_id = image_id
version.packages = packages
version.active = active
+
db_api.save(version)
+
+
+class DatastoreVersionMetadata(object):
+ @classmethod
+ def _datastore_version_metadata_add(cls, datastore_version_id,
+ key, value, exception_class):
+ """Create an entry in the Datastore Version Metadata table."""
+ # Do we have a mapping in the db?
+ # yes: and its deleted then modify the association
+ # yes: and its not deleted then error on create
+ # no: then just create the new association
+ try:
+ db_record = DBDatastoreVersionMetadata.find_by(
+ datastore_version_id=datastore_version_id,
+ key=key, value=value)
+ if db_record.deleted == 1:
+ db_record.deleted = 0
+ db_record.updated_at = utils.utcnow()
+ db_record.save()
+ return
+ else:
+ raise exception_class(
+ datastore_version_id=datastore_version_id,
+ flavor_id=value)
+ except exception.NotFound:
+ pass
+ DBDatastoreVersionMetadata.create(
+ datastore_version_id=datastore_version_id,
+ key=key, value=value)
+
+ @classmethod
+ def _datastore_version_metadata_delete(cls, datastore_version_id,
+ key, value, exception_class):
+ try:
+ db_record = DBDatastoreVersionMetadata.find_by(
+ datastore_version_id=datastore_version_id,
+ key=key, value=value)
+ if db_record.deleted == 0:
+ db_record.delete()
+ return
+ else:
+ raise exception_class(
+ datastore_version_id=datastore_version_id,
+ flavor_id=value)
+ except exception.ModelNotFoundError:
+ raise exception_class(datastore_version_id=datastore_version_id,
+ flavor_id=value)
+
+ @classmethod
+ def add_datastore_version_flavor_association(cls, datastore_name,
+ datastore_version_name,
+ flavor_ids):
+ db_api.configure_db(CONF)
+ db_ds_record = DBDatastore.find_by(
+ name=datastore_name
+ )
+ db_datastore_id = db_ds_record.id
+ db_dsv_record = DBDatastoreVersion.find_by(
+ datastore_id=db_datastore_id,
+ name=datastore_version_name
+ )
+ datastore_version_id = db_dsv_record.id
+ for flavor_id in flavor_ids:
+ cls._datastore_version_metadata_add(
+ datastore_version_id, 'flavor', flavor_id,
+ exception.DatastoreFlavorAssociationAlreadyExists)
+
+ @classmethod
+ def delete_datastore_version_flavor_association(cls, datastore_name,
+ datastore_version_name,
+ flavor_id):
+ db_api.configure_db(CONF)
+ db_ds_record = DBDatastore.find_by(
+ name=datastore_name
+ )
+ db_datastore_id = db_ds_record.id
+ db_dsv_record = DBDatastoreVersion.find_by(
+ datastore_id=db_datastore_id,
+ name=datastore_version_name
+ )
+ datastore_version_id = db_dsv_record.id
+ cls._datastore_version_metadata_delete(
+ datastore_version_id, 'flavor', flavor_id,
+ exception.DatastoreFlavorAssociationNotFound)
+
+ @classmethod
+ def list_datastore_version_flavor_associations(cls, context,
+ datastore_type,
+ datastore_version_id):
+ if datastore_type and datastore_version_id:
+ """
+ All nova flavors are permitted for a datastore_version unless
+ one or more entries are found in datastore_version_metadata,
+ in which case only those are permitted.
+ """
+ (datastore, datastore_version) = get_datastore_version(
+ type=datastore_type, version=datastore_version_id)
+ # If datastore_version_id and flavor key exists in the
+ # metadata table return all the associated flavors for
+ # that datastore version.
+ nova_flavors = create_nova_client(context).flavors.list()
+ bound_flavors = DBDatastoreVersionMetadata.find_all(
+ datastore_version_id=datastore_version.id,
+ key='flavor', deleted=False
+ )
+ if (bound_flavors.count() != 0):
+ bound_flavors = tuple(f.value for f in bound_flavors)
+ # Generate a filtered list of nova flavors
+ ds_nova_flavors = (f for f in nova_flavors
+ if f.id in bound_flavors)
+ associated_flavors = tuple(flavor_model(flavor=item)
+ for item in ds_nova_flavors)
+ else:
+ # Return all nova flavors if no flavor metadata found
+ # for datastore_version.
+ associated_flavors = tuple(flavor_model(flavor=item)
+ for item in nova_flavors)
+ return associated_flavors
+ else:
+ msg = _("Specify both the datastore and datastore_version_id.")
+ raise exception.BadRequest(msg)
diff --git a/trove/datastore/service.py b/trove/datastore/service.py
index 376bdb56..6a04a1ce 100644
--- a/trove/datastore/service.py
+++ b/trove/datastore/service.py
@@ -18,6 +18,7 @@
from trove.common import wsgi
from trove.datastore import models, views
+from trove.flavor import views as flavor_views
class DatastoreController(wsgi.Controller):
@@ -61,3 +62,16 @@ class DatastoreController(wsgi.Controller):
return wsgi.Result(views.
DatastoreVersionsView(datastore_versions,
req).data(), 200)
+
+ def list_associated_flavors(self, req, tenant_id, datastore,
+ version_id):
+ """
+ All nova flavors are returned for a datastore-version unless
+ one or more entries are found in datastore_version_metadata,
+ in which case only those are returned.
+ """
+ context = req.environ[wsgi.CONTEXT_KEY]
+ flavors = (models.DatastoreVersionMetadata.
+ list_datastore_version_flavor_associations(
+ context, datastore, version_id))
+ return wsgi.Result(flavor_views.FlavorsView(flavors, req).data(), 200)