diff --git a/api-ref/source/datastores.inc b/api-ref/source/datastores.inc index 28c8df63c1..748427704a 100644 --- a/api-ref/source/datastores.inc +++ b/api-ref/source/datastores.inc @@ -28,8 +28,6 @@ Response Example :language: javascript - - Show datastore details ~~~~~~~~~~~~~~~~~~~~~~ @@ -50,3 +48,19 @@ Response Example .. literalinclude:: samples/datastore-show-response.json :language: javascript + + +Delete datastore +~~~~~~~~~~~~~~~~ + +.. rest_method:: DELETE /v1.0/{project_id}/datastores/{datastore} + +Delete a datastore. + +Request +------- + +.. rest_parameters:: parameters.yaml + + - project_id: project_id + - datastore: data_store diff --git a/releasenotes/notes/ussuri-04-delete-datastoredad784e2345711ea.yaml b/releasenotes/notes/ussuri-04-delete-datastoredad784e2345711ea.yaml new file mode 100644 index 0000000000..4fe6251971 --- /dev/null +++ b/releasenotes/notes/ussuri-04-delete-datastoredad784e2345711ea.yaml @@ -0,0 +1,4 @@ +--- +features: + - Admin user can delete datastore if there are no instances or backups + associated. diff --git a/trove/common/exception.py b/trove/common/exception.py index e6cc91e27d..d7e20f64c7 100644 --- a/trove/common/exception.py +++ b/trove/common/exception.py @@ -66,6 +66,12 @@ class NotFound(TroveError): message = _("Resource %(uuid)s cannot be found.") +class BadRequest(TroveError): + + message = _("The server could not comply with the request since it is " + "either malformed or otherwise incorrect.") + + class CapabilityNotFound(NotFound): message = _("Capability '%(capability)s' cannot be found.") @@ -172,6 +178,16 @@ class DatastoreVersionInactive(TroveError): message = _("Datastore version '%(version)s' is not active.") +class DatastoreVersionAlreadyExists(BadRequest): + + message = _("A datastore version with the name '%(name)s' already exists.") + + +class DatastoreVersionsExist(BadRequest): + + message = _("Datastore versions exist for datastore %(datastore)s.") + + class DatastoreDefaultDatastoreNotFound(TroveError): message = _("Please specify datastore. Default datastore " @@ -240,12 +256,6 @@ class GuestTimeout(TroveError): message = _("Timeout trying to connect to the Guest Agent.") -class BadRequest(TroveError): - - message = _("The server could not comply with the request since it is " - "either malformed or otherwise incorrect.") - - class MissingKey(BadRequest): message = _("Required element/key - %(key)s was not specified.") @@ -661,11 +671,6 @@ class ImageNotFound(NotFound): message = _("Image %(uuid)s cannot be found.") -class DatastoreVersionAlreadyExists(BadRequest): - - message = _("A datastore version with the name '%(name)s' already exists.") - - class LogAccessForbidden(Forbidden): message = _("You must be admin to %(action)s log '%(log)s'.") diff --git a/trove/common/policies/datastores.py b/trove/common/policies/datastores.py index f3f9c02b13..a522f374ac 100644 --- a/trove/common/policies/datastores.py +++ b/trove/common/policies/datastores.py @@ -37,6 +37,16 @@ rules = [ 'method': 'GET' } ]), + policy.DocumentedRuleDefault( + name='datastore:delete', + check_str='rule:admin', + description='Delete a datastore.', + operations=[ + { + 'path': PATH_DATASTORE, + 'method': 'DELETE' + } + ]), policy.DocumentedRuleDefault( name='datastore:version_show', check_str='', diff --git a/trove/datastore/service.py b/trove/datastore/service.py index 24420ed70f..b9366690eb 100644 --- a/trove/datastore/service.py +++ b/trove/datastore/service.py @@ -15,13 +15,17 @@ # License for the specific language governing permissions and limitations # under the License. # +from oslo_log import log as logging +from trove.common import exception from trove.common import policy from trove.common import wsgi from trove.datastore import models, views from trove.flavor import views as flavor_views from trove.volume_type import views as volume_type_view +LOG = logging.getLogger(__name__) + class DatastoreController(wsgi.Controller): @@ -105,3 +109,17 @@ class DatastoreController(wsgi.Controller): context, datastore, version_id)) return wsgi.Result(volume_type_view.VolumeTypesView( volume_types, req).data(), 200) + + def delete(self, req, tenant_id, id): + """Remove an existing datastore.""" + self.authorize_request(req, 'delete') + + ds_versions = models.DatastoreVersions.load(id, only_active=False) + if len(ds_versions.db_info.all()) > 0: + raise exception.DatastoreVersionsExist(datastore=id) + + LOG.info("Deleting datastore %s", id) + + datastore = models.Datastore.load(id) + datastore.delete() + return wsgi.Result(None, 202)