Merge "RMS direct access to database for region resources"
This commit is contained in:
commit
88b95a0dcb
@ -15,10 +15,8 @@ from orm.services.region_manager.rms.services import error_base
|
||||
from orm.services.region_manager.rms.services import services as RegionService
|
||||
from orm.services.region_manager.rms.utils import authentication
|
||||
|
||||
from pecan import conf as pecan_conf
|
||||
from pecan import request
|
||||
from pecan import rest
|
||||
import requests
|
||||
import wsme
|
||||
from wsme import types as wtypes
|
||||
from wsmeext.pecan import wsexpose
|
||||
@ -190,45 +188,6 @@ class RegionsController(rest.RestController):
|
||||
metadata = RegionMetadataController()
|
||||
status = RegionStatusController()
|
||||
|
||||
def has_no_resources(self, region_id):
|
||||
# function to check if any resource (flavor, customer, or image) is
|
||||
# assigned to the region_id
|
||||
try:
|
||||
resources = {
|
||||
'flavors': [pecan_conf.api.fms_server.base,
|
||||
pecan_conf.api.fms_server.flavors],
|
||||
'customers': [pecan_conf.api.cms_server.base,
|
||||
pecan_conf.api.cms_server.customers],
|
||||
'images': [pecan_conf.api.ims_server.base,
|
||||
pecan_conf.api.ims_server.images]
|
||||
}
|
||||
|
||||
keystone_ep = authentication.get_keystone_ep(
|
||||
request.headers['X-Auth-Region'])
|
||||
|
||||
headers = {'Keystone-Endpoint': keystone_ep,
|
||||
'X-Auth-Region': request.headers['X-Auth-Region'],
|
||||
'X-Auth-Token': request.headers['X-Auth-Token']}
|
||||
|
||||
for resource in resources:
|
||||
resource_get_url = '%s%s/?region=%s' % (
|
||||
resources[resource][0],
|
||||
resources[resource][1], region_id)
|
||||
resp = requests.get(resource_get_url,
|
||||
headers=headers,
|
||||
verify=pecan_conf.verify)
|
||||
resp_dict = resp.json()
|
||||
|
||||
if resp_dict[resource]:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
raise err_utils.get_error(request.transaction_id,
|
||||
status_code=401,
|
||||
message=str(e))
|
||||
|
||||
@wsexpose(Regions, str, str, [str], str, str, str, str, str, str, str, str,
|
||||
str, str, str, str, status_code=200, rest_content_types='json')
|
||||
def get_all(self, type=None, status=None, metadata=None,
|
||||
@ -263,8 +222,9 @@ class RegionsController(rest.RestController):
|
||||
'ranger_agent_version': ranger_agent_version, 'clli': clli,
|
||||
'regionname': regionname, 'osversion': osversion,
|
||||
'location_type': location_type, 'state': state,
|
||||
'domain_name': domain_name, 'country': country, 'city': city,
|
||||
'street': street, 'zip': zip, 'vlcp_name': vlcp_name}
|
||||
'domain_name': domain_name, 'country': country,
|
||||
'city': city, 'street': street, 'zip': zip,
|
||||
'vlcp_name': vlcp_name}
|
||||
logger.debug("Parameters: {}".format(str(url_args)))
|
||||
|
||||
try:
|
||||
@ -358,46 +318,41 @@ class RegionsController(rest.RestController):
|
||||
|
||||
@wsexpose(None, str, rest_content_types='json', status_code=204)
|
||||
def delete(self, region_id):
|
||||
utils.set_utils_conf(pecan_conf)
|
||||
# currently ORM resource types are 'flavor', 'customer', and 'image'
|
||||
proceed_to_delete = self.has_no_resources(region_id)
|
||||
if proceed_to_delete:
|
||||
logger.info("Delete Region")
|
||||
authentication.authorize(request, 'region:delete')
|
||||
try:
|
||||
logger.info("Delete Region")
|
||||
authentication.authorize(request, 'region:delete')
|
||||
try:
|
||||
|
||||
logger.debug("delete region {}".format(region_id))
|
||||
RegionService.delete_region(region_id)
|
||||
logger.debug("region deleted")
|
||||
logger.debug("delete region {}".format(region_id))
|
||||
RegionService.delete_region(region_id)
|
||||
logger.debug("region deleted")
|
||||
|
||||
event_details = 'Region {} deleted'.format(region_id)
|
||||
utils.audit_trail('delete region', request.transaction_id,
|
||||
request.headers, region_id,
|
||||
event_details=event_details)
|
||||
event_details = 'Region {} deleted'.format(region_id)
|
||||
utils.audit_trail('delete region', request.transaction_id,
|
||||
request.headers, region_id,
|
||||
event_details=event_details)
|
||||
|
||||
# issue NotFoundError for "Delete Region" when group_id not found
|
||||
# which is returned by RegionService.delete_region function
|
||||
except error_base.NotFoundError as exp:
|
||||
logger.error("RegionsController - Region not found")
|
||||
raise err_utils.get_error(
|
||||
request.transaction_id,
|
||||
message="Cannot delete - " + exp.message,
|
||||
status_code=exp.status_code)
|
||||
|
||||
except Exception as exp:
|
||||
logger.exception(
|
||||
"error in deleting region .. reason:- {}".format(str(exp)))
|
||||
raise err_utils.get_error(request.transaction_id,
|
||||
status_code=500,
|
||||
message=str(exp))
|
||||
return
|
||||
else:
|
||||
region_resources_exist_msg = "Region {} cannot be deleted as " \
|
||||
"resources are assigned.".format(region_id)
|
||||
# issue NotFoundError for "Delete Region" when group_id not found
|
||||
# which is returned by RegionService.delete_region function
|
||||
except error_base.NotFoundError as exp:
|
||||
logger.error("RegionsController - Region not found")
|
||||
raise err_utils.get_error(
|
||||
request.transaction_id,
|
||||
message="Cannot delete - " + exp.message,
|
||||
status_code=exp.status_code)
|
||||
|
||||
except error_base.ConflictError as exp:
|
||||
logger.error("Region with resources cannot be deleted")
|
||||
raise err_utils.get_error(request.transaction_id,
|
||||
status_code=400,
|
||||
message=region_resources_exist_msg)
|
||||
message=exp.message)
|
||||
|
||||
except Exception as exp:
|
||||
logger.exception(
|
||||
"Error in deleting region .. reason:- {}".format(str(exp)))
|
||||
raise err_utils.get_error(request.transaction_id,
|
||||
status_code=500,
|
||||
message=str(exp))
|
||||
return
|
||||
|
||||
@wsexpose(RegionsData, str, body=RegionsData, status_code=201,
|
||||
rest_content_types='json')
|
||||
|
@ -77,6 +77,7 @@ def delete_region(region_id):
|
||||
:return:
|
||||
"""
|
||||
LOG.debug("logic:- delete region {}".format(region_id))
|
||||
|
||||
try:
|
||||
db = data_manager_factory.get_data_manager()
|
||||
# logic to allow 'delete_region' to issue NotFoundError when region_id is non-existent
|
||||
@ -84,6 +85,13 @@ def delete_region(region_id):
|
||||
if not region:
|
||||
raise error_base.NotFoundError(message="Region '{}' not found".format(region_id))
|
||||
|
||||
# Region with resources cannnot be deleted
|
||||
resource_exist = db.query_region_resources(region_id)
|
||||
if resource_exist:
|
||||
region_resources_exist_msg = "Region {} cannot be deleted as " \
|
||||
"resources are assigned.".format(region_id)
|
||||
raise error_base.ConflictError(message=region_resources_exist_msg)
|
||||
|
||||
db.delete_region(region_id)
|
||||
LOG.debug("region deleted")
|
||||
|
||||
|
@ -1,11 +1,19 @@
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
from orm.services.customer_manager.cms_rest.data.sql_alchemy.models import (
|
||||
Customer, CustomerRegion)
|
||||
from orm.services.customer_manager.cms_rest.data.sql_alchemy.models import \
|
||||
Region as CmsRegion
|
||||
from orm.services.flavor_manager.fms_rest.data.sql_alchemy.db_models import (
|
||||
Flavor, FlavorRegion)
|
||||
from orm.services.image_manager.ims.persistency.sql_alchemy.db_models import (
|
||||
Image, ImageRegion)
|
||||
|
||||
from orm.services.region_manager.rms.model import model as PythonModels
|
||||
from orm.services.region_manager.rms.services import error_base
|
||||
from orm.services.region_manager.rms.storage.base_data_manager import (BaseDataManager,
|
||||
DuplicateEntryError,
|
||||
EntityNotFound)
|
||||
from orm.services.region_manager.rms.storage.base_data_manager import (
|
||||
BaseDataManager, DuplicateEntryError, EntityNotFound)
|
||||
|
||||
import oslo_db
|
||||
from .data_models import (Group, GroupRegion, Region, RegionEndPoint,
|
||||
@ -177,6 +185,43 @@ class DataManager(BaseDataManager):
|
||||
logger.exception("fail to update region {}".format(str(exp)))
|
||||
raise
|
||||
|
||||
def query_region_resources(self, region_id):
|
||||
try:
|
||||
resource_exist = False
|
||||
session = self._engine_facade.get_session()
|
||||
with session.begin():
|
||||
# query customer resource for the region
|
||||
query = session.query(Customer)
|
||||
query = query.join(CustomerRegion).filter(
|
||||
CustomerRegion.customer_id == Customer.id)
|
||||
query = query.join(CmsRegion).filter(
|
||||
CmsRegion.id == CustomerRegion.region_id,
|
||||
CmsRegion.type == 'single', CmsRegion.name == region_id)
|
||||
if query.first() is not None:
|
||||
resource_exist = True
|
||||
else:
|
||||
# query flavor resource for the region
|
||||
query = session.query(Flavor)
|
||||
query = query.join(FlavorRegion).filter(
|
||||
FlavorRegion.flavor_internal_id == Flavor.internal_id,
|
||||
FlavorRegion.region_name == region_id)
|
||||
if query.first() is not None:
|
||||
resource_exist = True
|
||||
else:
|
||||
# query image resource for the region
|
||||
query = session.query(Image)
|
||||
query = query.join(ImageRegion).filter(
|
||||
ImageRegion.image_id == Image.id,
|
||||
ImageRegion.region_name == region_id)
|
||||
if query.first() is not None:
|
||||
resource_exist = True
|
||||
|
||||
return resource_exist
|
||||
except Exception as exp:
|
||||
logger.exception(
|
||||
"fail to verify if region {} has resources".format(region_id))
|
||||
raise
|
||||
|
||||
def delete_region(self, region_id):
|
||||
# delete a region from `region` table and also the region's
|
||||
# entries from `region_meta_data` and `region_end_points` tables
|
||||
|
@ -257,10 +257,9 @@ class TestAddRegion(FunctionalTest):
|
||||
@patch.object(regions, 'request')
|
||||
@patch.object(regions, 'err_utils')
|
||||
@patch.object(regions.RegionService, 'delete_region')
|
||||
@patch.object(regions.RegionsController, 'has_no_resources', return_value=True)
|
||||
@patch.object(regions.authentication, 'authorize', return_value=True)
|
||||
def test_delete_region_error(self, mock_auth, mock_delete_logic,
|
||||
mock_get_error, mock_request, mock_controller):
|
||||
mock_get_error, mock_request):
|
||||
mock_get_error.get_error = self.get_error
|
||||
mock_request.transaction_id = "555"
|
||||
mock_delete_logic.side_effect = regions.error_base.ErrorStatus(message="unknown error", status_code=500)
|
||||
|
@ -51,6 +51,9 @@ class db(object):
|
||||
def get_region_by_id_or_name(self, id_name):
|
||||
return id_name
|
||||
|
||||
def query_region_resources(self, id_name):
|
||||
return False
|
||||
|
||||
def add_region(self, **kw):
|
||||
if self.exp:
|
||||
raise Exception("any")
|
||||
@ -313,22 +316,16 @@ class TestServices(FunctionalTest):
|
||||
message = exp.message
|
||||
self.assertEqual(message, "id not found")
|
||||
|
||||
@patch.object(services, 'get_region_by_id_or_name',
|
||||
return_value={"a": "b"})
|
||||
@patch.object(services.data_manager_factory, 'get_data_manager',
|
||||
return_value=db(exp=True))
|
||||
def test_delete_region_error(self, mock_db_get_group,
|
||||
mock_get_region_id_name):
|
||||
def test_delete_region_error(self, mock_db_get_group):
|
||||
try:
|
||||
result = services.delete_region(self._to_wsme_from_input(full_region))
|
||||
except Exception as exp:
|
||||
message = str(exp)
|
||||
self.assertEqual(message, "not deleted")
|
||||
|
||||
@patch.object(services, 'get_region_by_id_or_name',
|
||||
return_value={"a": "b"})
|
||||
@patch.object(services.data_manager_factory, 'get_data_manager',
|
||||
return_value=db())
|
||||
def test_delete_region_success(self, mock_db_get_group,
|
||||
mock_get_region_id_name):
|
||||
def test_delete_region_success(self, mock_db_get_group):
|
||||
result = services.delete_region(self._to_wsme_from_input(full_region))
|
||||
|
Loading…
x
Reference in New Issue
Block a user