Removed RDS service call

This patch removes RDS service call to retreive resource status by
CMS, FMS, and IMS Ranger services.  These services retrieve the
status by accessing the resource status database directly.

Change-Id: I7695eb5dca697f3326fa2d19aa45681e4b5fc2ce
This commit is contained in:
Chi Lo 2020-01-30 20:27:34 -08:00
parent 7767e6bc7f
commit 305483dcc2
13 changed files with 453 additions and 268 deletions

View File

View File

@ -0,0 +1,42 @@
class ResourceStatusModel(object):
def __init__(self,
timestamp,
region,
status,
resource_id,
operation,
err_msg):
self.timestamp = timestamp
self.region = region
self.status = status
self.resource_id = resource_id
self.operation = operation
self.error_msg = err_msg
def as_dict(self):
return self.__dict__
class StatusModel(object):
def __init__(self, status):
self.regions_status = status
self.status = self._get_aggregated_status()
def _get_aggregated_status(self):
is_pending = False
for region in self.regions_status:
if (region.status == 'Error' and
region.operation.strip() != 'delete'):
# If a region had an error, the aggregated status is 'Error'
return 'Error'
elif region.status == 'Submitted':
# Just set the flag but don't return, because there might be
# an error in any of the next iterations
is_pending = True
if is_pending:
return 'Pending'
else:
# If self.regions_status is empty, the result will still be
# 'Success' but the server returns 404 Not Found
return 'Success'

View File

@ -0,0 +1,56 @@
from oslo_db.sqlalchemy import models
from sqlalchemy import BigInteger, Column, ForeignKey, Integer, Text
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class CommonBaseModel(models.ModelBase):
__table_args__ = {'mysql_engine': 'InnoDB'}
class ImageMetadData(Base, CommonBaseModel):
__tablename__ = 'image_metadata'
image_meta_data_id = Column(ForeignKey('resource_status.id'),
primary_key=True)
checksum = Column(Text, primary_key=False)
virtual_size = Column(Text, primary_key=False)
size = Column(Text, primary_key=False)
def __json__(self):
return dict(
image_meta_data_id=self.image_meta_data_id,
checksum=self.checksum,
virtual_size=self.virtual_size,
size=self.size
)
class ResourceStatus(Base, CommonBaseModel):
__tablename__ = 'resource_status'
id = Column(Integer, autoincrement=True, primary_key=True)
timestamp = Column(BigInteger, primary_key=False)
region = Column(Text, primary_key=False)
status = Column(Text, primary_key=False)
transaction_id = Column(Text, primary_key=False)
resource_id = Column(Text, primary_key=False)
ord_notifier = Column(Text, primary_key=False)
err_code = Column(Text, primary_key=False)
err_msg = Column(Text, primary_key=False)
operation = Column(Text, primary_key=False)
def __json__(self):
return dict(
id=self.id,
timestamp=self.timestamp,
region=self.region,
status=self.status,
transaction_id=self.transaction_id,
resource_id=self.resource_id,
ord_notifier=self.ord_notifier,
err_code=self.err_code,
err_msg=self.err_msg,
operation=self.operation
)

View File

@ -0,0 +1,86 @@
import logging
from orm.common.orm_common.model.models import ResourceStatusModel, StatusModel
from orm.common.orm_common.sql_alchemy.db_models import ResourceStatus
import time
logger = logging.getLogger(__name__)
class ResourceStatusRecord:
def __init__(self, session):
self.__resource_status = ResourceStatus()
self.__TableName = "resource_status"
if session:
self.setDBSession(session)
def setDBSession(self, session):
self.session = session
@property
def resource_status(self):
return self.__resource_status
@resource_status.setter
def resource_status(self, resource_status):
self.__resource_status = resource_status
def read_resource_status(self, resource_uuids):
records_model = {}
statuses_model = {}
timestamp = int(time.time()) * 1000
# assume same time period for all resource types
# max_interval_time_in_seconds = \
# conf.region_resource_id_status.max_interval_time.default * 60
max_interval_time_in_seconds = 2 * 60
ref_timestamp = (int(time.time()) -
max_interval_time_in_seconds) * 1000
try:
records = self.session.query(
ResourceStatus.id,
ResourceStatus.resource_id,
ResourceStatus.region,
ResourceStatus.status,
ResourceStatus.timestamp,
ResourceStatus.operation,
ResourceStatus.err_msg).filter(
ResourceStatus.resource_id.in_(resource_uuids)).all()
if records:
for id, resource_id, region, status, timestamp, operation, \
err_msg in records:
if (status == "Submitted" and
timestamp < ref_timestamp):
timestamp = timestamp
status = "Error"
err_msg = "Status updated to 'Error'. " \
"Too long 'Submitted' status"
status_model = ResourceStatusModel(
timestamp,
region,
status,
resource_id,
operation,
err_msg)
if resource_id in records_model:
records_model[resource_id].append(status_model)
else:
records_model[resource_id] = [status_model]
for id, model in records_model.items():
statuses_model[id] = StatusModel(model)
else:
logger.debug("No resource status records found")
return statuses_model
except Exception as ex:
message = "Failed to read resource status for id {}: {}".format(
resource_id, str(ex))
logger.exception(message)
raise

