Implementation of Keystone Group creation

Change-Id: Id4828f4611ae5b0e054337149082b2a0ec618d53
This commit is contained in:
Chi Lo 2019-03-12 10:38:15 -07:00 committed by hosingh000
parent e5a7860983
commit 2b78e52250
23 changed files with 1679 additions and 207 deletions

View File

@ -270,6 +270,73 @@ def add_to_parser(service_sub):
parser_list_customer.add_argument('--metadata', action='append', nargs="+",
type=str, help='<key:value>')
# group
parser_create_group = subparsers.add_parser('creste_group',
help='[<"X-RANGER-Client" '
'header>] <data file '
'with new group '
'JSON>')
parser_create_group.add_argument('client',
**cli_common.ORM_CLIENT_KWARGS)
parser_create_group.add_argument('datafile',
type=argparse.FileType('r'),
help='<data file with new group '
'JSON>')
parser_delete_group = subparsers.add_parser('delete_group',
help='[<"X-RANGER-Client" '
'header>] <group id>')
parser_delete_group.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_delete_group.add_argument('groupid', type=str, help='<group id>')
# groups region
parser_add_groups_region = subparsers.add_parser(
'add_groups_region',
help='[<"X-RANGER-Client" '
'header>] <group id> '
'<data file with region(s) JSON>')
parser_add_groups_region.add_argument(
'client', **cli_common.ORM_CLIENT_KWARGS)
parser_add_groups_region.add_argument(
'groupid', type=str, help='<groupid id>')
parser_add_groups_region.add_argument(
'datafile', type=argparse.FileType('r'),
help='<data file with region(s) JSON>')
parser_delete_groups_region = subparsers.add_parser(
'delete_groups_region',
help='[<"X-RANGER-Client" header>] [--force_delete] '
'<group id> <region id>')
parser_delete_groups_region.add_argument('client',
**cli_common.ORM_CLIENT_KWARGS)
parser_delete_groups_region.add_argument('groupid',
type=str,
help='<group id>')
parser_delete_groups_region.add_argument('regionid',
type=str,
help='<region id>')
parser_delete_groups_region.add_argument('--force_delete',
help='force delete groups region',
action="store_true")
# get group
h1, h2 = '[<"X-RANGER-Client" header>]', '<group id or group name>'
parser_get_group = subparsers.add_parser('get_group',
help='%s %s' % (h1, h2))
parser_get_group.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_get_group.add_argument('groupid', type=str, help=h2)
# list groups
h1 = '[<"X-RANGER-Client" header>]'
h2 = '[--region <name>] [--starts_with <name>] [--contains <name>]'
parser_list_groups = subparsers.add_parser('list_groups',
help='%s %s' % (h1, h2))
parser_list_groups.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_list_groups.add_argument('--region', type=str, help='region name')
parser_list_groups.add_argument('--starts_with', type=str,
help='group name')
parser_list_groups.add_argument('--contains', type=str,
help='* contains in group name')
return parser
@ -279,42 +346,47 @@ def preparm(p):
def cmd_details(args):
if args.subcmd == 'create_customer':
return requests.post, ''
return requests.post, 'customers/'
elif args.subcmd == 'delete_customer':
return requests.delete, '/%s' % args.custid
return requests.delete, 'customers/%s' % args.custid
elif args.subcmd == 'update_customer':
return requests.put, '/%s' % args.custid
return requests.put, 'customers/%s' % args.custid
elif args.subcmd == 'add_region':
return requests.post, '/%s/regions' % args.custid
return requests.post, 'customers/%s/regions' % args.custid
elif args.subcmd == 'replace_region':
return requests.put, '/%s/regions' % args.custid
return requests.put, 'customers/%s/regions' % args.custid
elif args.subcmd == 'delete_region':
return requests.delete, '/%s/regions/%s/%s' % (args.custid,
args.regionid,
args.force_delete)
return requests.delete, 'customers/%s/regions/%s/%s' % (
args.custid,
args.regionid,
args.force_delete)
elif args.subcmd == 'add_user':
return requests.post, '/%s/regions/%s/users' % (
return requests.post, 'customers/%s/regions/%s/users' % (
args.custid, args.regionid)
elif args.subcmd == 'replace_user':
return requests.put, '/%s/regions/%s/users' % (
return requests.put, 'customers/%s/regions/%s/users' % (
args.custid, args.regionid)
elif args.subcmd == 'delete_user':
return requests.delete, '/%s/regions/%s/users/%s' % (
args.custid, args.regionid, args.userid)
return requests.delete, 'customers/%s/regions/%s/users/%s' % (
args.custid,
args.regionid,
args.userid)
elif args.subcmd == 'add_default_user':
return requests.post, '/%s/users' % args.custid
return requests.post, 'customers/%s/users' % args.custid
elif args.subcmd == 'replace_default_user':
return requests.put, '/%s/users' % args.custid
return requests.put, 'customers/%s/users' % args.custid
elif args.subcmd == 'delete_default_user':
return requests.delete, '/%s/users/%s' % (args.custid, args.userid)
return requests.delete, 'customers/%s/users/%s' % (
args.custid,
args.userid)
elif args.subcmd == 'add_metadata':
return requests.post, '/%s/metadata' % args.custid
return requests.post, 'customers/%s/metadata' % args.custid
elif args.subcmd == 'replace_metadata':
return requests.put, '/%s/metadata' % args.custid
return requests.put, 'customers/%s/metadata' % args.custid
elif args.subcmd == 'get_customer':
return requests.get, '/%s' % args.custid
return requests.get, 'customers/%s' % args.custid
elif args.subcmd == 'enabled':
return requests.put, '/%s/enabled' % args.custid
return requests.put, 'customers/%s/enabled' % args.custid
elif args.subcmd == 'list_customers':
param = ''
if args.region:
@ -328,7 +400,29 @@ def cmd_details(args):
if args.metadata:
for meta in args.metadata:
param += '%smetadata=%s' % (preparm(param), meta[0])
return requests.get, '/%s' % param
return requests.get, 'customers/%s' % param
elif args.subcmd == 'create_group':
return requests.post, 'groups/'
elif args.subcmd == 'delete_group':
return requests.delete, 'groups/%s' % args.groupid
elif args.subcmd == 'add_groups_region':
return requests.post, 'groups/%s/regions' % args.groupid
elif args.subcmd == 'delete_groups_region':
return requests.delete, 'groups/%s/regions/%s/%s' % (
args.groupid,
args.regionid,
args.force_delete)
elif args.subcmd == 'get_group':
return requests.get, 'groups/%s' % args.groupid
elif args.subcmd == 'list_groups':
param = ''
if args.region:
param += '%sregion=%s' % (preparm(param), args.region)
if args.starts_with:
param += '%sstarts_with=%s' % (preparm(param), args.starts_with)
if args.contains:
param += '%scontains=%s' % (preparm(param), args.contains)
return requests.get, 'groups/%s' % param
def get_token(timeout, args, host):
@ -384,7 +478,11 @@ def get_token(timeout, args, host):
'Failed in get_token, host: {}, region: {}'.format(host,
auth_region))
url = url % (keystone_ep,)
data = data % (base_config.user_domain_name, username, password, tenant_name, base_config.project_domain_name,)
data = data % (base_config.user_domain_name,
username,
password,
tenant_name,
base_config.project_domain_name,)
if args.verbose:
print(
@ -413,14 +511,16 @@ def get_environment_variable(argument):
def run(args):
rms_url = args.rms_base_url if args.rms_base_url else base_config.rms['base_url']
host = args.cms_base_url if args.cms_base_url else base_config.cms['base_url']
rms_url = args.rms_base_url if args.rms_base_url else \
base_config.rms['base_url']
host = args.cms_base_url if args.cms_base_url else \
base_config.cms['base_url']
port = args.port if args.port else base_config.cms['port']
data = args.datafile.read() if 'datafile' in args else '{}'
timeout = args.timeout if args.timeout else 10
rest_cmd, cmd_url = cmd_details(args)
url = '%s/v1/orm/customers' % (host) + cmd_url
url = '%s/v1/orm/' % (host) + cmd_url
if args.faceless:
auth_token = auth_region = requester = client = ''
else:

View File

@ -0,0 +1,112 @@
from oslo_db.exception import DBDuplicateEntry
from pecan import request, rest
from wsmeext.pecan import wsexpose
from orm.common.orm_common.utils import api_error_utils as err_utils
from orm.common.orm_common.utils import utils
from orm.services.customer_manager.cms_rest.logger import get_logger
from orm.services.customer_manager.cms_rest.logic.error_base import ErrorStatus
from orm.services.customer_manager.cms_rest.logic.group_logic import GroupLogic
from orm.services.customer_manager.cms_rest.model.GroupModels import \
Region, RegionResultWrapper
from orm.services.customer_manager.cms_rest.utils import authentication
LOG = get_logger(__name__)
class RegionController(rest.RestController):
@wsexpose([str], str, str, rest_content_types='json')
def get(self, group_id, region_id):
return ["This is groups region controller ", "group id: " + group_id]
@wsexpose(RegionResultWrapper, str, body=[Region],
rest_content_types='json', status_code=200)
def post(self, group_id, regions):
LOG.info("RegionController - Add Regions group id {0} "
"regions: {1}".format(group_id, str(regions)))
authentication.authorize(request, 'groups:add_region')
try:
group_logic = GroupLogic()
result = group_logic.add_regions(group_id,
regions,
request.transaction_id)
LOG.info("RegionController - Add Regions finished: " + str(result))
event_details = 'Group {} regions: {} added'.format(
group_id, [r.name for r in regions])
utils.audit_trail('add group regions',
request.transaction_id,
request.headers,
group_id,
event_details=event_details)
except DBDuplicateEntry as exception:
LOG.log_exception(
"RegionController - Group Region already exists", exception)
raise err_utils.get_error(request.transaction_id,
status_code=409,
message='Region already exists',
error_details=exception.message)
except ErrorStatus as exception:
LOG.log_exception(
"RegionController - Failed to add regions", exception)
raise err_utils.get_error(request.transaction_id,
message=exception.message,
status_code=exception.status_code)
except Exception as exception:
LOG.log_exception(
"RegionController - Failed in add regions", exception)
raise err_utils.get_error(request.transaction_id,
status_code=500,
error_details=str(exception))
return result
@wsexpose(None, str, str, str, str, status_code=204)
def delete(self, group_id, region_id, force_delete='False'):
if force_delete == 'True':
force_delete = True
else:
force_delete = False
requester = request.headers.get('X-RANGER-Requester')
is_rds_client_request = requester == 'rds_resource_service_proxy'
LOG.info("Delete Region group id {0} region_id: {1} by RDS Proxy: "
" {2} ".format(group_id, region_id, is_rds_client_request))
authentication.authorize(request, 'groups:delete_region')
try:
group_logic = GroupLogic()
group_logic.delete_region(group_id,
region_id,
request.transaction_id,
is_rds_client_request,
force_delete)
LOG.info("RegionController - Delete Region finished")
event_details = 'Group {} region: {} deleted'.format(group_id,
region_id)
utils.audit_trail('delete group region',
request.transaction_id,
request.headers,
group_id,
event_details=event_details)
except ValueError as exception:
raise err_utils.get_error(request.transaction_id,
message=exception.message,
status_code=404)
except ErrorStatus as exception:
LOG.log_exception("RegionController - Failed to delete region",
exception)
raise err_utils.get_error(request.transaction_id,
message=exception.message,
status_code=exception.status_code)
except Exception as exception:
LOG.log_exception("RegionController - Failed in delete Region",
exception)
raise err_utils.get_error(request.transaction_id,
status_code=500,
error_details=str(exception))

View File

@ -4,12 +4,15 @@ from wsmeext.pecan import wsexpose
from orm.common.orm_common.utils import api_error_utils as err_utils
from orm.common.orm_common.utils import utils
from orm.services.customer_manager.cms_rest.controllers.v1.orm.customer.regions import RegionController
from orm.services.customer_manager.cms_rest.controllers.v1.orm.customer.users import DefaultUserController
from orm.services.customer_manager.cms_rest.controllers.v1.orm.customer.users \
import DefaultUserController
from orm.services.customer_manager.cms_rest.controllers.v1.orm.group.regions \
import RegionController
from orm.services.customer_manager.cms_rest.logger import get_logger
from orm.services.customer_manager.cms_rest.logic.error_base import ErrorStatus
from orm.services.customer_manager.cms_rest.logic.group_logic import GroupLogic
from orm.services.customer_manager.cms_rest.model.GroupModels import Group, GroupResultWrapper, GroupSummaryResponse
from orm.services.customer_manager.cms_rest.model.GroupModels \
import Group, GroupResultWrapper, GroupSummaryResponse
from orm.services.customer_manager.cms_rest.utils import authentication
LOG = get_logger(__name__)
@ -26,22 +29,26 @@ class GroupController(rest.RestController):
try:
group_logic = GroupLogic()
result = group_logic.get_group(group_uuid)
LOG.info("GroupController - GetGroupDetails finished well: " + str(result))
LOG.info(
"GroupController - GetGroupDetails finished: " + str(result))
except ErrorStatus as exception:
LOG.log_exception("GroupController - Failed to GetGroupDetails", exception)
LOG.log_exception("GroupController - Failed to GetGroupDetails",
exception)
raise err_utils.get_error(request.transaction_id,
message=exception.message,
status_code=exception.status_code)
except Exception as exception:
LOG.log_exception("GroupController - Failed to GetGroupDetails", exception)
LOG.log_exception("GroupController - Failed to GetGroupDetails",
exception)
raise err_utils.get_error(request.transaction_id,
status_code=500,
error_details=exception.message)
return result
@wsexpose(GroupResultWrapper, body=Group, rest_content_types='json', status_code=201)
@wsexpose(GroupResultWrapper, body=Group, rest_content_types='json',
status_code=201)
def post(self, group):
LOG.info("GroupController - CreateGroup: " + str(group))
authentication.authorize(request, 'groups:create')
@ -54,12 +61,17 @@ class GroupController(rest.RestController):
try:
uuid = utils.create_or_validate_uuid(group.uuid, 'groupId')
except TypeError:
raise ErrorStatus(409.1, 'Unable to create Group ID {0}'.format(group.uuid))
raise ErrorStatus(
409.1, 'Unable to create Group ID {0}'.format(
group.uuid))
try:
result = group_logic.create_group(group, uuid, request.transaction_id)
result = group_logic.create_group(group,
uuid,
request.transaction_id)
except oslo_db.exception.DBDuplicateEntry as exception:
raise ErrorStatus(409.2, 'Group field {0} already exists'.format(exception.columns))
raise ErrorStatus(
409.2, 'Group field {0} already exists'.format(
exception.columns))
LOG.info("GroupController - Group Created: " + str(result))
utils.audit_trail('create group', request.transaction_id,
@ -68,20 +80,25 @@ class GroupController(rest.RestController):
return result
except ErrorStatus as exception:
LOG.log_exception("GroupController - Failed to CreateGroup", exception)
LOG.log_exception("GroupController - Failed to CreateGroup",
exception)
raise err_utils.get_error(request.transaction_id,
message=exception.message,
status_code=exception.status_code)
@wsexpose(GroupResultWrapper, str, body=Group, rest_content_types='json', status_code=200)
@wsexpose(GroupResultWrapper, str, body=Group, rest_content_types='json',
status_code=200)
def put(self, group_id, group):
LOG.info("GroupController - UpdateGroup: " + str(group))
authentication.authorize(request, 'groups:update')
try:
group_logic = GroupLogic()
result = group_logic.update_group(group, group_id, request.transaction_id)
result = group_logic.update_group(group,
group_id,
request.transaction_id)
response.status = 200
LOG.info("GroupController - UpdateGroup finished well: " + str(group))
LOG.info(
"GroupController - UpdateGroup finished well: " + str(group))
utils.audit_trail('update group', request.transaction_id,
request.headers, group_id,
@ -94,7 +111,8 @@ class GroupController(rest.RestController):
status_code=exception.status_code)
except Exception as exception:
LOG.log_exception("GroupController - Failed to UpdateGroup", exception)
LOG.log_exception("GroupController - Failed to UpdateGroup",
exception)
raise err_utils.get_error(request.transaction_id,
status_code=500,
error_details=exception.message)
@ -108,7 +126,6 @@ class GroupController(rest.RestController):
LOG.info("GroupController - GetGrouplist")
authentication.authorize(request, 'groups:get_all')
# This shouldn't be necessary, but apparently is on mtn29
start = 0 if start is None else start
limit = 0 if limit is None else limit
@ -121,12 +138,14 @@ class GroupController(rest.RestController):
limit)
return result
except ErrorStatus as exception:
LOG.log_exception("GroupController - Failed to GetGrouplist", exception)
LOG.log_exception("GroupController - Failed to GetGrouplist",
exception)
raise err_utils.get_error(request.transaction_id,
status_code=exception.status_code)
except Exception as exception:
LOG.log_exception("GroupController - Failed to GetGrouplist", exception)
LOG.log_exception("GroupController - Failed to GetGrouplist",
exception)
raise err_utils.get_error(request.transaction_id,
status_code=500,
error_details=exception.message)

View File

@ -1,14 +1,21 @@
import logging
from orm.services.customer_manager.cms_rest.data.sql_alchemy.customer_record import CustomerRecord
from orm.services.customer_manager.cms_rest.data.sql_alchemy.customer_region_record import CustomerRegionRecord
from orm.services.customer_manager.cms_rest.data.sql_alchemy.group_record import GroupRecord
from orm.services.customer_manager.cms_rest.data.sql_alchemy.models import (CmsRole, CmsUser, Customer,
Groups,
CustomerRegion, Quota,
QuotaFieldDetail, Region,
UserRole)
from orm.services.customer_manager.cms_rest.data.sql_alchemy.user_role_record import UserRoleRecord
from orm.services.customer_manager.cms_rest.data.sql_alchemy.customer_record \
import CustomerRecord
from orm.services.customer_manager.cms_rest.data.sql_alchemy.\
customer_region_record import CustomerRegionRecord
from orm.services.customer_manager.cms_rest.data.sql_alchemy.\
group_record import GroupRecord
from orm.services.customer_manager.cms_rest.data.sql_alchemy.\
groups_region_record import GroupsRegionRecord
from orm.services.customer_manager.cms_rest.data.sql_alchemy.models \
import (CmsRole, CmsUser, Customer,
Groups, GroupRegion,
CustomerRegion, Quota,
QuotaFieldDetail, Region,
UserRole)
from orm.services.customer_manager.cms_rest.data.sql_alchemy.user_role_record \
import UserRoleRecord
from orm.services.customer_manager.cms_rest.logic.error_base import ErrorStatus
import oslo_db
from oslo_db.sqlalchemy import session as db_session
@ -38,7 +45,8 @@ class DataManager(object):
if not connection_string:
connection_string = conf.database.connection_string
self._engine_facade = db_session.EngineFacade(connection_string, autocommit=False)
self._engine_facade = db_session.EngineFacade(connection_string,
autocommit=False)
self._session = None
listen(self.session, 'before_flush', on_before_flush)
self.image_record = None
@ -63,7 +71,9 @@ class DataManager(object):
try:
self.session.flush()
except oslo_db.exception.DBDuplicateEntry as exception:
raise ErrorStatus(409.2, 'Duplicate Entry {0} already exist'.format(exception.columns))
raise ErrorStatus(
409.2, 'Duplicate Entry {0} already exist'.format(
exception.columns))
except Exception:
raise
@ -136,6 +146,12 @@ class DataManager(object):
self.session)
return self.customer_region_record
if record_name == "GroupRegion" or record_name == "group_region":
if not hasattr(self, "groups_region_record"):
self.groups_region_record = GroupsRegionRecord(
self.session)
return self.groups_region_record
if record_name == "UserRole" or record_name == "user_role":
if not hasattr(self, "user_role_record"):
self.user_role_record = UserRoleRecord(self.session)
@ -211,7 +227,8 @@ class DataManager(object):
sql_group = Groups(
uuid=uuid,
name=group.name,
domain_id=1,
domain_name='default',
enabled=group.enabled,
description=group.description
)
@ -268,6 +285,27 @@ class DataManager(object):
return db_region
def add_group_region(self, group_id, region_id):
group_region = GroupRegion(
group_id=group_id,
region_id=region_id
)
self.session.add(group_region)
self.flush()
def add_region(self, region):
db_region = self.session.query(Region).filter(
Region.name == region.name).first()
if not (db_region is None):
return db_region
db_region = Region(name=region.name, type=region.type)
self.session.add(db_region)
self.flush()
return db_region
def get_region_id_by_name(self, name):
region_id = self.session.query(Region.id).filter(
Region.name == name).scalar()

View File

@ -1,6 +1,9 @@
from __builtin__ import int
from orm.services.customer_manager.cms_rest.data.sql_alchemy.models import (Groups)
from orm.services.customer_manager.cms_rest.data.sql_alchemy.models import (
Groups,
Region,
GroupRegion)
from orm.services.customer_manager.cms_rest.logger import get_logger
LOG = get_logger(__name__)
@ -9,7 +12,8 @@ LOG = get_logger(__name__)
class GroupRecord:
def __init__(self, session):
# this model is uses only for the parameters of access mothods, not an instance of model in the database
# this model is uses only for the parameters of access mothods,
# not an instance of model in the database
self.__groups = Groups()
self.__TableName = "groups"
@ -31,11 +35,13 @@ class GroupRecord:
try:
self.session.add(groups)
except Exception as exception:
LOG.log_exception("Failed to insert Group" + str(groups), exception)
LOG.log_exception("Failed to insert Group" + str(groups),
exception)
raise
def delete_by_primary_key(self, group_id):
result = self.session.connection().execute("delete from groups where id = {}".format(group_id)) # nosec
cmd = 'DELETE FROM groups WHERE id = %s'
result = self.session.connection().execute(cmd, (group_id))
return result
def read_by_primary_key(self):
@ -44,7 +50,7 @@ class GroupRecord:
def read_groups(self, group_id):
try:
groups = self.session.query(Groups).filter(Groups.id == group_id)
return group.first()
return groups.first()
except Exception as exception:
message = "Failed to read_groups:group_id: %d " % (group_id)
@ -53,7 +59,8 @@ class GroupRecord:
def read_group_by_uuid(self, group_uuid):
try:
groups = self.session.query(Groups).filter(Groups.uuid == group_uuid)
groups = self.session.query(Groups).filter(
Groups.uuid == group_uuid)
return groups.first()
except Exception as exception:
@ -61,14 +68,35 @@ class GroupRecord:
LOG.log_exception(message, exception)
raise
def get_group_id_from_uuid(self, uuid):
result = self.session.connection().scalar("SELECT id from groups WHERE uuid = \"{}\"".format(uuid)) # nosec
def get_group_id_from_uuid(self, group_uuid):
cmd = "SELECT id from groups WHERE uuid = %s"
result = self.session.connection().scalar(cmd, (group_uuid))
if result:
return int(result)
else:
return None
def get_groups_status_by_uuids(self, uuid_str):
cmd = "SELECT id, resource_id, region, status FROM " \
"rds_resource_status_view WHERE resource_id IN (%s)"
results = self.session.connection().execute(cmd, (uuid_str))
group_region = {}
if results:
resource_status = dict(
(id, (resource_id, region, status))
for id, resource_id, region, status in results)
# using resource_status, create group_region with resource_id
# as key and (region, status) as value
for v in resource_status.values():
if v[0] in group_region:
group_region[v[0]].append(v[1:])
else:
group_region[v[0]] = [v[1:]]
results.close()
return group_region
def delete_group_by_uuid(self, uuid):
try:
result = self.session.query(Groups).filter(
@ -85,9 +113,8 @@ class GroupRecord:
try:
LOG.info("get_groups_by_criteria: criteria: {0}".format(criteria))
region = criteria['region'] if 'region' in criteria else None
user = criteria['user'] if 'user' in criteria else None
rgroup = criteria['rgroup'] if 'rgroup' in criteria else None
starts_with = criteria['starts_with'] if 'starts_with' in criteria else None
starts_with = criteria['starts_with'] if 'starts_with' in \
criteria else None
contains = criteria['contains'] if 'contains' in criteria else None
query = self.session.query(Groups)
@ -100,11 +127,20 @@ class GroupRecord:
query = query.filter(
Groups.name.ilike("%{}%".format(contains)))
if region:
query = query.join(GroupRegion).filter(
GroupRegion.group_id == Groups.uuid)
query = query.join(Region).filter(
Region.id == GroupRegion.region_id,
Region.type == 'single',
Region.name == region)
query = self.customise_query(query, criteria)
return query.all()
except Exception as exception:
message = "Failed to get_groups_by_criteria: criteria: {0}".format(criteria)
message = "Failed to get_groups_by_criteria: " \
"criteria: {0}".format(criteria)
LOG.log_exception(message, exception)
raise

View File

@ -0,0 +1,97 @@
from orm.services.customer_manager.cms_rest.data.sql_alchemy.group_record \
import GroupRecord
from orm.services.customer_manager.cms_rest.data.sql_alchemy.models \
import GroupRegion
from orm.services.customer_manager.cms_rest.data.sql_alchemy.region_record \
import RegionRecord
from orm.services.customer_manager.cms_rest.logger import get_logger
LOG = get_logger(__name__)
class GroupsRegionRecord:
def __init__(self, session):
# thie model uses for the parameters for any acceess methods - not
# as instance of record in the table
self.__groups_region = GroupRegion()
self.__TableName = "groups_region"
if (session):
self.session = session
def setDBSession(self, session):
self.session = session
@property
def groups_region(self):
return self.__groups_region
@groups_region.setter
def groups_region(self):
self.__groups_region = GroupRegion()
def insert(self, group_region):
try:
self.session.add(group_region)
except Exception as exception:
LOG.log_exception(
"Failed to insert group_region" + str(group_region), exception)
raise
def get_regions_for_group(self, group_uuid):
group_regions = []
try:
group_record = GroupRecord(self.session)
group_id = group_record.get_group_id_from_uuid(group_uuid)
query = self.session.query(GroupRegion).filter(
GroupRegion.group_id == group_id)
for group_region in query.all():
group_regions.append(group_region)
return group_regions
except Exception as exception:
message = "Failed to get_region_names_for_group: %d" % (group_id)
LOG.log_exception(message, exception)
raise
def delete_region_for_group(self, group_uuid, region_name):
# get region id by name
region_record = RegionRecord(self.session)
region_id = region_record.get_region_id_from_name(region_name)
if region_id is None:
raise ValueError(
'region with the region name {0} not found'.format(
region_name))
cmd = 'DELETE FROM groups_region WHERE group_id = %s and \
region_id = %s'
result = self.session.connection().execute(cmd,
(group_uuid, region_id))
self.session.flush()
if result.rowcount == 0:
LOG.warn('region with the region name {0} not found'.format(
region_name))
raise ValueError(
'region with the region name {0} not found'.format(
region_name))
LOG.debug("num records deleted: " + str(result.rowcount))
return result
def delete_all_regions_for_group(self, group_id):
# group_id can be a uuid (type of string) or id (type of int).
# If group_id is uuid, then get id from uuid and use the id in the
# next sql command
if isinstance(group_id, basestring):
group_record = GroupRecord(self.session)
group_id = group_record.get_group_id_from_uuid(group_id)
# not including default region which is -1
cmd = 'DELETE FROM groups_region WHERE group_id = %s and \
region_id <> -1'
result = self.session.connection().execute(cmd, (group_id))
return result

View File

@ -33,8 +33,8 @@ class CmsDomain(Base, CMSBaseModel):
'''
' Groups is a DataObject and contains all the fields defined in Groups table record.
' defined as SqlAlchemy model map to a table
' Groups is a DataObject and contains all the fields defined in Groups
' table record, defined as SqlAlchemy model map to a table
'''
@ -43,16 +43,21 @@ class Groups(Base, CMSBaseModel):
id = Column(Integer, primary_key=True)
uuid = Column(String(64), nullable=False, unique=True)
domain_id = Column(Integer, ForeignKey('cms_domain.id'), primary_key=True, nullable=False)
domain_name = Column(String(64), ForeignKey('cms_domain.name'), nullable=False)
name = Column(String(64), nullable=False, unique=True)
description = Column(String(255), nullable=True)
enabled = Column(SmallInteger, nullable=False)
group_regions = relationship("GroupRegion", cascade="all, delete, delete-orphan")
def __json__(self):
return dict(
uuid=self.uuid,
name=self.name,
description=self.description,
domain_id=self.domain_id
domain_name=self.domain_name,
enabled=self.enabled,
group_regions=[group_region.__json__() for group_region in
self.group_regions]
)
def get_dict(self):
@ -62,23 +67,72 @@ class Groups(Base, CMSBaseModel):
proxy_dict = {
"uuid": self.uuid,
"name": self.name,
"domain_id": self.domain_id,
"description": self.description
"domain_name": self.domain_name,
"description": self.description,
"enabled": 1 if self.enabled else 0
}
group_regions = self.get_group_regions()
proxy_dict["regions"] = [group_region.get_proxy_dict() for group_region in group_regions]
return proxy_dict
def get_group_regions(self):
group_regions = []
for group_region in self.group_regions:
if group_region.region_id != -1:
group_regions.append(group_region)
return group_regions
def to_wsme(self):
uuid = self.uuid
name = self.name
domain_name = self.domain_name
description = self.description
enabled = True if self.enabled else False
regions = [group_region.to_wsme() for group_region in self.group_regions if
group_region.region_id != -1]
result = GroupWsmeModels.Group(description=description,
name=name,
uuid=uuid,
regions=regions,
enabled=enabled,
domain_name=domain_name)
return result
'''
' GroupRegion is a DataObject and contains all the fields defined in GroupRegion table record.
' defined as SqlAlchemy model map to a table
'''
class GroupRegion(Base, CMSBaseModel):
__tablename__ = "groups_region"
group_id = Column(String(64), ForeignKey('groups.uuid'), primary_key=True, nullable=False, index=True)
region_id = Column(Integer, ForeignKey('cms_region.id'), primary_key=True, nullable=False, index=True)
region = relationship("Region", viewonly=True)
def __json__(self):
return dict(
group_id=self.group_id,
region_id=self.region_id
)
def get_proxy_dict(self):
proxy_dict = {
"name": self.region.name,
"action": "modify"
}
return proxy_dict
def to_wsme(self):
uuid = self.uuid
name = self.name
domainId = self.domain_id
description = self.description
result = GroupWsmeModels.Group(description=description,
name=name,
uuid=uuid,
domainId=domainId)
return result
name = self.region.name
type = self.region.type
region = GroupWsmeModels.Region(name=name,
type=type)
return region
'''
' CmsUser is a DataObject and contains all the fields defined in CmsUser table record.

View File

@ -41,6 +41,7 @@
"groups:get_all": "rule:admin_or_support_or_viewer_or_creator",
"groups:create": "rule:admin_or_support_or_creator",
"groups:update": "rule:admin_or_creator",
"groups:delete": "rule:admin"
"groups:delete": "rule:admin",
"groups:add_region": "rule:admin_or_support_or_creator",
"groups:delete_region": "rule:admin_or_creator"
}

View File

@ -1,12 +1,20 @@
from pecan import request
from pecan import conf, request
import requests
from orm.common.orm_common.utils import utils
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 (ErrorStatus)
from orm.services.customer_manager.cms_rest.model.GroupModels import (GroupResultWrapper, GroupSummary,
GroupSummaryResponse)
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__)
@ -21,14 +29,47 @@ class GroupLogic(object):
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')
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()
@ -49,17 +90,19 @@ class GroupLogic(object):
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()
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()
# new_group_dict = sql_group.get_proxy_dict()
group_result_wrapper = build_response(group_uuid, transaction_id, 'update')
datamanager.flush() # i want to get any exception created by this insert
group_result_wrapper = build_response(group_uuid, transaction_id,
'update')
datamanager.flush()
datamanager.commit()
return group_result_wrapper
@ -69,17 +112,75 @@ class GroupLogic(object):
datamanager.rollback()
raise
def get_group(self, group):
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()
ret_group.status = 'no regions'
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
@ -87,16 +188,48 @@ class GroupLogic(object):
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)
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
@ -109,12 +242,59 @@ class GroupLogic(object):
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))
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() # i want to get any exception created by this delete
datamanager.flush()
datamanager.commit()
except Exception as exp:
LOG.log_exception("GroupLogic - Failed to delete group", exp)

View File

@ -1,14 +1,38 @@
from orm.services.customer_manager.cms_rest.logic.error_base import ErrorStatus
from orm.services.customer_manager.cms_rest.model.Model import Model
from orm.common.orm_common.utils.cross_api_utils import (get_regions_of_group,
set_utils_conf)
from pecan import conf
import wsme
from wsme import types as wtypes
class Region(Model):
"""network model the group
"""network model the region
"""
def __init__(self, id):
self.id = id
name = wsme.wsattr(wsme.types.text, mandatory=True)
type = wsme.wsattr(wsme.types.text, default="single", mandatory=False)
status = wsme.wsattr(wsme.types.text, mandatory=False)
error_message = wsme.wsattr(wsme.types.text, mandatory=False)
def __init__(self, name="", type="single", users=[], status="",
error_message=""):
"""Create a new region.
:param name: region name
:param type: region type
:param quotas: quotas ( array of Quota)
:param users: array of users of specific region
:param status: status of creation
:param error_message: error message if status is error
"""
self.name = name
self.type = type
self.users = users
self.status = status
if error_message:
self.error_message = error_message
class Group(Model):
@ -17,12 +41,13 @@ class Group(Model):
description = wsme.wsattr(wsme.types.text, mandatory=True)
name = wsme.wsattr(wsme.types.text, mandatory=True)
status = wsme.wsattr(wsme.types.text, mandatory=False)
domainId = wsme.wsattr(int, mandatory=True)
domain_name = wsme.wsattr(wsme.types.text, mandatory=True)
uuid = wsme.wsattr(wsme.types.text, mandatory=False)
enabled = wsme.wsattr(bool, mandatory=True)
regions = wsme.wsattr([Region], mandatory=False)
def __init__(self, description="", name="",
regions=[], status="", domainId=1, uuid=None):
def __init__(self, description="", name="", enabled=False,
regions=[], status="", domain_name='default', uuid=None):
"""Create a new Group.
:param description: Server name
@ -31,7 +56,8 @@ class Group(Model):
self.description = description
self.name = name
self.status = status
self.domainId = domainId
self.domain_name = domain_name
self.enabled = enabled
self.regions = regions
if uuid is not None:
self.uuid = uuid
@ -44,18 +70,27 @@ class Group(Model):
if context == "update":
for region in self.regions:
if region.type == "group":
raise ErrorStatus(400, "region type is invalid for update, \'group\' can be only in create")
raise ErrorStatus(400,
"region type is invalid for update, "
" \'group\' can be only in create")
def handle_region_group(self):
regions_to_add = []
for region in self.regions[:]: # get copy of it to be able to delete from the origin
# get copy of it to be able to delete from the origin
for region in self.regions[:]:
if region.type == "group":
group_regions = self.get_regions_for_group(region.name)
if not group_regions:
raise ErrorStatus(404, 'Group {} Not found'.format(region.name))
raise ErrorStatus(
404, 'Group {} Not found'.format(region.name))
self.regions.remove(region)
# remove duplicates if exist
self.regions.extend(set(regions_to_add))
self.regions.extend(set(regions_to_add)) # remove duplicates if exist
def get_regions_for_group(self, group_name):
set_utils_conf(conf)
regions = get_regions_of_group(group_name)
return regions
class GroupResult(Model):
@ -83,33 +118,44 @@ class GroupResultWrapper(Model):
self.group = group_result
""" GroupSummary is a DataObject and contains all the fields defined in GroupSummary structure. """
""" GroupSummary is a DataObject and contains all the fields
defined in GroupSummary structure.
"""
class GroupSummary(Model):
name = wsme.wsattr(wsme.types.text)
id = wsme.wsattr(wsme.types.text)
description = wsme.wsattr(wsme.types.text)
domain_id = wsme.wsattr(int, mandatory=True)
domain_name = wsme.wsattr(wsme.types.text)
enabled = wsme.wsattr(bool, mandatory=True)
status = wsme.wsattr(wtypes.text, mandatory=True)
regions = wsme.wsattr([str], mandatory=True)
def __init__(self, name='', id='', description='',
status="", domain_id=0):
status="", enabled=True, domain_name='default', regions=[]):
Model.__init__(self)
self.name = name
self.id = id
self.description = description
self.enabled = enabled
self.status = status
self.domain_id = domain_id
self.domain_name = domain_name
self.regions = regions
@staticmethod
def from_db_model(sql_group):
regions = [region.region.name for region in
sql_group.group_regions if
region.region_id != -1]
group = GroupSummary()
group.id = sql_group.uuid
group.name = sql_group.name
group.description = sql_group.description
group.domain_id = sql_group.domain_id
group.enabled = bool(sql_group.enabled)
group.domain_name = sql_group.domain_name
group.regions = regions
return group
@ -122,4 +168,31 @@ class GroupSummaryResponse(Model):
self.groups = []
""" Region Result Handler """
class RegionResult(Model):
id = wsme.wsattr(wsme.types.text, mandatory=True)
added = wsme.wsattr(wsme.types.text, mandatory=False)
links = wsme.wsattr({str: str}, mandatory=True)
def __init__(self, id, added=None, links={}):
self.id = id
self.added = added
self.links = links
class RegionResultWrapper(Model):
transaction_id = wsme.wsattr(wsme.types.text, mandatory=True)
regions = wsme.wsattr([RegionResult], mandatory=True)
def __init__(self, transaction_id, regions):
regions_result = [RegionResult(region['id'],
region['added'],
region['links']) for region in regions]
self.transaction_id = transaction_id
self.regions = regions_result
""" ****************************************************************** """

View File

@ -17,28 +17,34 @@ class RdsProxy(object):
def get_status(resource_id):
try:
LOG.debug(
"Sending to RDS Server to get status: " + conf.api.rds_server.base + conf.api.rds_server.status + resource_id)
"Sending to RDS Server to get status: " +
conf.api.rds_server.base + conf.api.rds_server.status +
resource_id)
resp = requests.get(
conf.api.rds_server.base + conf.api.rds_server.status + resource_id,
verify=conf.verify)
conf.api.rds_server.base + conf.api.rds_server.status +
resource_id, verify=conf.verify)
LOG.debug(
"Sending to RDS Server to get status: " + conf.api.rds_server.base + conf.api.rds_server.status + resource_id)
"Sending to RDS Server to get status: " +
conf.api.rds_server.base +
conf.api.rds_server.status + resource_id)
pp = pprint.PrettyPrinter(width=30)
pretty_text = pp.pformat(resp.json())
LOG.debug("Response from RDS Server:\n" + pretty_text)
return resp
except Exception as exp:
LOG.log_exception(
"CustomerLogic - Failed to Get status for customer : " + resource_id,
exp)
LOG.log_exception("CustomerLogic - Failed to Get status for "
"customer : " + resource_id, exp)
raise
@staticmethod
def send_customer(customer, transaction_id, method): # method is "POST" or "PUT"
return RdsProxy.send_customer_dict(customer.get_proxy_dict(), transaction_id, method)
def send_customer(customer, transaction_id, method):
# method is "POST" or "PUT"
return RdsProxy.send_customer_dict(customer.get_proxy_dict(),
transaction_id,
method)
@staticmethod
def send_customer_dict(customer_dict, transaction_id, method): # method is "POST" or "PUT"
def send_customer_dict(customer_dict, transaction_id, method):
data = {
"service_template":
{
@ -75,26 +81,105 @@ class RdsProxy(object):
'X-RANGER-Client'] if 'X-RANGER-Client' in request.headers else \
'NA'
headers['X-RANGER-Requester'] = request.headers[
'X-RANGER-Requester'] if 'X-RANGER-Requester' in request.headers else \
''
'X-RANGER-Requester'] if 'X-RANGER-Requester' in \
request.headers else ''
LOG.debug("Wrapper JSON before sending action: {0} to Rds Proxy\n{1}".format(method, pretty_text))
LOG.info("Sending to RDS Server: " + conf.api.rds_server.base + conf.api.rds_server.resources)
LOG.debug("Wrapper JSON before sending action: {0} to Rds "
"Proxy\n{1}".format(method, pretty_text))
LOG.info("Sending to RDS Server: " +
conf.api.rds_server.base + conf.api.rds_server.resources)
wrapper_json = json.dumps(data)
if method == "POST":
resp = requests.post(conf.api.rds_server.base + conf.api.rds_server.resources,
data=wrapper_json,
headers=headers,
verify=conf.verify)
resp = requests.post(
conf.api.rds_server.base + conf.api.rds_server.resources,
data=wrapper_json,
headers=headers,
verify=conf.verify)
else:
resp = requests.put(conf.api.rds_server.base + conf.api.rds_server.resources,
data=wrapper_json,
headers=headers,
verify=conf.verify)
resp = requests.put(
conf.api.rds_server.base + conf.api.rds_server.resources,
data=wrapper_json,
headers=headers,
verify=conf.verify)
if resp.content:
LOG.debug("Response Content from rds server: {0}".format(resp.content))
LOG.debug(
"Response Content from rds server: {0}".format(resp.content))
content = resp.content
if resp.content:
content = resp.json()
if resp.content and 200 <= resp.status_code < 300:
content = resp.json()
return content
raise ErrorStatus(resp.status_code, content)
@staticmethod
def send_group_dict(group_dict, transaction_id, method):
data = {
"service_template":
{
"resource": {
"resource_type": "group"
},
"model": str(json.dumps(group_dict)),
"tracking": {
"external_id": "",
"tracking_id": transaction_id
}
}
}
data_to_display = {
"service_template":
{
"resource": {
"resource_type": "group"
},
"model": group_dict,
"tracking": {
"external_id": "",
"tracking_id": transaction_id
}
}
}
pp = pprint.PrettyPrinter(width=30)
pretty_text = pp.pformat(data_to_display)
wrapper_json = json.dumps(data)
headers['X-RANGER-Client'] = request.headers[
'X-RANGER-Client'] if 'X-RANGER-Client' in request.headers else \
'NA'
headers['X-RANGER-Requester'] = request.headers[
'X-RANGER-Requester'] if 'X-RANGER-Requester' in \
request.headers else ''
LOG.debug("Wrapper JSON before sending action: {0} to Rds "
"Proxy\n{1}".format(method, pretty_text))
LOG.info("Sending to RDS Server: " + conf.api.rds_server.base +
conf.api.rds_server.resources)
wrapper_json = json.dumps(data)
if method == "POST":
resp = requests.post(
conf.api.rds_server.base + conf.api.rds_server.resources,
data=wrapper_json,
headers=headers,
verify=conf.verify)
else:
resp = requests.put(
conf.api.rds_server.base + conf.api.rds_server.resources,
data=wrapper_json,
headers=headers,
verify=conf.verify)
if resp.content:
LOG.debug(
"Response Content from rds server: {0}".format(resp.content))
content = resp.content
if resp.content:

View File

@ -106,52 +106,54 @@ create table if not exists groups
(
id integer auto_increment not null,
uuid varchar(64) not null,
domain_id integer not null,
domain_name varchar(64) not null,
name varchar(64) not null,
description varchar(255) not null,
enabled tinyint not null,
primary key (id),
foreign key (`domain_id`) references `cms_domain` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
foreign key (`domain_name`) references `cms_domain` (`name`) ON DELETE CASCADE ON UPDATE NO ACTION,
unique name_idx(name),
unique uuid_idx (uuid));
create table if not exists groups_region
(
region_id integer not null,
group_id integer not null,
group_id varchar(64) not null,
primary key (region_id, group_id),
foreign key (`region_id`) references `cms_region` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
foreign key (`group_id`) references `groups` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
foreign key (`group_id`) references `groups` (`uuid`) ON DELETE CASCADE ON UPDATE NO ACTION,
index region_id (region_id),
index group_id_idx (group_id));
create table if not exists group_role
create table if not exists groups_role
(
role_id integer not null,
group_id integer not null,
region_id integer not null,
group_id varchar(64) not null,
region_id integer not null,
primary key (role_id, region_id, group_id),
foreign key (role_id) references cms_role(id),
foreign key (`group_id`) references `groups` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
foreign key (role_id) references cms_role(id),
foreign key (`group_id`) references `groups` (`uuid`) ON DELETE CASCADE ON UPDATE NO ACTION,
index region_id (region_id),
index group_id_idx (group_id));
create table if not exists group_user
create table if not exists groups_user
(
group_id integer not null,
group_id varchar(64) not null,
user_id integer not null,
primary key (group_id, user_id),
foreign key (`user_id`) references `cms_user` (`id`) ON DELETE CASCADE,
foreign key (`group_id`) references `groups` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
foreign key (`group_id`) references `groups` (`uuid`) ON DELETE CASCADE ON UPDATE NO ACTION,
index user_id (user_id),
index group_id (group_id));
create table if not exists group_customer
create table if not exists groups_customer
(
group_id integer not null,
group_id varchar(64) not null,
customer_id integer not null,
region_id integer not null,
primary key (group_id, customer_id, region_id),
foreign key (`group_id`) references `groups` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
foreign key (`group_id`) references `groups` (`uuid`) ON DELETE CASCADE ON UPDATE NO ACTION,
foreign key (`customer_id`) references `customer` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
foreign key (`region_id`) references `cms_region` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
index customer_id_idx (customer_id),

View File

@ -3,6 +3,7 @@ SET sql_notes=0;
USE orm;
insert ignore into cms_region(id,name,type) values(-1, "DEFAULT", "single");
insert ignore into cms_domain(id,name) values(1, "default");
DROP PROCEDURE IF EXISTS MoveKeyToQuota;
DELIMITER ;;

View File

@ -41,7 +41,8 @@ audit = {
cms = {
'base_url': config.cms['base_url'],
'delete_region': 'v1/orm/customers/{0}/regions/{1}'
'delete_region': 'v1/orm/customers/{0}/regions/{1}',
'delete_groups_region': 'v1/orm/groups/{0}/regions/{1}'
}
fms = {
@ -115,6 +116,9 @@ yaml_configs = {
},
'image_yaml': {
'yaml_version': '2014-10-16'
},
'group_yaml': {
'yaml_version': '2014-10-16'
}
}
@ -148,18 +152,22 @@ region_resource_id_status = {
{
'customer',
'image',
'flavor'
'flavor',
'group'
},
'allowed_ranger_agent_resource_version':
{
'customer': '1.0',
'image': '1.0',
'flavor': '1.0'
'flavor': '1.0',
'group': '1.0'
}
}
app_module = app['modules'][0]
logging = config.get_log_config(config.rds['log'], app['service_name'], app_module)
logging = config.get_log_config(config.rds['log'],
app['service_name'],
app_module)
verify = config.ssl_verify

View File

@ -73,10 +73,11 @@ class Result(wtypes.DynamicBase):
"""class method, json header."""
customer = wsme.wsattr(CreatedResource, mandatory=False)
group = wsme.wsattr(CreatedResource, mandatory=False)
flavor = wsme.wsattr(CreatedResource, mandatory=False)
image = wsme.wsattr(CreatedResource, mandatory=False)
def __init__(self, customer=None,
def __init__(self, customer=None, group=None,
flavor=None, image=None):
"""init function.
@ -85,6 +86,8 @@ class Result(wtypes.DynamicBase):
"""
if customer is not None:
self.customer = customer
if group is not None:
self.group = group
if flavor is not None:
self.flavor = flavor
if image is not None:

View File

@ -212,7 +212,7 @@ def notify_ord(transaction_id,
:param transaction_id: The transaction id under which the resource was
updated
:param tracking_id: The tracking ID of the whole operation
:param resource_type: The resource type ("customer" | "image" | "flavor")
:param resource_type: The resource type ("customer" | "group" | "image" | "flavor")
:param resource_template_version: The version id of the change in git
:param resource_name: The updated resource name
:param resource_id: The updated resource ID

View File

@ -4,7 +4,8 @@ from pecan import conf
import requests
from orm.services.resource_distributor.rds.services.base import ErrorMessage
from orm.services.resource_distributor.rds.utils import authentication as AuthService
from orm.services.resource_distributor.rds.utils import \
authentication as AuthService
logger = logging.getLogger(__name__)
@ -25,26 +26,39 @@ def _set_headers(region):
def invoke_resources_region_delete(resource_type, region, resource_id):
logger.debug(
"REGION STATUS PROXY - send delete status to {} service for region {}".format(resource_type, region))
logger.debug("REGION STATUS PROXY - send delete status to {} service for "
"region {}".format(resource_type, region))
_set_headers(region)
try:
if resource_type == "customer":
logger.debug("sending the data to {} server delete method ".format(resource_type))
logger.debug("sending the data to {} server delete "
"method ".format(resource_type))
response = requests.delete(
conf.cms.base_url + (conf.cms.delete_region).format(resource_id, region),
conf.cms.base_url + (conf.cms.delete_region).format(
resource_id, region),
headers=headers, verify=conf.verify)
elif resource_type == "group":
logger.debug("sending the data to {} server delete "
"method ".format(resource_type))
response = requests.delete(
conf.cms.base_url + (conf.cms.delete_groups_region).format(
resource_id, region),
headers=headers, verify=conf.verify)
elif resource_type == "flavor":
logger.debug("sending the data to {} server delete method ".format(resource_type))
logger.debug("sending the data to {} server delete "
"method ".format(resource_type))
response = requests.delete(
conf.fms.base_url + (conf.fms.delete_region).format(resource_id, region),
conf.fms.base_url + (conf.fms.delete_region).format(
resource_id, region),
headers=headers, verify=conf.verify)
elif resource_type == "image":
logger.debug("sending the data to {} server delete method ".format(resource_type))
logger.debug("sending the data to {} server delete "
"method ".format(resource_type))
response = requests.delete(
conf.ims.base_url + (conf.ims.delete_region).format(resource_id, region),
conf.ims.base_url + (conf.ims.delete_region).format(
resource_id, region),
headers=headers, verify=conf.verify)
else:
response = None
@ -78,20 +92,22 @@ def send_image_metadata(meta_data, region, resource_id, action='post'):
_set_headers(region)
data_to_send_as_json = json.dumps(data_to_send)
logger.debug("sending the data to ims server post method ")
logger.debug("ims server {0} path = {1}".format(conf.ims.base_url,
conf.ims.metadata_path).format(
resource_id, region))
logger.debug("ims server {0} path = {1}".format(
conf.ims.base_url,
conf.ims.metadata_path).format(resource_id, region))
if action == 'post':
try:
response = requests.post(
conf.ims.base_url + (conf.ims.metadata_path).format(resource_id, region),
conf.ims.base_url + (conf.ims.metadata_path).format(
resource_id, region),
data=data_to_send_as_json, headers=headers, verify=conf.verify)
logger.debug("got response from ims {}".format(response))
except requests.ConnectionError as exp:
logger.error(exp)
logger.exception(exp)
raise ErrorMessage("fail to connect to server {}".format(exp.message))
raise ErrorMessage(
"fail to connect to server {}".format(exp.message))
if response.status_code != 200:
raise ErrorMessage(

View File

@ -4,7 +4,7 @@ import time
from orm.services.resource_distributor.rds.services import region_resource_id_status as regionResourceIdStatus
from orm.services.resource_distributor.rds.services import (yaml_customer_builder, yaml_flavor_bulder,
yaml_image_builder)
yaml_group_builder, yaml_image_builder)
from orm.services.resource_distributor.rds.services.base import ConflictValue, ErrorMessage
from orm.services.resource_distributor.rds.services.model.resource_input import ResourceData as InputData
from orm.services.resource_distributor.rds.sot import sot_factory
@ -20,7 +20,7 @@ def _get_inputs_from_resource_type(jsondata,
resource_type,
external_transaction_id,
operation="create"):
if resource_type == "customer":
if resource_type == "customer" or resource_type == "group":
input_data = InputData(resource_id=jsondata['uuid'],
resource_type=resource_type,
operation=operation,
@ -99,6 +99,8 @@ def _create_data_to_sot(input_data):
yamldata = "delete"
elif input_data.resource_type == "customer":
yamldata = yaml_customer_builder.yamlbuilder(jsondata, target)
elif input_data.resource_type == "group":
yamldata = yaml_group_builder.yamlbuilder(jsondata, target)
elif input_data.resource_type == "flavor":
yamldata = yaml_flavor_bulder.yamlbuilder(jsondata, target)
elif input_data.resource_type == "image":

View File

@ -0,0 +1,69 @@
"""yaml build build yaml from json input."""
import logging
import re
import yaml
from pecan import conf
logger = logging.getLogger(__name__)
def create_final_yaml(title, description, resources, outputs):
"""put all yaml strings together.
:param title: ther version of yaml
:param description: file description
:param resources: body of the yaml file
:param outputs: the output of the yaml
:return: the full string of yaml file
"""
title_yaml = re.sub("'", "", yaml.dump(title, default_flow_style=False))
description_yaml = yaml.dump(description, default_flow_style=False)
resourcesyaml = re.sub("''", '', yaml.dump(resources,
default_flow_style=False))
resources_yaml = re.sub("'", '', resourcesyaml)
yamldata = title_yaml
yamldata = yamldata + "\n" + description_yaml
yamldata = yamldata + "\n" + resources_yaml
yamldata = yamldata + "\n" + yaml.dump(outputs)
return yamldata
def yamlbuilder(alldata, region):
logger.info("building group yaml")
logger.debug("start building group yaml for region %s" % region['name'])
"""build group yaml.
build yaml file from json
:param alldata: full json data
:param region: data per region
:return: the full string of yaml file
"""
outputs = {}
resources = {}
yaml_version = conf.yaml_configs.group_yaml.yaml_version
title = {'heat_template_version': yaml_version}
description = {'description': 'yaml file for region - %s' % region['name']}
jsondata = alldata
group_name = jsondata['name']
group_description = '"%s"' % (jsondata['description'])
status = {"0": False, "1": True}[str(jsondata['enabled'])]
outputs['outputs'] = {}
resources['resources'] = {}
resources['resources'][group_name] =\
{'type': 'OS::Keystone::Group\n',
'properties': {'name': "%s" % group_name,
'description': group_description,
'domain': alldata['domain_name'],
'roles': []}}
# create the output
outputs['outputs'][group_name] =\
{"value": {"get_resource": "%s" % group_name}}
# putting all parts together for full yaml
yamldata = create_final_yaml(title, description, resources, outputs)
logger.debug(
"done building group yaml for region %s " % region['name'])
return yamldata

View File

@ -0,0 +1,224 @@
from orm.services.customer_manager.cms_rest.data.sql_alchemy\
import models as sql_models
from orm.services.customer_manager.cms_rest.logic.error_base import ErrorStatus
from orm.services.customer_manager.cms_rest.logic import group_logic
import orm.services.customer_manager.cms_rest.model.GroupModels as models
from orm.tests.unit.cms import FunctionalTest
import mock
group = None
data_manager_mock = None
record_mock = None
mock_returns_error = False
flow_type = 0
STATUS_JSON = {
"regions": [
{
"status": "Success",
"region": "GRP1",
"error_code": "",
"error_msg": ""
}
],
"status": "Success"
}
class RdsStatus(object):
def __init__(self, status_code=200, status="Success", oy=False):
self.status_code = status_code
self.status = status
self.oy = oy
def json(self):
if self.oy:
return {}
else:
return {"status": self.status}
class TestGroupLogic(FunctionalTest):
def setUp(self):
global group
FunctionalTest.setUp(self)
group_logic.DataManager = get_mock_datamanager
group_logic.pecan = mock.MagicMock()
group_logic.utils = mock.MagicMock()
group_logic.utils.make_transid.return_value = 'some_trans_id'
group_logic.utils.audit_trail.return_value = None
group_logic.utils.make_uuid.return_value = 'some_uuid'
group_logic.utils.get_time_human.return_value = '111'
group_logic.RdsProxy = mock.MagicMock()
group_logic.RdsProxy.send_group.return_value = None
group_logic.RdsProxy.get_status.return_value = RdsStatus()
group_logic.build_response = mock.MagicMock()
group = models.Group()
global flow_type
flow_type = 0
def tearDown(self):
global mock_returns_error
FunctionalTest.tearDown(self)
mock_returns_error = False
def test_create_group_success_with_regions(self):
group.regions = [models.Region(name="a")]
group.name = 'Group Name'
logic = group_logic.GroupLogic()
logic.create_group(group, 'some_uuid', 'some_trans_id')
assert data_manager_mock.commit.called
assert not data_manager_mock.rollback.called
def test_delete_region_success(self):
logic = group_logic.GroupLogic()
logic.delete_region('group_id', 'region_id', 'transaction_is', True,
False)
assert record_mock.delete_region_for_group.called
assert data_manager_mock.commit.called
def test_delete_region_success_force_delete(self):
logic = group_logic.GroupLogic()
logic.delete_region('group_id', 'region_id', 'transaction_is', True,
True)
assert record_mock.delete_region_for_group.called
assert data_manager_mock.commit.called
def test_delete_region_error(self):
global mock_returns_error
mock_returns_error = True
logic = group_logic.GroupLogic()
self.assertRaises(SystemError, logic.delete_region, 'group_id',
'region_id', 'transaction_is', True, False)
assert data_manager_mock.rollback.called
def test_get_group_list_by_criteria(self):
logic = group_logic.GroupLogic()
result = logic.get_group_list_by_criteria(None, None, None, None)
self.assertTrue(data_manager_mock.get_record.called)
self.assertTrue(record_mock.get_groups_by_criteria.called)
def test_get_group_success(self):
logic = group_logic.GroupLogic()
get_mock = mock.MagicMock()
get_mock.json.return_value = STATUS_JSON
group_logic.requests.get = mock.MagicMock(return_value=get_mock)
logic.get_group('group_id')
self.assertTrue(data_manager_mock.get_group_by_uuid_or_name.called)
def test_get_group_not_found(self):
global flow_type
flow_type = 1
logic = group_logic.GroupLogic()
self.assertRaises(ErrorStatus, logic.get_group, 'group_id')
self.assertTrue(data_manager_mock.get_group_by_uuid_or_name.called)
def test_delete_group_by_uuid_success(self):
logic = group_logic.GroupLogic()
logic.delete_group_by_uuid('group_id')
# Customer found in CMS DB but not found in RDS
group_logic.RdsProxy.get_status.return_value = RdsStatus(
status_code=404)
logic.delete_group_by_uuid('group_id')
def test_delete_group_by_uuid_not_found(self):
global flow_type
# Change the flow to "customer not found in CMS DB"
flow_type = 1
logic = group_logic.GroupLogic()
# test that ErrorStatus exception is raised when no customer found
with self.assertRaises(group_logic.ErrorStatus):
logic.delete_group_by_uuid('group_id')
def test_delete_group_by_uuid_errors(self):
global mock_returns_error
mock_returns_error = True
logic = group_logic.GroupLogic()
self.assertRaises(SystemError, logic.delete_group_by_uuid, 'group_id')
# RDS returned an empty json
mock_returns_error = False
group_logic.RdsProxy.get_status.return_value = RdsStatus(oy=True)
self.assertRaises(group_logic.ErrorStatus,
logic.delete_group_by_uuid,
'group_id')
# RDS returned 500
group_logic.RdsProxy.get_status.return_value = RdsStatus(
status_code=500)
self.assertRaises(group_logic.ErrorStatus,
logic.delete_group_by_uuid,
'group_id')
# RDS returned Error status
group_logic.RdsProxy.get_status.return_value = RdsStatus(
status='Error')
self.assertRaises(group_logic.ErrorStatus,
logic.delete_group_by_uuid,
'group_id')
def test_delete_group_by_uuid_conflict(self):
global flow_type
flow_type = 2
logic = group_logic.GroupLogic()
self.assertRaises(group_logic.ErrorStatus, logic.delete_group_by_uuid,
'group_id')
def get_mock_datamanager():
global data_manager_mock
global record_mock
sql_group = sql_models.Groups(name='a')
sql_group.group_regions = []
data_manager_mock = mock.MagicMock()
record_mock = mock.MagicMock()
record_mock.get_groups_by_criteria.return_value = [sql_group]
def _get_group():
def mock_to_wsme():
return models.Group(regions=[models.Region()])
sql_group = sql_models.Groups()
sql_group.to_wsme = mock_to_wsme
sql_group.uuid = '1234'
sql_group.status = 'Success'
sql_group.name = 'GRP1'
return sql_group
if not mock_returns_error:
data_manager_mock.get_group_by_uuid_or_name.return_value = _get_group()
record_mock.delete_region_for_group.return_value = None
record_mock.delete_group_by_uuid.return_value = None
if flow_type == 1:
record_mock.read_group_by_uuid.return_value = None
data_manager_mock.get_group_by_uuid_or_name.return_value = None
elif flow_type == 2:
q = mock.MagicMock()
q.get_group_regions.return_value = [mock.MagicMock()]
record_mock.read_group_by_uuid.return_value = q
record_mock.delete_group_by_uuid.side_effect = SystemError()
else:
record_mock.read_group_by_uuid.side_effect = SystemError()
record_mock.delete_region_for_group.side_effect = SystemError()
data_manager_mock.get_record.return_value = record_mock
return data_manager_mock

View File

@ -0,0 +1,217 @@
import mock
import requests
from orm.services.customer_manager.cms_rest.controllers.v1.orm.group\
import root
from orm.services.customer_manager.cms_rest.logic.error_base import ErrorStatus
from orm.services.customer_manager.cms_rest.model import GroupModels
from orm.tests.unit.cms import FunctionalTest, test_utils
from wsme.exc import ClientSideError
group_logic_mock = None
class TestGroupController(FunctionalTest):
def setUp(self):
FunctionalTest.setUp(self)
root.authentication = mock.MagicMock()
root.GroupLogic = get_mock_group_logic
root.GroupLogic.return_error = 0
root.utils = mock.MagicMock()
root.utils.make_transid.return_value = 'some_trans_id'
root.utils.audit_trail.return_value = None
root.utils.make_uuid.return_value = 'some_uuid'
root.err_utils = mock.MagicMock()
def tearDown(self):
FunctionalTest.tearDown(self)
def test_create_group(self):
# given
requests.post = mock.MagicMock(return_value=ResponseMock(201))
# when
response = self.app.post_json('/v1/orm/groups', GROUP_JSON)
# assert
assert response.status_int == 201
assert root.utils.audit_trail.called
assert root.utils.create_or_validate_uuid.called
assert group_logic_mock.create_group_called
def test_create_group_fail(self):
# given
requests.post = mock.MagicMock()
root.GroupLogic.return_error = 1
root.err_utils.get_error = mock.MagicMock(
return_value=ClientSideError("blabla", 500))
# when
response = self.app.post_json('/v1/orm/groups',
GROUP_JSON, expect_errors=True)
# assert
self.assertEqual(response.status_int, 500)
def test_get_group(self):
# given
requests.get = mock.MagicMock(return_value=ResponseMock(200))
# when
response = self.app.get('/v1/orm/groups/some_id')
# assert
assert response.status_int == 200
assert group_logic_mock.get_group.called
def test_get_group_fail_bad_request(self):
# given
requests.put = mock.MagicMock()
root.GroupLogic.return_error = 1
root.err_utils.get_error = mock.MagicMock(
return_value=ClientSideError("blabla", 500))
# when
response = self.app.get('/v1/orm/groups/some_id', expect_errors=True)
# assert
self.assertEqual(response.status_int, 500)
assert group_logic_mock.get_group.called
def test_get_group_fail(self):
# given
requests.put = mock.MagicMock()
root.GroupLogic.return_error = 2
root.err_utils.get_error = mock.MagicMock(
return_value=ClientSideError("blabla", 404))
# when
response = self.app.get('/v1/orm/groups/some_id', expect_errors=True)
# assert
self.assertEqual(response.status_int, 404)
assert group_logic_mock.get_group.called
def test_get_list_group(self):
# given
requests.get = mock.MagicMock(return_value=ResponseMock(200))
# when
response = self.app.get('/v1/orm/groups?region=region')
# assert
assert group_logic_mock.get_group_list_by_criteria.called
def test_get_list_group_fail(self):
# given
requests.get = mock.MagicMock()
root.GroupLogic.return_error = 1
root.err_utils.get_error = mock.MagicMock(
return_value=ClientSideError("blabla", 500))
# when
response = self.app.get('/v1/orm/groups?region=region',
expect_errors=True)
# assert
self.assertEqual(response.status_int, 500)
def test_get_list_group_bad_request(self):
# given
requests.get = mock.MagicMock()
root.GroupLogic.return_error = 2
root.err_utils.get_error = mock.MagicMock(
return_value=ClientSideError("blabla", 500))
# when
response = self.app.get('/v1/orm/groups?region=region',
expect_errors=True)
# assert
self.assertEqual(response.status_int, 500)
@mock.patch.object(root, 'authentication')
def test_delete_group_success(self, mock_auth):
response = self.app.delete('/v1/orm/groups/test')
self.assertEqual(response.status_int, 204)
@mock.patch.object(root, 'authentication')
def test_delete_group_conflict(self, mock_auth):
root.GroupLogic.return_error = 2
root.err_utils.get_error = test_utils.get_error
response = self.app.delete('/v1/orm/groups/test', expect_errors=True)
self.assertEqual(response.status_int, 409)
@mock.patch.object(root, 'authentication')
def test_delete_group_error(self, mock_auth):
root.GroupLogic.return_error = 1
root.err_utils.get_error = test_utils.get_error
response = self.app.delete('/v1/orm/groups/test', expect_errors=True)
self.assertEqual(response.status_int, 500)
def get_mock_group_logic():
global group_logic_mock
group_logic_mock = mock.MagicMock()
if root.GroupLogic.return_error == 0:
res = GroupModels.GroupResultWrapper(transaction_id='1',
id='1',
links={},
updated=None,
created='1')
list_res = GroupModels.GroupSummaryResponse()
list_res.groups.append(
GroupModels.GroupSummary(name='1', id='1', description='1'))
group_logic_mock.get_group.return_value = GroupModels.Group(
**RET_GROUP_JSON)
group_logic_mock.get_group_list_by_criteria.return_value = list_res
group_logic_mock.create_group.return_value = res
elif root.GroupLogic.return_error == 1:
group_logic_mock.create_group.side_effect = SystemError()
group_logic_mock.get_group.side_effect = SystemError()
group_logic_mock.get_group_list_by_criteria.side_effect = SystemError()
group_logic_mock.delete_group_by_uuid.side_effect = SystemError()
else:
group_logic_mock.get_group.side_effect = ErrorStatus(status_code=404)
group_logic_mock.get_group_list_by_criteria.side_effect = ErrorStatus(
status_code=404)
group_logic_mock.delete_group_by_uuid.side_effect = ErrorStatus(
status_code=409)
return group_logic_mock
class ResponseMock:
def __init__(self, status_code=200):
self.status_code = status_code
GROUP_JSON = {
"description": "Group description",
"enabled": True,
"name": "myGroup",
"domain_name": "default",
"regions": [
{
"name": "SAN1",
"type": "single"
}
]
}
RET_GROUP_JSON = {
"description": "Group description",
"name": "myName",
"domain_name": "default",
"enabled": True,
"regions": [GroupModels.Region()]
}

View File

@ -33,6 +33,7 @@ class CmsTests(TestCase):
# Set up the args parameter
args = mock.MagicMock()
args.custid = 'test_custid'
args.groupid = 'test_groupid'
args.regionid = 'test_region'
args.userid = 'test_userid'
args.region = 'test_region'
@ -42,35 +43,57 @@ class CmsTests(TestCase):
args.force_delete is False
subcmd_to_result = {
'create_customer': (requests.post, '',),
'delete_customer': (requests.delete, '/%s' % args.custid,),
'update_customer': (requests.put, '/%s' % args.custid,),
'add_region': (requests.post, '/%s/regions' % args.custid,),
'replace_region': (requests.put, '/%s/regions' % args.custid,),
'create_customer': (requests.post, 'customers/',),
'delete_customer': (
requests.delete, 'customers/%s' % args.custid,),
'update_customer': (requests.put, 'customers/%s' % args.custid,),
'add_region': (
requests.post, 'customers/%s/regions' % args.custid,),
'replace_region': (
requests.put, 'customers/%s/regions' % args.custid,),
'delete_region': (
requests.delete,
'/%s/regions/%s/%s' % (args.custid, args.regionid,
args.force_delete),),
'customers/%s/regions/%s/%s' % (args.custid, args.regionid,
args.force_delete),),
'add_user': (
requests.post,
'/%s/regions/%s/users' % (args.custid, args.regionid),),
requests.post, 'customers/%s/regions/%s/users' % (
args.custid, args.regionid),),
'replace_user': (
requests.put,
'/%s/regions/%s/users' % (args.custid, args.regionid),),
'delete_user': (requests.delete, '/%s/regions/%s/users/%s' % (
args.custid, args.regionid, args.userid),),
'add_default_user': (requests.post, '/%s/users' % args.custid,),
'replace_default_user': (requests.put, '/%s/users' % args.custid,),
'customers/%s/regions/%s/users' % (
args.custid, args.regionid),),
'delete_user': (
requests.delete, 'customers/%s/regions/%s/users/%s' % (
args.custid, args.regionid, args.userid),),
'add_default_user': (
requests.post, 'customers/%s/users' % args.custid,),
'replace_default_user': (
requests.put, 'customers/%s/users' % args.custid,),
'delete_default_user': (
requests.delete, '/%s/users/%s' % (args.custid, args.userid),),
'add_metadata': (requests.post, '/%s/metadata' % args.custid,),
'replace_metadata': (requests.put, '/%s/metadata' % args.custid,),
'get_customer': (requests.get, '/%s' % args.custid,),
requests.delete, 'customers/%s/users/%s' % (
args.custid, args.userid),),
'add_metadata': (
requests.post, 'customers/%s/metadata' % args.custid,),
'replace_metadata': (
requests.put, 'customers/%s/metadata' % args.custid,),
'get_customer': (requests.get, 'customers/%s' % args.custid,),
'list_customers': (requests.get,
'/?region=%s&user=%s&starts_with=%s'
'customers/?region=%s&user=%s&starts_with=%s'
'&contains=%s' % (args.region,
args.user, args.starts_with,
args.contains))
args.contains)),
'delete_group': (
requests.delete, 'groups/%s' % args.groupid,),
'delete_groups_region': (
requests.delete,
'groups/%s/regions/%s/%s' % (args.groupid, args.regionid,
args.force_delete),),
'get_group': (requests.get, 'groups/%s' % args.groupid,),
'list_groups': (requests.get,
'groups/?region=%s&starts_with=%s'
'&contains=%s' % (args.region,
args.starts_with,
args.contains))
}
# Assert that each subcommand returns the expected details
@ -105,7 +128,10 @@ class CmsTests(TestCase):
@mock.patch.object(cmscli.cli_common, 'get_keystone_ep')
@mock.patch.object(cmscli.requests, 'post')
@mock.patch.object(cmscli.requests, 'get')
def test_list_customers(self, mock_get, mock_post, mock_get_keystone_ep):
@mock.patch.object(cmscli, 'get_token')
@mock.patch.object(cmscli, 'globals')
def test_list_customers(self, mock_globals, mock_get_token,
mock_get, mock_post, mock_get_keystone_ep):
mock_post.return_value = self.respond(TJ, 200)
mock_get.return_value = self.mock_response
args = ormcli.main('orm cms list_customers t'.split())
@ -222,7 +248,7 @@ class CmsTests(TestCase):
@mock.patch('requests.get')
@mock.patch('requests.post')
def test_list_customers(self, mock_post, mock_get):
def test_list_customers_with_filters(self, mock_post, mock_get):
cli = ormcli.Cli()
cli.create_parser()
cli.parse(
@ -230,3 +256,70 @@ class CmsTests(TestCase):
resp = self.respond('{"Hi, mom"}', 200, {'X-Subject-Token': 989})
mock_post.return_value = self.respond(
{"access": {"token": {"id": 989}}}, 200)
@mock.patch.object(cmscli.cli_common, 'get_keystone_ep')
@mock.patch.object(cmscli.requests, 'post')
@mock.patch.object(cmscli.requests, 'get')
@mock.patch.object(cmscli, 'get_token')
@mock.patch.object(cmscli, 'globals')
def test_list_groups(self, mock_globals, mock_get_token,
mock_get, mock_post, mock_get_keystone_ep):
mock_post.return_value = self.respond(TJ, 200)
mock_get.return_value = self.mock_response
args = ormcli.main('orm cms list_groups t'.split())
sys.stdout.seek(0)
output = sys.stdout.read()
self.assertIn(json.dumps(TJ), output)
@mock.patch.object(cmscli.cli_common, 'get_keystone_ep')
@mock.patch.object(cmscli.requests, 'post')
@mock.patch.object(cmscli.requests, 'get')
@mock.patch.object(cmscli, 'get_token')
@mock.patch.object(cmscli, 'globals')
def test_list_groups_a(self, mock_globals, mock_get_token,
mock_get, mock_post, mock_get_keystone_ep):
mock_post.return_value = self.respond(TJ, 200)
mock_get.return_value = self.mock_response
mock_get.__name__ = 'a'
args = ormcli.main('orm cms --verbose list_groups t'.split())
sys.stdout.seek(0)
output = sys.stdout.read()
self.assertIn(json.dumps(TJ), output)
@mock.patch.object(cmscli.cli_common, 'get_keystone_ep')
@mock.patch.object(cmscli.requests, 'post')
@mock.patch.object(cmscli.requests, 'get')
def test_list_groups_e(self, mock_get, mock_post, mock_get_keystone_ep):
mock_post.return_value = self.respond(TJ, 200)
mock_get.side_effect = Exception('e')
with self.assertRaises(SystemExit) as cm:
args = ormcli.main('orm cms list_groups t'.split())
self.assertEqual(cm.exception.code, 1)
sys.stdout.seek(0)
output = sys.stdout.read()
self.assertIn('e', output)
@mock.patch.object(cmscli.cli_common, 'get_keystone_ep')
@mock.patch.object(cmscli.requests, 'post')
@mock.patch.object(cmscli.requests, 'get')
@mock.patch.object(cmscli, 'get_token')
@mock.patch.object(cmscli, 'globals')
def test_list_groups_errors(self, mock_globals, mock_get_token,
mock_get, mock_post,
mock_get_keystone_ep):
mock_post.return_value = self.respond(TJ, 200)
mock_get.return_value = self.respond(TJ, 204, oy=True)
with self.assertRaises(SystemExit) as cm:
args = ormcli.main('orm cms list_groups t'.split())
self.assertEqual(cm.exception.code, 0)
sys.stdout.seek(0)
output = sys.stdout.read()
self.assertEqual('', output)
mock_get.return_value = self.respond(TJ, 404, oy=True)
with self.assertRaises(SystemExit) as cm:
args = ormcli.main('orm cms --faceless list_groups t'.split())
self.assertEqual(cm.exception.code, 1)
sys.stdout.seek(0)
output = sys.stdout.read()
self.assertIn('API error:', output)

View File

@ -0,0 +1,42 @@
"""unittests create group yaml module."""
from mock import patch
import unittest
import yaml
from orm.services.resource_distributor.rds.services import\
yaml_group_builder as GroupBuild
alldata = {
'domain_name': 'nc',
'description': 'this is a description', 'enabled': 1,
'regions': [{'name': 'regionname'}],
'name': 'test_group'}
yaml_group = \
'heat_template_version: 2015-1-1\n\ndescription: yaml file for region - ' \
'regionname\n\nresources:\n'\
' test_group:\n properties:\n'\
' description: "this is a description"\n'\
' domain: nc\n'\
' name: test_group\n roles: []\n'\
' type: OS::Keystone::Group\n\n\n'\
'outputs:\n'\
' test_group:\n'\
' value: {get_resource: test_group}\n'
region = {'name': 'regionname',
'rangerAgentVersion': 1.0}
class CreateResource(unittest.TestCase):
"""class metohd."""
maxDiff = None
@patch.object(GroupBuild, 'conf')
def test_create_group_yaml_nousers(self, mock_conf):
"""test valid dict to yaml output as expected without users."""
ver = mock_conf.yaml_configs.group_yaml.yaml_version = '2015-1-1'
yamlfile = GroupBuild.yamlbuilder(alldata, region)
yamlfile_as_json = yaml.safe_load(yamlfile)
self.assertEqual(yamlfile_as_json['heat_template_version'], ver)
self.assertEqual(yaml.safe_load(yamlfile), yaml.safe_load(yaml_group))