326 lines
13 KiB
Python
Executable File
326 lines
13 KiB
Python
Executable File
from pecan import request
|
|
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,
|
|
set_utils_conf)
|
|
|
|
from orm.services.customer_manager.cms_rest.data.data_manager import \
|
|
DataManager
|
|
from orm.services.customer_manager.cms_rest.logger import get_logger
|
|
from orm.services.customer_manager.cms_rest.logic.error_base import (
|
|
DuplicateEntryError, ErrorStatus)
|
|
from orm.services.customer_manager.cms_rest.model.GroupModels import (
|
|
GroupResultWrapper, GroupSummary, GroupSummaryResponse)
|
|
|
|
from orm.services.customer_manager.cms_rest.rds_proxy import RdsProxy
|
|
LOG = get_logger(__name__)
|
|
|
|
|
|
class GroupLogic(object):
|
|
|
|
def build_full_group(self, group, uuid, datamanager):
|
|
if any(char in ":" for char in group.name):
|
|
raise ErrorStatus(400, "Group Name does not allow colon(:).")
|
|
|
|
if group.name.strip() == '':
|
|
raise ErrorStatus(400, "Group Name can not be blank.")
|
|
|
|
sql_group = datamanager.add_group(group, uuid)
|
|
|
|
sql_group_id = sql_group.uuid
|
|
datamanager.add_group_region(sql_group_id, -1)
|
|
|
|
self.add_regions_to_db(group.regions, sql_group_id, datamanager)
|
|
|
|
return sql_group
|
|
|
|
def add_regions_to_db(self, regions, sql_group_id,
|
|
datamanager, default_users=[]):
|
|
for region in regions:
|
|
|
|
sql_region = datamanager.add_region(region)
|
|
try:
|
|
datamanager.add_group_region(sql_group_id, sql_region.id)
|
|
except Exception as ex:
|
|
if hasattr(ex, 'orig') and ex.orig[0] == 1062:
|
|
raise DuplicateEntryError(
|
|
'Error, duplicate entry, region ' +
|
|
region.name +
|
|
' already associated with group')
|
|
raise ex
|
|
|
|
def create_group(self, group, uuid, transaction_id):
|
|
datamanager = DataManager()
|
|
try:
|
|
group.handle_region_group()
|
|
sql_group = self.build_full_group(group, uuid, datamanager)
|
|
group_result_wrapper = build_response(uuid, transaction_id,
|
|
'create')
|
|
|
|
if sql_group.group_regions and len(sql_group.group_regions) > 1:
|
|
group_dict = sql_group.get_proxy_dict()
|
|
for region in group_dict["regions"]:
|
|
region["action"] = "create"
|
|
|
|
datamanager.flush()
|
|
RdsProxy.send_group_dict(group_dict, transaction_id, "POST")
|
|
else:
|
|
LOG.debug(
|
|
"Group with no regions - wasn't send to RDS Proxy " +
|
|
str(group))
|
|
|
|
datamanager.commit()
|
|
|
|
except Exception as exp:
|
|
LOG.log_exception("GroupLogic - Failed to CreateGroup", exp)
|
|
datamanager.rollback()
|
|
raise
|
|
|
|
return group_result_wrapper
|
|
|
|
def update_group(self, group, group_uuid, transaction_id):
|
|
datamanager = DataManager()
|
|
try:
|
|
group.validate_model('update')
|
|
group_record = datamanager.get_record('group')
|
|
group_id = group_record.get_group_id_from_uuid(
|
|
group_uuid)
|
|
|
|
sql_group = group_record.read_group_by_uuid(group_uuid)
|
|
if not sql_group:
|
|
raise ErrorStatus(
|
|
404, 'group {0} was not found'.format(group_uuid))
|
|
# old_group_dict = sql_group.get_proxy_dict()
|
|
group_record.delete_by_primary_key(group_id)
|
|
datamanager.flush()
|
|
|
|
sql_group = self.build_full_group(group, group_uuid,
|
|
datamanager)
|
|
# new_group_dict = sql_group.get_proxy_dict()
|
|
|
|
group_result_wrapper = build_response(group_uuid, transaction_id,
|
|
'update')
|
|
datamanager.flush()
|
|
datamanager.commit()
|
|
|
|
return group_result_wrapper
|
|
|
|
except Exception as exp:
|
|
LOG.log_exception("GroupLogic - Failed to CreateGroup", exp)
|
|
datamanager.rollback()
|
|
raise
|
|
|
|
def delete_region(self, group_id, region_id, transaction_id,
|
|
on_success_by_rds, force_delete):
|
|
datamanager = DataManager()
|
|
try:
|
|
group_region = datamanager.get_record('group_region')
|
|
sql_group = datamanager.get_group_by_uuid_or_name(group_id)
|
|
if on_success_by_rds and sql_group is None:
|
|
return
|
|
if sql_group is None:
|
|
raise ErrorStatus(
|
|
404,
|
|
"group with id {} does not exist".format(group_id))
|
|
|
|
group_dict = sql_group.get_proxy_dict()
|
|
group_region.delete_region_for_group(group_id, region_id)
|
|
datamanager.flush()
|
|
|
|
if on_success_by_rds:
|
|
datamanager.commit()
|
|
LOG.debug("Region {0} in group {1} deleted".format(region_id,
|
|
group_id))
|
|
else:
|
|
region = next((r.region for r in sql_group.group_regions
|
|
if r.region.name == region_id), None)
|
|
if region:
|
|
if region.type == 'group':
|
|
set_utils_conf(conf)
|
|
regions = get_regions_of_group(region.name)
|
|
else:
|
|
regions = [region_id]
|
|
for region in group_dict['regions']:
|
|
if region['name'] in regions:
|
|
region['action'] = 'delete'
|
|
|
|
RdsProxy.send_group_dict(group_dict, transaction_id, "PUT")
|
|
if force_delete:
|
|
datamanager.commit()
|
|
else:
|
|
datamanager.rollback()
|
|
|
|
except Exception as exp:
|
|
datamanager.rollback()
|
|
raise
|
|
|
|
finally:
|
|
datamanager.close()
|
|
|
|
def get_group(self, group):
|
|
datamanager = DataManager()
|
|
sql_group = datamanager.get_group_by_uuid_or_name(group)
|
|
|
|
if not sql_group:
|
|
raise ErrorStatus(404, 'group: {0} not found'.format(group))
|
|
ret_group = sql_group.to_wsme()
|
|
|
|
if sql_group.get_group_regions():
|
|
resp = requests.get(conf.api.rds_server.base +
|
|
conf.api.rds_server.status +
|
|
sql_group.uuid, verify=conf.verify).json()
|
|
|
|
for item in ret_group.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_group.status = resp['status']
|
|
else:
|
|
ret_group.status = 'no regions'
|
|
|
|
return ret_group
|
|
|
|
def get_group_list_by_criteria(self, region, user, starts_with, contains,
|
|
start=0, limit=0):
|
|
datamanager = DataManager()
|
|
group_record = datamanager.get_record('group')
|
|
sql_groups = group_record.get_groups_by_criteria(
|
|
region=region,
|
|
user=user,
|
|
starts_with=starts_with,
|
|
contains=contains,
|
|
start=start,
|
|
limit=limit)
|
|
response = GroupSummaryResponse()
|
|
if sql_groups:
|
|
uuids = ','.join(str(sql_group.uuid)
|
|
for sql_group in sql_groups
|
|
if sql_group and sql_group.uuid)
|
|
resource_status = group_record.get_groups_status_by_uuids(uuids)
|
|
|
|
for sql_group in sql_groups:
|
|
groups = GroupSummary.from_db_model(sql_group)
|
|
|
|
if sql_group.uuid:
|
|
# rds_region list contains tuples - each containing the
|
|
# region associated with the customer along with the
|
|
# region status
|
|
rds_region = resource_status.get(sql_group.uuid)
|
|
if rds_region and groups.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
|
|
if item[1] == 'Error']
|
|
submitted_status = [item for item in rds_region
|
|
if item[1] == 'Submitted']
|
|
success_status = [item for item in rds_region
|
|
if item[1] == 'Success']
|
|
|
|
if len(error_status) > 0:
|
|
groups.status = 'Error'
|
|
elif len(submitted_status) > 0:
|
|
groups.status = 'Pending'
|
|
elif len(success_status) > 0:
|
|
groups.status = 'Success'
|
|
else:
|
|
groups.status = 'no regions'
|
|
response.groups.append(groups)
|
|
return response
|
|
|
|
def delete_group_by_uuid(self, group_id):
|
|
datamanager = DataManager()
|
|
|
|
try:
|
|
datamanager.begin_transaction()
|
|
group_record = datamanager.get_record('group')
|
|
|
|
sql_group = group_record.read_group_by_uuid(group_id)
|
|
if sql_group is None:
|
|
raise ErrorStatus(
|
|
404, "Group '{0}' not found".format(group_id))
|
|
|
|
regions = sql_group.get_group_regions()
|
|
if len(regions) > 0:
|
|
# Do not delete a group that still has region(s)
|
|
raise ErrorStatus(405,
|
|
"Cannot delete a group that has region(s). "
|
|
"Please delete the region(s) first and then "
|
|
"delete the group.")
|
|
else:
|
|
expected_status = 'Success'
|
|
invalid_status = 'N/A'
|
|
# Get status from RDS
|
|
resp = RdsProxy.get_status(sql_group.uuid)
|
|
if resp.status_code == 200:
|
|
status_resp = resp.json()
|
|
if 'status' in 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:
|
|
# Group not found in RDS, that means it never has any
|
|
# region(s). 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 group status")
|
|
elif status != expected_status:
|
|
raise ErrorStatus(
|
|
409,
|
|
"The group has not been deleted "
|
|
"successfully from all of its regions "
|
|
"(either the deletion failed on one of the "
|
|
"regions or it is still in progress)")
|
|
|
|
# OK to delete
|
|
group_record.delete_group_by_uuid(group_id)
|
|
datamanager.flush()
|
|
datamanager.commit()
|
|
except Exception as exp:
|
|
LOG.log_exception("GroupLogic - Failed to delete group", exp)
|
|
datamanager.rollback()
|
|
raise
|
|
|
|
|
|
def build_response(group_uuid, transaction_id, context):
|
|
"""this function generate th group action response JSON
|
|
:param group_uuid:
|
|
:param transaction_id:
|
|
:param context: create or update
|
|
:return:
|
|
"""
|
|
# The link should point to the group itself (/v1/orm/groups/{id})
|
|
link_elements = request.url.split('/')
|
|
base_link = '/'.join(link_elements)
|
|
if context == 'create':
|
|
base_link = base_link + '/' + group_uuid
|
|
|
|
timestamp = utils.get_time_human()
|
|
group_result_wrapper = GroupResultWrapper(
|
|
transaction_id=transaction_id,
|
|
id=group_uuid,
|
|
updated=None,
|
|
created=timestamp,
|
|
links={'self': base_link})
|
|
return group_result_wrapper
|