View File

@ -1,10 +1,12 @@
import logging
import pprint
import requests
import time
import requests
from orm.common.client.audit.audit_client.api import audit
from orm.common.orm_common.sql_alchemy.resource_status_record \
import ResourceStatusRecord
from pecan import conf
# from cms_rest.logger import get_logger
@ -56,7 +58,8 @@ def create_or_validate_uuid(uuid, uuid_type):
LOG.critical(
'CRITICAL|{}|Failed in make_uuid: connection error: {}'.format(
nagios, str(exp)))
exp.message = 'connection error: Failed to get uuid: unable to connect to server'
exp.message = 'connection error: Failed to get uuid: \
unable to connect to server'
raise
except Exception as e:
LOG.info('Failed in make_uuid:' + str(e))
@ -80,11 +83,14 @@ def make_transid():
try:
LOG.debug('Requesting transaction ID from: {}'.format(url))
resp = requests.post(url, data={'uuid_type': 'transaction'}, verify=conf.verify)
resp = requests.post(url, data={'uuid_type': 'transaction'},
verify=conf.verify)
except requests.exceptions.ConnectionError as exp:
nagios = 'CON{}UUIDGEN001'.format(conf.server.name.upper())
LOG.critical('CRITICAL|{}|Failed in make_transid: connection error: {}'.format(nagios, str(exp)))
exp.message = 'connection error: Failed to get uuid: unable to connect to server'
LOG.critical('CRITICAL|{}|Failed in make_transid: '
'connection error: {}'.format(nagios, str(exp)))
exp.message = 'connection error: Failed to get uuid: \
unable to connect to server'
raise
except Exception as e:
LOG.info('Failed in make_transid:' + str(e))
@ -206,6 +212,11 @@ def get_resource_status(resource_id):
return result.json()
def get_resource_status_from_db(session, resource_ids):
resource_status_record = ResourceStatusRecord(session)
return resource_status_record.read_resource_status(resource_ids)
def get_time_human():
"""this function return the timestamp for output JSON
:return: timestamp in wanted format

View File

@ -4,6 +4,7 @@ from orm.services.customer_manager.cms_rest.data.sql_alchemy.models import (CmsU
CustomerMetadata, CustomerRegion,
Region, UserRole)
from orm.services.customer_manager.cms_rest.logger import get_logger
from sqlalchemy import or_
LOG = get_logger(__name__)
@ -66,6 +67,19 @@ class CustomerRecord:
LOG.log_exception(message, exception)
raise
def read_customer_by_uuid_or_name(self, customer_uuid):
try:
customer = self.session.query(Customer).filter(
or_(Customer.uuid == customer_uuid,
Customer.name == customer_uuid))
return customer.first()
except Exception as exception:
message = "Failed to get customer by uuid or name: %s " % customer_uuid
LOG.log_exception(message, exception)
raise
def get_customer_id_from_uuid(self, uuid):
result = self.session.connection().scalar("SELECT id from customer WHERE uuid = \"{}\"".format(uuid)) # nosec
@ -79,6 +93,7 @@ class CustomerRecord:
" FROM rds_resource_status_view WHERE resource_id IN ({})".format(uuid_str))
cust_region_dict = {}
if results:
resource_status_dict = dict((id, (resource_id, region, status)) for id, resource_id, region, status in results)
# using resource_status_dict, create cust_region_dict with resource_id as key and (region, status) as value
for v in list(resource_status_dict.values()):

View File

@ -15,6 +15,7 @@ class CMSBaseModel(models.ModelBase):
__table_args__ = {'mysql_engine': 'InnoDB'}
'''
' CmsDomain is a DataObject and contains all the fields defined in cms_domain table record.
' defined as SqlAlchemy model map to a table
@ -438,6 +439,7 @@ class GroupsUser(Base, CMSBaseModel):
user = GroupWsmeModels.User(id=id, domain=domain)
return user
'''
' CmsRole is a DataObject and contains all the fields defined in CmsRole
' table record, defined as SqlAlchemy model map to a table
@ -643,7 +645,8 @@ class CustomerRegion(Base, CMSBaseModel):
customer_id=self.customer_id,
region_id=self.region_id,
customer_region_quotas=[quota.__json__() for quota in self.customer_region_quotas],
customer_region_user_roles=[user_role.__json__() for user_role in self.customer_region_user_roles]
customer_region_user_roles=[user_role.__json__() for user_role in self.customer_region_user_roles],
region=self.region.name
)
def get_proxy_dict(self):

View File

@ -1,7 +1,6 @@
import oslo_db
import pecan
from pecan import conf, request
import requests
from orm.common.orm_common.utils import utils
from orm.common.orm_common.utils.cross_api_utils import (get_regions_of_group,
@ -627,34 +626,42 @@ class CustomerLogic(object):
finally:
datamanager.close()
def set_resource_status(self, sql_customer, status_model):
wsme_customer = sql_customer.to_wsme()
wsme_customer.status = 'no regions'
if status_model and status_model.regions_status:
for region in wsme_customer.regions:
for status in status_model.regions_status:
if status.region == region.name:
region.status = status.status
if status.error_msg:
region.error_message = status.error_msg
wsme_customer.status = status_model.status
return wsme_customer
def get_customer(self, customer):
datamanager = DataManager()
sql_customer = datamanager.get_customer_by_uuid_or_name(customer)
customer_record = datamanager.get_record('customer')
sql_customer = customer_record.read_customer_by_uuid_or_name(customer)
if not sql_customer:
raise ErrorStatus(404, 'customer: {0} not found'.format(customer))
ret_customer = sql_customer.to_wsme()
# if we have regions in sql_customer
if sql_customer.get_real_customer_regions():
# if we have regions in sql_customer
resp = requests.get(conf.api.rds_server.base +
conf.api.rds_server.status +
sql_customer.uuid, verify=conf.verify).json()
for item in ret_customer.regions:
for status in resp['regions']:
if status['region'] == item.name:
item.status = status['status']
if status['error_msg']:
item.error_message = status['error_msg']
ret_customer.status = resp['status']
uuid = [sql_customer.uuid]
resource_status_dict = utils.get_resource_status_from_db(
datamanager.get_session(), uuid)
status_model = resource_status_dict.get(sql_customer.uuid)
wsme_customer = self.set_resource_status(sql_customer, status_model)
else:
ret_customer.status = 'no regions'
return ret_customer
wsme_customer = sql_customer.to_wsme()
wsme_customer.status = 'no regions'
return wsme_customer
def get_customer_list_by_criteria(self, region, user, starts_with, contains,
metadata, start=0, limit=0):
@ -667,37 +674,20 @@ class CustomerLogic(object):
metadata=metadata,
start=start,
limit=limit)
response = CustomerSummaryResponse()
if sql_customers:
uuids = ','.join(str("\'" + sql_customer.uuid + "\'")
for sql_customer in sql_customers if sql_customer and sql_customer.uuid)
resource_status_dict = customer_record.get_customers_status_by_uuids(uuids)
uuids = [sql_customer.uuid for sql_customer in sql_customers]
resource_status_dict = utils.get_resource_status_from_db(
datamanager.get_session(), uuids)
for sql_customer in sql_customers:
customer = CustomerSummary.from_db_model(sql_customer)
if sql_customer.uuid:
# rds_region_list contains tuples - each containing the region associated
# with the customer along with the region status
rds_region_list = resource_status_dict.get(sql_customer.uuid)
status_model = resource_status_dict.get(sql_customer.uuid)
wsme_customer = self.set_resource_status(sql_customer, status_model)
customer_summary = CustomerSummary.from_wsme(wsme_customer)
response.customers.append(customer_summary)
if rds_region_list and customer.regions:
# set customer.status to 'error' if any of the regions has an 'Error' status'
# else, if any region status shows 'Submitted' then set customer status to 'Pending'
# otherwise customer status is 'Success'
error_status = [item for item in rds_region_list if item[1] == 'Error']
submitted_status = [item for item in rds_region_list if item[1] == 'Submitted']
success_status = [item for item in rds_region_list if item[1] == 'Success']
if len(error_status) > 0:
customer.status = 'Error'
elif len(submitted_status) > 0:
customer.status = 'Pending'
elif len(success_status) > 0:
customer.status = 'Success'
else:
customer.status = 'no regions'
response.customers.append(customer)
return response
def enable(self, customer_uuid, enabled, transaction_id):
@ -745,38 +735,25 @@ class CustomerLogic(object):
"delete the customer.")
else:
expected_status = 'Success'
invalid_status = 'N/A'
# Get status from RDS
resp = RdsProxy.get_status(sql_customer.uuid)
if resp.status_code == 200:
status_resp = resp.json()
if 'status' in list(status_resp.keys()):
LOG.debug(
'RDS returned status: {}'.format(
status_resp['status']))
status = status_resp['status']
else:
# Invalid response from RDS
LOG.error('Response from RDS did not contain status')
status = invalid_status
elif resp.status_code == 404:
# Customer not found in RDS, that means it never had any regions
# So it is OK to delete it
LOG.debug(
'Resource not found in RDS, so it is OK to delete')
status = expected_status
else:
# Invalid status code from RDS
log_message = 'Invalid response code from RDS: {}'.format(
resp.status_code)
log_message = log_message.replace('\n', '_').replace('\r',
'_')
LOG.warning(log_message)
status = invalid_status
if status == invalid_status:
raise ErrorStatus(500, "Could not get customer status")
elif status != expected_status:
# Get status from resource status table
uuid = [sql_customer.uuid]
resource_status_dict = utils.get_resource_status_from_db(
datamanager.get_session(), uuid)
status_model = resource_status_dict.get(sql_customer.uuid)
if status_model:
status = status_model.status
LOG.debug(
'Status from resource_status table: {}'.format(status))
else:
# Customer not found in table, that means it never
# had any regions. So it is OK to delete it
status = expected_status
LOG.debug(
'Resource not found in table, so it is OK to delete')
if status != expected_status:
raise ErrorStatus(409,
"The customer has not been deleted "
"successfully from all of its regions "

View File

@ -418,6 +418,21 @@ class CustomerSummary(Model):
return customer
@staticmethod
def from_wsme(wsme_customer):
regions = [region.name for region in
wsme_customer.regions]
customer = CustomerSummary()
customer.id = wsme_customer.uuid
customer.name = wsme_customer.name
customer.description = wsme_customer.description
customer.enabled = wsme_customer.enabled
customer.num_regions = len(regions)
customer.regions = regions
customer.status = wsme_customer.status
return customer
class CustomerSummaryResponse(Model):
customers = wsme.wsattr([CustomerSummary], mandatory=True)

View File

@ -1,7 +1,7 @@
from orm.services.flavor_manager.fms_rest.data.sql_alchemy.db_models import (
FlavorRegion, FlavorTenant)
from orm.services.flavor_manager.fms_rest.data.wsme.models import (
ExtraSpecsWrapper, Flavor,
ExtraSpecsWrapper,
FlavorListFullResponse, FlavorWrapper,
Region, RegionWrapper, TagsWrapper,
TenantWrapper)
@ -9,6 +9,7 @@ from orm.services.flavor_manager.fms_rest.logger import get_logger
from orm.services.flavor_manager.fms_rest.logic.error_base import (
ConflictError, ErrorStatus, NotFoundError)
from orm.common.orm_common.injector import injector
from orm.common.orm_common.utils import utils
from oslo_config import cfg
import oslo_db
@ -27,15 +28,16 @@ def validate_tenants_regions_list(requested_tenants, requested_regions,
valid_tenants_list, valid_regions_list = [], []
if results:
# the first element in the results tuple is the tenant
# prep result_tenant_list from result_rows and remove NoneTypes from list
# the first element in the results tuple is the tenant prep
# result_tenant_list from result_rows and remove NoneTypes from list
result_tenant_list = [x[0] for x in results]
result_tenant_list = filter(None, result_tenant_list)
# lastly clean up valid_tenants_list list by removing duplicate items
valid_tenants_list = list(dict.fromkeys(result_tenant_list))
# second element in the results tuple is the region - compile the region
# data into valid_regions_list and eliminate duplicates from the list
# second element in the results tuple is the region - compile the
# region data into valid_regions_list and eliminate duplicates
# from the list
valid_regions_list = [x[1] for x in results]
valid_regions_list = list(dict.fromkeys(valid_regions_list))
@ -170,10 +172,9 @@ def update_flavor(flavor, flavor_uuid, transaction_id): # pragma: no cover
datamanager.close()
@di.dependsOn('rds_proxy')
@di.dependsOn('data_manager')
def delete_flavor_by_uuid(flavor_uuid): # , transaction_id):
rds_proxy, DataManager = di.resolver.unpack(delete_flavor_by_uuid)
DataManager = di.resolver.unpack(delete_flavor_by_uuid)
datamanager = DataManager()
try:
@ -195,35 +196,24 @@ def delete_flavor_by_uuid(flavor_uuid): # , transaction_id):
raise ErrorStatus(405, msg)
else:
expected_status = 'Success'
invalid_status = 'N/A'
# Get status from RDS
resp = rds_proxy.get_status(sql_flavor.id)
if resp.status_code == 200:
status_resp = resp.json()
if 'status' in list(status_resp.keys()):
LOG.debug(
'RDS returned status:{}'.format(status_resp['status']))
status = status_resp['status']
else:
# Invalid response from RDS
LOG.warning('Response from RDS did not contain status')
status = invalid_status
elif resp.status_code == 404:
# Flavor not found in RDS, that means it never had any regions
# So it is OK to delete it
LOG.debug('Resource not found in RDS, so it is OK to delete')
status = expected_status
else:
# Invalid status code from RDS
LOG.warning('Invalid response code from RDS: {}'.format(
resp.status_code))
status = invalid_status
if status == invalid_status:
LOG.error('Invalid flavor status received from RDS')
raise ErrorStatus(500,
"Invalid flavor status received from RDS")
elif status != expected_status:
# Get status from resource status table
uuid = [sql_flavor.id]
resource_status_dict = utils.get_resource_status_from_db(
datamanager.get_session(), uuid)
status_model = resource_status_dict.get(sql_flavor.id)
if status_model:
status = status_model.status
LOG.debug(
'Status from resource_status table: {}'.format(status))
else:
# Flavor not found in table, that means it never had any
# regions. So it is OK to delete it
status = expected_status
LOG.debug('Resource not found in table, so it is OK to delete')
if status != expected_status:
msg = "The flavor has not been deleted " \
"successfully from all of its regions " \
"(either the deletion failed on one of the " \
@ -447,7 +437,8 @@ def delete_tenant(flavor_uuid, tenant_id, transaction_id):
LOG.log_exception("FlavorLogic - Tenant not found", str(exp))
raise
else:
LOG.log_exception("FlavorLogic - failed to delete tenant", str(exp))
LOG.log_exception(
"FlavorLogic - failed to delete tenant", str(exp))
raise
except Exception as exp:
LOG.log_exception("FlavorLogic - Failed to delete tenant", str(exp))
@ -558,9 +549,8 @@ def delete_extra_specs(flavor_id, transaction_id, extra_spec=None):
@di.dependsOn('data_manager')
@di.dependsOn('rds_proxy')
def get_tags(flavor_uuid):
DataManager, rds_proxy = di.resolver.unpack(get_flavor_by_uuid)
DataManager = di.resolver.unpack(get_tags)
datamanager = DataManager()
flavor_record = datamanager.get_record('flavor')
@ -760,21 +750,26 @@ def update_extra_specs(flavor_id, extra_specs, transaction_id):
@di.dependsOn('data_manager')
@di.dependsOn('rds_proxy')
def get_flavor_by_uuid(flavor_uuid):
DataManager, rds_proxy = di.resolver.unpack(get_flavor_by_uuid)
DataManager = di.resolver.unpack(get_flavor_by_uuid)
datamanager = DataManager()
flavor_record = datamanager.get_record('flavor')
try:
flavor_record = datamanager.get_record('flavor')
sql_flavor = flavor_record.get_flavor_by_id(flavor_uuid)
sql_flavor = flavor_record.get_flavor_by_id(flavor_uuid)
if not sql_flavor:
raise ErrorStatus(404, 'flavor id {0} not found'.format(flavor_uuid))
if not sql_flavor:
raise ErrorStatus(
404, 'flavor id {0} not found'.format(flavor_uuid))
flavor_wrapper = FlavorWrapper.from_db_model(sql_flavor)
flavor_wrapper = get_flavor_status(
sql_flavor, datamanager.get_session())
except Exception as exp:
LOG.log_exception("Failed to get_flavor_by_uuid", exp)
raise
update_region_statuses(flavor_wrapper.flavor, sql_flavor)
return flavor_wrapper
@ -820,14 +815,32 @@ def add_tags(flavor_id, tags, transaction_id):
return result
def get_flavor_status(sql_flavor, session):
flavor_wrapper = FlavorWrapper.from_db_model(sql_flavor)
region_names = [reg.region_name for reg in sql_flavor.flavor_regions]
if len(region_names):
uuid = [sql_flavor.id]
resource_status_dict = utils.get_resource_status_from_db(
session, uuid)
status_model = resource_status_dict.get(sql_flavor.id)
update_region_statuses(
flavor_wrapper.flavor, region_names, status_model)
else:
# flavor has no regions
flavor_wrapper.flavor.status = "no regions"
return flavor_wrapper
@di.dependsOn('data_manager')
@di.dependsOn('rds_proxy')
def get_flavor_by_uuid_or_name(flavor_uuid_or_name):
DataManager, rds_proxy = di.resolver.unpack(get_flavor_by_uuid)
DataManager = di.resolver.unpack(get_flavor_by_uuid_or_name)
datamanager = DataManager()
try:
flavor_record = datamanager.get_record('flavor')
sql_flavor = flavor_record.get_flavor_by_id_or_name(
@ -838,9 +851,9 @@ def get_flavor_by_uuid_or_name(flavor_uuid_or_name):
404,
'flavor id or name {0} not found'.format(flavor_uuid_or_name))
flavor_wrapper = FlavorWrapper.from_db_model(sql_flavor)
flavor_wrapper = get_flavor_status(
sql_flavor, datamanager.get_session())
update_region_statuses(flavor_wrapper.flavor, sql_flavor)
except Exception as exp:
LOG.log_exception("Failed to get_flavor_by_uuid_or_name", exp)
raise
@ -850,56 +863,37 @@ def get_flavor_by_uuid_or_name(flavor_uuid_or_name):
return flavor_wrapper
@di.dependsOn('rds_proxy')
def update_region_statuses(flavor, sql_flavor):
rds_proxy = di.resolver.unpack(update_region_statuses)
def update_region_statuses(flavor, region_names, status_model):
# remove the regions comes from database and return the regions which
# return from rds, because there might be group region there (in the db)
# and in the response from the rds we will have a list of all regions
# belong to this group
flavor.regions[:] = []
resp = rds_proxy.get_status(sql_flavor.id)
if resp.status_code == 200:
rds_status_resp = resp.json()
# store all regions for the flavor in the flavor_regions_list
flavor_regions_list = []
for region_data in sql_flavor.flavor_regions:
flavor_regions_list.append(region_data.region_name)
flavor.status = 'no regions'
error_status = submitted_status = success_status = 0
if status_model and status_model.regions_status:
# get region status if region in flavor_regions_list
if flavor_regions_list and 'regions' in list(rds_status_resp.keys()):
for rds_region_status in rds_status_resp['regions']:
if region_names:
for status in status_model.regions_status:
# check that the region read from RDS is in the
# flavor_regions_list
if rds_region_status['region'] in flavor_regions_list:
if status.region in region_names:
flavor.regions.append(
Region(name=rds_region_status['region'], type="single",
status=rds_region_status['status'],
error_message=rds_region_status['error_msg']))
Region(name=status.region, type="single",
status=status.status,
error_message=status.error_msg))
if 'status' in list(rds_status_resp.keys()):
# if flavor not assigned to region set flavor.status to
# 'no regions'
if flavor_regions_list:
flavor.status = rds_status_resp['status']
else:
flavor.status = 'no regions'
elif resp.status_code == 404:
# flavor id not in rds resource_status table as no region is assigned
flavor.status = "no regions"
else:
flavor.status = "N/A"
flavor.status = status_model.status
@di.dependsOn('data_manager')
@di.dependsOn('rds_proxy')
def get_flavor_list_by_params(visibility, region, tenant, series, vm_type,
vnf_name, starts_with, contains, alias):
DataManager, rds_proxy = di.resolver.unpack(get_flavor_list_by_params)
DataManager = di.resolver.unpack(get_flavor_list_by_params)
datamanager = DataManager()
try:
flavor_record = datamanager.get_record('flavor')
sql_flavors = flavor_record.get_flavors_by_criteria(
@ -914,53 +908,23 @@ def get_flavor_list_by_params(visibility, region, tenant, series, vm_type,
alias=alias)
response = FlavorListFullResponse()
if sql_flavors:
uuids = ','.join(str("\'" + sql_flavor.id + "\'")
for sql_flavor in sql_flavors
if sql_flavor and sql_flavor.id)
resource_status_dict = flavor_record.get_flavors_status_by_uuids(
uuids)
if sql_flavors:
uuids = [sql_flavor.id for sql_flavor in sql_flavors]
resource_status_dict = utils.get_resource_status_from_db(
datamanager.get_session(), uuids)
for sql_flavor in sql_flavors:
flavor = Flavor.from_db_model(sql_flavor)
if sql_flavor.id:
# rds_region_list contains tuples - each containing the
# region associated with the flavor along with the region
# status
rds_region_list = resource_status_dict.get(sql_flavor.id)
flavor_wrapper = FlavorWrapper.from_db_model(sql_flavor)
region_names = [reg.region_name for reg
in sql_flavor.flavor_regions]
# determine flavor overall status by checking its region
# statuses:
if rds_region_list and flavor.regions:
# set image.status to 'error' if any of the regions has
# an 'Error' status' else, if any region status shows
# 'Submitted' then set image status to 'Pending'
# otherwise image status = 'Success'
error_status = [item for item in rds_region_list
if item[1] == 'Error']
submitted_status = [item for item in rds_region_list
if item[1] == 'Submitted']
success_status = [item for item in rds_region_list
if item[1] == 'Success']
status_model = resource_status_dict.get(sql_flavor.id)
update_region_statuses(
flavor_wrapper.flavor, region_names, status_model)
if len(error_status) > 0:
flavor.status = 'Error'
elif len(submitted_status) > 0:
flavor.status = 'Pending'
elif len(success_status) > 0:
flavor.status = 'Success'
# use rds_region_list to format the regions' statuses
# in flavor record
for rgn in flavor.regions:
for rds_row_items in rds_region_list:
if rgn.name == rds_row_items[0]:
rgn.status = rds_row_items[1]
else:
flavor.status = 'no regions'
response.flavors.append(flavor)
response.flavors.append(flavor_wrapper.flavor)
except Exception as exp:
LOG.log_exception("Fail to get_flavor_list_by_params", exp)

View File

@ -33,6 +33,19 @@ class RdsStatus(object):
return {"status": self.status}
class ResourceStatusModel(object):
def __init__(self, region='DPK', status='Success', err_msg=None):
self.region = region
self.status = status
self.error_msg = err_msg
class StatusModel(object):
def __init__(self, status='Success'):
self.regions_status = [ResourceStatusModel()]
self.status = status
class TestCustomerLogic(FunctionalTest):
def setUp(self):
global customer
@ -46,6 +59,8 @@ class TestCustomerLogic(FunctionalTest):
customer_logic.utils.audit_trail.return_value = None
customer_logic.utils.make_uuid.return_value = 'some_uuid'
customer_logic.utils.get_time_human.return_value = '1337'
customer_logic.utils.get_resource_status_from_db.return_value = \
{'1337': StatusModel()}
customer_logic.RdsProxy = mock.MagicMock()
customer_logic.RdsProxy.send_customer.return_value = None
@ -384,12 +399,13 @@ class TestCustomerLogic(FunctionalTest):
{"key:value"})
def test_delete_customer_by_uuid_success(self):
logic = customer_logic.CustomerLogic()
logic.delete_customer_by_uuid('customer_id')
global flow_type
flow_type = 3
# Customer found in CMS DB but not found in RDS
customer_logic.RdsProxy.get_status.return_value = RdsStatus(
status_code=404)
customer_logic.utils.get_resource_status_from_db.return_value = \
{'1337': StatusModel()}
logic = customer_logic.CustomerLogic()
logic.delete_customer_by_uuid('customer_id')
def test_delete_customer_by_uuid_not_found(self):
@ -403,31 +419,23 @@ class TestCustomerLogic(FunctionalTest):
logic.delete_customer_by_uuid('customer_id')
def test_delete_customer_by_uuid_errors(self):
global flow_type
flow_type = 3
global mock_returns_error
mock_returns_error = True
logic = customer_logic.CustomerLogic()
self.assertRaises(SystemError, logic.delete_customer_by_uuid, 'customer_id')
# RDS returned an empty json
mock_returns_error = False
customer_logic.RdsProxy.get_status.return_value = RdsStatus(oy=True)
customer_logic.utils.get_resource_status_from_db.return_value = \
{'1337': StatusModel(status='Error')}
self.assertRaises(customer_logic.ErrorStatus,
logic.delete_customer_by_uuid,
'customer_id')
# RDS returned 500
customer_logic.RdsProxy.get_status.return_value = RdsStatus(
status_code=500)
self.assertRaises(customer_logic.ErrorStatus,
logic.delete_customer_by_uuid,
'customer_id')
# RDS returned Error status
customer_logic.RdsProxy.get_status.return_value = RdsStatus(
status='Error')
self.assertRaises(customer_logic.ErrorStatus,
logic.delete_customer_by_uuid,
'customer_id')
self.assertTrue(record_mock.read_customer_by_uuid.called)
def test_delete_customer_by_uuid_conflict(self):
global flow_type
@ -454,20 +462,14 @@ class TestCustomerLogic(FunctionalTest):
def test_get_customer_success(self):
logic = customer_logic.CustomerLogic()
get_mock = mock.MagicMock()
get_mock.json.return_value = STATUS_JSON
customer_logic.requests.get = mock.MagicMock(return_value=get_mock)
logic.get_customer('customer_id')
self.assertTrue(data_manager_mock.get_customer_by_uuid_or_name.called)
self.assertTrue(record_mock.read_customer_by_uuid_or_name.called)
def test_get_customer_not_found(self):
global flow_type
flow_type = 1
# customer_logic.requests.get = mock.MagicMock(return_value=None)
logic = customer_logic.CustomerLogic()
self.assertRaises(ErrorStatus, logic.get_customer, 'id')
@ -507,7 +509,14 @@ def get_mock_datamanager():
sql_customer.uuid = '1337'
sql_customer.status = 'Success'
sql_customer.name = 'DPK'
return sql_customer
def _get_customer_no_regions():
sql_customer = sql_models.Customer()
sql_customer.customer_customer_regions = []
sql_customer.uuid = '1337'
sql_customer.status = 'Success'
sql_customer.name = 'DPK'
return sql_customer
def _add_customer(*args, **kwargs):
@ -547,17 +556,20 @@ def get_mock_datamanager():
data_manager_mock.update_customer = _update_customer
data_manager_mock.add_region = _add_region
data_manager_mock.add_user.return_value = sql_models.CmsUser()
data_manager_mock.get_customer_by_uuid_or_name.return_value = _get_customer()
record_mock.delete_region_for_customer.return_value = None
record_mock.delete_customer_by_uuid.return_value = None
record_mock.read_customer_by_uuid_or_name.return_value = _get_customer()
if flow_type == 1:
record_mock.read_customer_by_uuid.return_value = None
data_manager_mock.get_customer_by_uuid_or_name.return_value = None
record_mock.read_customer_by_uuid_or_name.return_value = None
elif flow_type == 2:
q = mock.MagicMock()
q.get_real_customer_regions.return_value = [mock.MagicMock()]
record_mock.read_customer_by_uuid.return_value = q
elif flow_type == 3:
record_mock.read_customer_by_uuid.return_value = _get_customer_no_regions()
record_mock.delete_user_from_region.return_value = resultobj(rowcount)
else:

View File

@ -1,4 +1,5 @@
from orm.common.orm_common.injector import injector
from orm.common.orm_common.utils import utils
from orm.services.flavor_manager.fms_rest.data.sql_alchemy import db_models
from orm.services.flavor_manager.fms_rest.data.wsme import models
from orm.services.flavor_manager.fms_rest.data.wsme.models import *
@ -20,6 +21,7 @@ class OES():
def to_db_model(self):
return None
error = None
FLAVOR_MOCK = None
@ -343,45 +345,44 @@ class TestFlavorLogic(FunctionalTest):
self.assertRaises(flavor_logic.ErrorStatus, flavor_logic.delete_tags,
'a', None, 'a')
def test_delete_flavor_by_uuid_success(self):
@patch.object(utils, 'get_resource_status_from_db')
def test_delete_flavor_by_uuid_success(self, mock_get_resource):
global error
error = 31
injector.override_injected_dependency(
('data_manager', get_datamanager_mock))
injector.override_injected_dependency(
('rds_proxy', get_rds_proxy_mock()))
error = 10
flavor_logic.delete_flavor_by_uuid('some_id')
error = 33
injector.override_injected_dependency(
('rds_proxy', get_rds_proxy_mock()))
flavor_logic.delete_flavor_by_uuid('some_id')
def test_delete_flavor_by_uuid_bad_status(self):
global error
injector.override_injected_dependency(
('data_manager', get_datamanager_mock))
# Run once for response with no status and once for an invalid
# response code
for error_value in (32, 40,):
error = error_value
injector.override_injected_dependency(
('rds_proxy', get_rds_proxy_mock()))
status_model = MagicMock()
try:
flavor_logic.delete_flavor_by_uuid('some_id')
self.fail('ErrorStatus not raised!')
except flavor_logic.ErrorStatus as e:
self.assertEqual(e.status_code, 500)
# status model has success status
status_model.status = 'Success'
resource_status_dict = {'some_id': status_model}
mock_get_resource.return_value = resource_status_dict
flavor_logic.delete_flavor_by_uuid('some_uuid')
# status model not found
resource_status_dict = {}
mock_get_resource.return_value = resource_status_dict
flavor_logic.delete_flavor_by_uuid('some_id')
@patch.object(utils, 'get_resource_status_from_db')
def test_delete_flavor_by_uuid_bad_status(self, mock_get_resource):
global error
error = 10
# RDS returned OK, but the resource status is Error
error = 34
injector.override_injected_dependency(
('rds_proxy', get_rds_proxy_mock()))
('data_manager', get_datamanager_mock))
status_model = MagicMock()
# status model has error status
status_model.status = 'Error'
resource_status_dict = {'some_id': status_model}
mock_get_resource.return_value = resource_status_dict
try:
flavor_logic.delete_flavor_by_uuid('some_id')
flavor_logic.delete_flavor_by_uuid('some_uuid')
self.fail('ErrorStatus not raised!')
except flavor_logic.ErrorStatus as e:
self.assertEqual(e.status_code, 409)
@ -691,6 +692,9 @@ def get_datamanager_mock():
elif error == 9:
record.get_flavor_by_id.side_effect = flavor_logic.ErrorStatus(
500)
elif error == 10:
record.get_flavor_by_id.return_value = db_models.Flavor(
id='some_id')
else:
record.get_flavor_by_id.return_value = MagicMock()
return record