Merge diverged code

Change-Id: I7a88d9bec69371bec1004572a4fa87cdfbbf1f28
This commit is contained in:
Nicholas Jones 2018-04-27 14:18:18 -05:00 committed by nj762h
parent 2eddcd66c6
commit dac751d04b
145 changed files with 5375 additions and 3096 deletions

View File

@ -0,0 +1,219 @@
"""keystone_utils token validator unittests."""
import mock
import unittest
from keystone_utils import tokens
class MyResponse(object):
def __init__(self, status, json_result):
self.status_code = status
self._json_result = json_result
def json(self):
return self._json_result
class MyKeystone(object):
def validate(self, a):
raise tokens.v3_client.exceptions.NotFound('test')
def find(self, **kwargs):
raise tokens.v3_client.exceptions.NotFound('test')
class MyClient(object):
def __init__(self, set_tokens=True):
if set_tokens:
self.tokens = MyKeystone()
else:
self.tokens = mock.MagicMock()
self.roles = MyKeystone()
class TokensTest(unittest.TestCase):
def setUp(self):
tokens._KEYSTONES = {}
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_find_keystone_ep_sanity(self, mock_get):
result = tokens._find_keystone_ep('a', 'b')
self.assertEqual(result, 'test')
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE + 1, {'regions': [{'endpoints': [
{'publicURL': 'test', 'type': 'identity'}]}]}))
def test_find_keystone_ep_bad_return_code(self, mock_get):
result = tokens._find_keystone_ep('a', 'b')
self.assertIsNone(result)
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {}))
def test_find_keystone_ep_no_keystone_ep_in_response(self, mock_get):
result = tokens._find_keystone_ep('a', 'b')
self.assertIsNone(result)
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'test'}]}]}))
def test_find_keystone_ep_no_identity_in_response(self, mock_get):
result = tokens._find_keystone_ep('a', 'b')
self.assertIsNone(result)
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
@mock.patch.object(tokens.v3_client, 'Client')
def test_is_token_valid_sanity(self, mock_get, mock_client):
self.assertTrue(tokens.is_token_valid('a', 'b', tokens.TokenConf(
'a', 'b', 'c', 'd', '3')))
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
@mock.patch.object(tokens.v3_client, 'Client')
def test_is_token_valid_sanity_role_required(self, mock_get, mock_client):
user = {'user': {'id': 'test_id', 'domain': {'id': 'test'}}}
mock_client.tokens.validate = mock.MagicMock(return_value=user)
self.assertTrue(tokens.is_token_valid('a', 'b', tokens.TokenConf(
'a', 'b', 'c', 'd', '3'), 'test', {'domain': 'test'}))
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_token_not_found(self, mock_get):
client_backup = tokens.v3_client.Client
tokens.v3_client.Client = mock.MagicMock(return_value=MyClient())
self.assertFalse(tokens.is_token_valid('a', 'b', tokens.TokenConf(
'a', 'b', 'c', 'd', '3')))
tokens.v3_client.Client = client_backup
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_invalid_version(self, mock_get):
client_backup = tokens.v3_client.Client
tokens.v3_client.Client = mock.MagicMock(return_value=MyClient())
self.assertRaises(ValueError, tokens.is_token_valid, 'a', 'b',
tokens.TokenConf('a', 'b', 'c', 'd', '4'))
tokens.v3_client.Client = client_backup
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_keystone_v2(self, mock_get):
client_backup = tokens.v2_client.Client
tokens.v2_client.Client = mock.MagicMock()
self.assertFalse(tokens.is_token_valid('a', 'b',
tokens.TokenConf('a', 'b', 'c',
'd', '2.0'),
'test',
{'tenant': 'test'}))
tokens.v2_client.Client = client_backup
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_keystone_v2_invalid_location(self, mock_get):
client_backup = tokens.v2_client.Client
tokens.v2_client.Client = mock.MagicMock()
self.assertRaises(ValueError, tokens.is_token_valid, 'a', 'b',
tokens.TokenConf('a', 'b', 'c', 'd', '2.0'), 'test',
{'domain': 'test'})
tokens.v2_client.Client = client_backup
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE + 1, {'regions': [{'endpoints': [
{'publicURL': 'test', 'type': 'identity'}]}]}))
def test_is_token_valid_keystone_ep_not_found(self, mock_get):
self.assertRaises(tokens.KeystoneNotFoundError, tokens.is_token_valid,
'a', 'b', tokens.TokenConf('a', 'b', 'c', 'd', '3'))
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_no_role_location(self, mock_get):
tokens.v3_client.Client = mock.MagicMock()
self.assertRaises(ValueError, tokens.is_token_valid, 'a', 'b',
tokens.TokenConf('a', 'b', 'c', 'd', '3'), 'test')
@mock.patch.object(tokens.v3_client, 'Client')
def test_does_user_have_role_sanity_true(self, mock_client):
user = {'user': {'id': 'test_id', 'domain': {'id': 'test'}}}
self.assertTrue(tokens._does_user_have_role(mock_client, '3', user,
'admin',
{'domain': 'test'}))
@mock.patch.object(tokens.v3_client, 'Client')
def test_does_user_have_role_sanity_false(self, mock_client):
user = {'user': {'id': 'test_id', 'domain': {'id': 'test'}}}
mock_client.roles.check = mock.MagicMock(
side_effect=tokens.v3_client.exceptions.NotFound('test'))
self.assertFalse(tokens._does_user_have_role(mock_client, '3', user,
'admin',
{'domain': 'test'}))
@mock.patch.object(tokens.v3_client, 'Client')
def test_does_user_have_role_invalid_user(self, mock_client):
user = {}
self.assertFalse(tokens._does_user_have_role(mock_client, '3', user,
'admin',
{'domain': 'test'}))
@mock.patch.object(tokens.v3_client, 'Client')
def test_does_user_have_role_role_does_not_exist(self, mock_client):
user = {'user': {'id': 'test_id', 'domain': {'id': 'test'}}}
mock_client.roles.find = mock.MagicMock(
side_effect=tokens.v3_client.exceptions.NotFound('test'))
self.assertRaises(tokens.v3_client.exceptions.NotFound,
tokens._does_user_have_role, mock_client, '3',
user, 'test', {'domain': 'default'})
@mock.patch.object(tokens.requests, 'get', return_value=MyResponse(
tokens.OK_CODE, {'regions': [{'endpoints': [{'publicURL': 'test',
'type': 'identity'}]}]}))
def test_is_token_valid_role_does_not_exist(self, mock_get):
tokens.v3_client.Client = mock.MagicMock(return_value=MyClient(False))
self.assertRaises(ValueError, tokens.is_token_valid, 'a', 'b',
tokens.TokenConf('a', 'b', 'c', 'd', '3'), 'test',
{'domain': 'test'})
def test_get_token_user_invalid_arguments(self):
self.assertRaises(ValueError, tokens.get_token_user, 'a', 'b')
@mock.patch.object(tokens, '_find_keystone_ep', return_value=None)
def test_get_token_user_keystone_ep_not_found(self,
mock_find_keystone_ep):
self.assertRaises(tokens.KeystoneNotFoundError,
tokens.get_token_user, 'a', mock.MagicMock(), 'c')
def test_get_token_user_invalid_keystone_version(self):
conf = tokens.TokenConf(None, None, None, None, None)
self.assertRaises(ValueError, tokens.get_token_user, 'a', conf, 'c',
'd')
@mock.patch.object(tokens, '_get_keystone_client')
def test_get_token_user_token_not_found(self, mock_get_keystone_client):
ks = mock.MagicMock()
ks.tokens.validate.side_effect = tokens.v3_client.exceptions.NotFound()
mock_get_keystone_client.return_value = ks
conf = tokens.TokenConf('3', '3', '3', '3', '3')
self.assertIsNone(tokens.get_token_user('a', conf, 'c', 'd'))
@mock.patch.object(tokens, '_get_keystone_client')
def test_get_token_user_success(self, mock_get_keystone_client):
token_info = mock.MagicMock()
token_info.token = 'a'
token_info.user = 'test_user'
ks = mock.MagicMock()
ks.tokens.validate.return_value = token_info
mock_get_keystone_client.return_value = ks
conf = tokens.TokenConf('2.0', '2.0', '2.0', '2.0', '2.0')
result = tokens.get_token_user('a', conf, 'c', 'd')
self.assertEqual(result.token, 'a')
self.assertEqual(result.user, 'test_user')

View File

@ -1,6 +1,5 @@
"""Token utility module."""
import logging
import requests
from orm.common.client.keystone.mock_keystone.keystoneclient import exceptions
@ -8,6 +7,8 @@ from orm.common.client.keystone.mock_keystone.keystoneclient.v2_0 import client
from orm.common.client.keystone.mock_keystone.keystoneclient.v3 import client as v3_client
from orm.common.orm_common.utils import dictator
from pecan import request
_verify = False
OK_CODE = 200
@ -96,6 +97,10 @@ def get_token_user(token, conf, lcp_id=None, keystone_ep=None):
try:
token_info = keystone.tokens.validate(token)
logger.debug('User token found in Keystone')
if not request.headers.get('X-RANGER-Requester'):
request.headers['X-RANGER-Requester'] = \
token_info.user['username']
return TokenUser(token_info)
# Other exceptions raised by validate() are critical errors,
# so instead of returning False, we'll just let them propagate

View File

@ -1,5 +1,4 @@
import logging
from pecan.hooks import PecanHook
logger = logging.getLogger(__name__)

View File

@ -10,7 +10,7 @@ class ResourceProviderRegister:
# Maps resource names to a provider
self.resource_providers = {}
def register(self, resource_name, provider=None, allow_override=True):
def register(self, resource_name, provider=None, allow_override=False):
if provider is None:
# Give a partial usable as a decorator
return partial(

View File

@ -23,6 +23,7 @@ import six
from orm.common.orm_common.utils import api_error_utils as err_utils
from orm.common.orm_common.utils import dictator
logger = logging.getLogger(__name__)
registered_checks = {}
@ -214,22 +215,19 @@ class RoleCheck(Check):
"""Check that there is a matching role in the ``user`` object."""
def __call__(self, target, user, enforcer):
try:
logger.debug('Checking role:{}'.format(self.match))
result = any(
[role['name'] == self.match for role in user.user['roles']])
logger.debug('Role check result: {}'.format(result))
if not result:
logger.info(
'INFO|CON{}AUTH001|Not allowed to perform this operation,'
' user:{} does not have role:{}'.format(
dictator.get('service_name', 'ORM'),
user.user['name'], self.match))
raise err_utils.get_error('N/A', status_code=403)
return result
except Exception:
logger.debug('Invalid user, failing role check')
raise
logger.debug('Checking against policy role:{}'.format(self.match))
result = any(
[role['name'] == self.match for role in user.user['roles']])
logger.debug('Role check result: {}'.format(result))
if not result:
logger.info(
'INFO|CON{}AUTH001|Not allowed to perform this operation,'
' user:{} does not have role:{}'.format(
dictator.get('service_name', 'ORM'),
user.user['name'], self.match))
return result
@register('user')

View File

@ -22,6 +22,7 @@ import six
import _checks
LOG = logging.getLogger(__name__)
@ -210,7 +211,7 @@ def _parse_check(rule):
try:
kind, match = rule.split(':', 1)
except Exception:
LOG.exception('Failed to understand rule %s', rule)
LOG.exception(('Failed to understand rule %s'), rule)
# If the rule is invalid, we'll fail closed
return _checks.FalseCheck()
@ -220,7 +221,7 @@ def _parse_check(rule):
elif None in _checks.registered_checks:
return _checks.registered_checks[None](kind, match)
else:
LOG.error('No handler for matches of kind %s', kind)
LOG.error(('No handler for matches of kind %s'), kind)
return _checks.FalseCheck()
@ -336,7 +337,7 @@ def _parse_text_rule(rule):
return state.result
except ValueError:
# Couldn't parse the rule
LOG.exception('Failed to understand rule %s', rule)
LOG.exception(('Failed to understand rule %s'), rule)
# Fail closed
return _checks.FalseCheck()

View File

@ -131,6 +131,10 @@ def authorize(action, request, app_conf, keystone_ep=None):
token_to_validate = request.headers.get('X-Auth-Token')
lcp_id = request.headers.get('X-Auth-Region')
keystone_ep = keystone_ep if keystone_ep else (
request.headers.get('Keystone-Endpoint'))
try:
if _is_authorization_enabled(app_conf):
try:

View File

@ -219,7 +219,9 @@ import logging
import os
import _parser
from orm.common.orm_common.utils import api_error_utils as err_utils
from oslo_config import cfg
from oslo_policy import _checks
from oslo_policy._i18n import _
from oslo_serialization import jsonutils
@ -525,9 +527,6 @@ class Enforcer(object):
# If it is False, raise the exception if requested
if do_raise and not result:
if exc:
raise exc(*args, **kwargs)
raise PolicyNotAuthorized(rule, target, creds)
raise err_utils.get_error('N/A', status_code=403)
return result

View File

View File

@ -0,0 +1,68 @@
import json
import logging
import mock
from orm_common.hooks import api_error_hook
from unittest import TestCase
logger = logging.getLogger(__name__)
class TestAPIErrorHook(TestCase):
@mock.patch.object(api_error_hook, 'err_utils')
@mock.patch.object(api_error_hook, 'json')
def test_after_401(self, mock_json, mock_err_utils):
a = api_error_hook.APIErrorHook()
state = mock.MagicMock()
mock_err_utils.get_error_dict.return_value = 'B'
mock_json.loads = json.loads
mock_json.dumps = json.dumps
state.response.status_code = 401
a.after(state)
self.assertEqual(state.response.body,
json.dumps(mock_err_utils.get_error_dict.return_value))
@mock.patch.object(api_error_hook, 'err_utils')
def test_after_not_an_error(self, mock_err_utils):
a = api_error_hook.APIErrorHook()
state = mock.MagicMock()
mock_err_utils.get_error_dict.return_value = 'B'
state.response.body = 'AAAA'
temp = state.response.body
# A successful status code
state.response.status_code = 201
a.after(state)
# Assert that the response body hasn't changed
self.assertEqual(state.response.body, temp)
@mock.patch.object(api_error_hook, 'err_utils')
@mock.patch.object(api_error_hook.json, 'loads',
side_effect=ValueError('test'))
def test_after_error(self, mock_json, mock_err_utils):
a = api_error_hook.APIErrorHook()
state = mock.MagicMock()
mock_err_utils.get_error_dict.return_value = 'B'
state.response.body = 'AAAA'
mock_json.loads = mock.MagicMock(side_effect=ValueError('sd'))
state.response.status_code = 402
a.after(state)
self.assertEqual(state.response.body,
json.dumps(mock_err_utils.get_error_dict.return_value))
@mock.patch.object(api_error_hook, 'err_utils')
@mock.patch.object(api_error_hook, 'json')
def test_after_success(self, mock_json, mock_err_utils):
a = api_error_hook.APIErrorHook()
state = mock.MagicMock()
mock_err_utils.get_error_dict.return_value = 'B'
mock_json.loads = json.loads
mock_json.dumps = json.dumps
mock_json.loads = json.loads
state.response.body = '{"debuginfo": null, "faultcode": "Client", "faultstring": "{\\"code\\": 404, \\"created\\": \\"1475768730.95\\", \\"details\\": \\"\\", \\"message\\": \\"customer: q not found\\", \\"type\\": \\"Not Found\\", \\"transaction_id\\": \\"mock_json5efa7416fb4d408cc0e30e4373cf00\\"}"}'
state.response.status_code = 400
a.after(state)
self.assertEqual(json.loads(state.response.body), json.loads('{"message": "customer: q not found", "created": "1475768730.95", "type": "Not Found", "details": "", "code": 404, "transaction_id": "mock_json5efa7416fb4d408cc0e30e4373cf00"}'))

View File

@ -0,0 +1,31 @@
import mock
from orm_common.hooks import security_headers_hook
from unittest import TestCase
class MyHeaders(object):
def __init__(self):
self.headers = {}
def add(self, key, value):
self.headers[key] = value
class TestSecurityHeadersHook(TestCase):
def test_after(self):
s = security_headers_hook.SecurityHeadersHook()
test_headers = MyHeaders()
state = mock.MagicMock()
state.response.headers = test_headers
s.after(state)
security_headers = {'X-Frame-Options': 'DENY',
'X-Content-Type-Options': 'nosniff',
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
'Content-Security-Policy': 'default-src \'self\'',
'X-Permitted-Cross-Domain-Policies': 'none',
'X-XSS-Protection': '1; mode=block'}
for header in security_headers:
self.assertEqual(security_headers[header],
test_headers.headers[header])

View File

@ -0,0 +1,17 @@
import logging
import mock
from orm_common.hooks import transaction_id_hook
from unittest import TestCase
logger = logging.getLogger(__name__)
class TestTransactionIdHook(TestCase):
@mock.patch.object(transaction_id_hook.utils, 'make_transid',
return_value='test')
def test_before_sanity(self, mock_make_transid):
t = transaction_id_hook.TransactionIdHook()
state = mock.MagicMock()
t.before(state)
self.assertEqual(state.request.transaction_id, 'test')
self.assertEqual(state.request.tracking_id, 'test')

View File

@ -0,0 +1,57 @@
import logging
import mock
from orm_common.injector import injector
import os
from unittest import TestCase
logger = logging.getLogger(__name__)
class TestInjector(TestCase):
def setUp(self):
pass
@mock.patch.object(injector, '_import_file_by_name')
def test_register_providers(self, mock_import_file_by_name):
os.environ['CMS_ENV'] = 'test'
injector.register_providers('CMS_ENV', 'a/b/c', logger)
@mock.patch.object(injector, '_import_file_by_name')
def test_register_providers_env_not_exist(self, mock_import_file_by_name):
injector.register_providers('CMS_ENV1', 'a/b/c', logger)
@mock.patch.object(injector, '_import_file_by_name')
def test_register_providers_env_test(self, mock_import_file_by_name):
os.environ['CMS_ENV2'] = '__TEST__'
injector.register_providers('CMS_ENV2', 'a/b/c', logger)
@mock.patch.object(injector, '_import_file_by_name')
def test_register_providers_with_existing_provider(self, mock_import_file_by_name):
mock_import_file_by_name.return_value = type('module', (object,), {'providers': ['a1', 'b2']})()
os.environ['c3'] = 'test'
injector.register_providers('c3', 'a/b/c', logger)
def test_get_di(self):
injector.get_di()
@mock.patch.object(injector, 'logger')
def test_import_file_by_name_ioerror(self, mock_logger):
injector.logger = mock.MagicMock()
# Calling it with ('', '.') should raise an IOError
# (no such file or directory)
self.assertRaises(IOError, injector._import_file_by_name, '', '.')
@mock.patch.object(injector.imp, 'load_source', return_value='test')
def test_import_file_by_name_sanity(self, mock_load_source):
self.assertEqual(injector._import_file_by_name('', '.'), 'test')
@mock.patch.object(injector._di.providers, 'register_instance')
def test_override_injected_dependency(self, mock_di):
injector.override_injected_dependency((1, 2,))
self.assertTrue(mock_di.called)
'''
@mock.patch.object(ResourceProviderRegister, 'register_instance')
def test_override_injected_dependency(self, mock_resourceProviderRegister):
injector.override_injected_dependency(mock.Mock())
'''

View File

@ -0,0 +1,103 @@
import mock
import unittest
from orm_common.policy import _checks
class TestChecks(unittest.TestCase):
def test_call_simple_checks(self):
check = _checks.FalseCheck()
self.assertFalse(check(1, 2, 3))
check = _checks.TrueCheck()
self.assertTrue(check(1, 2, 3))
check = _checks.GenericCheck('a', 'b')
self.assertFalse(check(1, 2, 3))
def test_str_simple_checks(self):
check = _checks.FalseCheck()
self.assertEqual(str(check), '!')
check = _checks.TrueCheck()
self.assertEqual(str(check), '@')
check = _checks.GenericCheck('a', 'b')
self.assertEqual(str(check), 'a:b')
def test_call_complex_checks(self):
first_rule = _checks.TrueCheck()
second_rule = _checks.FalseCheck()
check = _checks.NotCheck(first_rule)
self.assertFalse(check(1, 2, 3))
check = _checks.AndCheck([first_rule])
check.add_check(second_rule)
self.assertFalse(check(1, 2, 3))
check = _checks.AndCheck([first_rule, first_rule])
self.assertTrue(check(1, 2, 3))
check = _checks.OrCheck([first_rule])
check.add_check(second_rule)
self.assertTrue(check(1, 2, 3))
self.assertEqual(check.pop_check(), (check, second_rule,))
check = _checks.OrCheck([second_rule, second_rule])
self.assertFalse(check(1, 2, 3))
def test_str_complex_checks(self):
first_rule = _checks.TrueCheck()
second_rule = _checks.FalseCheck()
check = _checks.NotCheck(first_rule)
self.assertEqual(str(check), 'not @')
check = _checks.AndCheck([first_rule])
check.add_check(second_rule)
self.assertEqual(str(check), '(@ and !)')
check = _checks.OrCheck([first_rule])
check.add_check(second_rule)
self.assertEqual(str(check), '(@ or !)')
def test_call_custom_checks_error(self):
check = _checks.RoleCheck('a', 'admin')
# test no longer valid.
# change: https://gerrit.mtn5.cci.att.com/#/c/25690/
# removed the exception raise
#
# try:
# check(1, mock.MagicMock(), 3)
# self.fail('ClientSideError not raised!')
# except ClientSideError as exc:
# self.assertEqual(exc.code, 403)
for check_type in (_checks.TenantCheck,
_checks.DomainCheck):
check = check_type('a', 'admin')
# 2 is not a user, so the check will fail
self.assertFalse(check(1, 2, 3))
def test_call_custom_checks_success(self):
user = mock.MagicMock()
user.user = {'roles': [{'name': 'admin'}]}
user.tenant = {'name': 'admin'}
user.domain = {'name': 'admin'}
for check_type in (_checks.RoleCheck,
_checks.TenantCheck,
_checks.DomainCheck):
check = check_type('a', 'admin')
# 2 is not a user, so the check will fail
self.assertTrue(check(1, user, 3))
def test_call_rule_check_error(self):
enforcer = mock.MagicMock()
enforcer.rules = {'test': mock.MagicMock(
side_effect=KeyError('test'))}
check = _checks.RuleCheck('rule', 'test')
self.assertFalse(check(1, 2, enforcer))
def test_call_rule_check_success(self):
enforcer = mock.MagicMock()
enforcer.rules = {'test': mock.MagicMock(return_value=True)}
check = _checks.RuleCheck('rule', 'test')
self.assertTrue(check(1, 2, enforcer))

View File

@ -0,0 +1,129 @@
import mock
import unittest
from orm_common.policy import policy
class Exception_Test(Exception):
pass
class TestPolicy(unittest.TestCase):
def setUp(self):
policy._ENFORCER = None
policy._POLICY_FILE = None
policy._TOKEN_CONF = None
def test_reset(self):
policy._ENFORCER = mock.MagicMock()
policy._POLICY_FILE = mock.MagicMock()
policy.reset()
self.assertIsNone(policy._ENFORCER)
self.assertIsNone(policy._POLICY_FILE)
# Call it a second time when they are both None and see
# that no exception is raised
policy.reset()
self.assertIsNone(policy._ENFORCER)
self.assertIsNone(policy._POLICY_FILE)
@mock.patch.object(policy, 'open')
@mock.patch.object(policy.qolicy, 'Enforcer')
@mock.patch.object(policy.qolicy, 'Rules')
def test_init_success(self, mock_rules, mock_enforcer, mock_open):
policy_file = 'a'
token_conf = 'b'
mock_rules.load_json.return_value = 'c'
policy.init(policy_file, token_conf)
self.assertEqual(policy._POLICY_FILE, 'a')
self.assertEqual(policy._TOKEN_CONF, 'b')
def test_init_enforcer_already_exists(self):
policy._ENFORCER = mock.MagicMock()
# Nothing should happen when the enforcer already exists, so make sure
# that no exception is raised
policy.init('a', 'b')
@mock.patch.object(policy, 'open')
@mock.patch.object(policy.qolicy, 'Rules')
@mock.patch.object(policy, '_ENFORCER')
def test_reset_rules_no_policy_file(self, mock_enforcer,
mock_rules, mock_open):
self.assertRaises(ValueError, policy.reset_rules)
@mock.patch.object(policy, 'open')
@mock.patch.object(policy.qolicy, 'Rules')
@mock.patch.object(policy, '_ENFORCER')
def test_reset_rules_success(self, mock_enforcer,
mock_rules, mock_open):
policy._POLICY_FILE = mock.MagicMock()
policy.reset_rules()
self.assertTrue(mock_enforcer.set_rules.called)
@mock.patch.object(policy, 'reset_rules')
@mock.patch.object(policy.tokens, 'get_token_user',
side_effect=ValueError('test'))
@mock.patch.object(policy, '_ENFORCER')
def test_enforce_enforcer_error(self, mock_enforcer,
mock_get_token_user,
mock_reset_rules):
mock_enforcer.enforce.side_effect = policy.EnforcerError()
self.assertRaises(policy.EnforcerError, policy.enforce, 'action',
'token', mock.MagicMock())
@mock.patch.object(policy, 'reset_rules')
@mock.patch.object(policy.tokens, 'get_token_user')
@mock.patch.object(policy, '_ENFORCER')
def test_enforce_success(self, mock_enforcer,
mock_get_token_user,
mock_reset_rules):
mock_enforcer.enforce.return_value = True
self.assertTrue(policy.enforce('action', 'token', mock.MagicMock()))
def test_authorize_authorization_disabled(self):
request = mock.MagicMock()
app_conf = mock.MagicMock()
app_conf.authentication.enabled = False
# No exception should be raised
policy.authorize('a', request, app_conf)
@mock.patch.object(policy, 'enforce')
def test_authorize_no_token(self, mock_enforce):
request = mock.MagicMock()
request.headers.get.return_value = None
app_conf = mock.MagicMock()
app_conf.authentication.enabled = True
# No exception should be raised
policy.authorize('a', request, app_conf)
@mock.patch.object(policy, 'enforce', side_effect=policy.EnforcerError())
@mock.patch.object(policy.err_utils, 'get_error', return_value=Exception_Test)
def test_authorize_enforce_failed(self, mock_enforce, mock_get_error):
request = mock.MagicMock()
request.headers.get.return_value = None
app_conf = mock.MagicMock()
app_conf.authentication.enabled = True
self.assertRaises(Exception_Test, policy.authorize, 'a', request,
app_conf)
@mock.patch.object(policy, 'enforce', side_effect=ValueError())
@mock.patch.object(policy.err_utils, 'get_error', return_value=Exception_Test)
def test_authorize_other_error(self, mock_enforce, mock_get_error):
request = mock.MagicMock()
request.headers.get.return_value = None
app_conf = mock.MagicMock()
app_conf.authentication.enabled = True
self.assertRaises(Exception_Test, policy.authorize, 'a', request,
app_conf)
@mock.patch.object(policy, 'enforce')
def test_authorize_success(self, mock_enforce):
request = mock.MagicMock()
request.headers.get.return_value = 'test'
app_conf = mock.MagicMock()
app_conf.authentication.enabled = True
# No exception should be raised
policy.authorize('a', request, app_conf)

View File

@ -0,0 +1,14 @@
import json
import mock
from orm_common.utils import api_error_utils
from unittest import TestCase
class TestCrossApiUtil(TestCase):
@mock.patch.object(api_error_utils.utils, 'get_time_human', return_value=1.337)
def test_get_error_default_message(self, mock_time):
self.assertEqual(
json.loads(api_error_utils.get_error('test', 'a').message),
{"details": "a", "message": "Incompatible JSON body",
"created": "1.337", "code": 400, "type": "Bad Request",
"transaction_id": "test"})

View File

@ -0,0 +1,74 @@
import mock
from orm_common.utils import cross_api_utils
import time
from unittest import TestCase
class TestCrossApiUtil(TestCase):
@mock.patch('pecan.conf')
def setUp(self, mock_conf):
self.mock_response = mock.Mock()
cross_api_utils.conf = mock_conf
def respond(self, value, code):
self.mock_response.json.return_value = value
self.mock_response.status_code = code
return self.mock_response
def test_set_utils_conf(self):
cross_api_utils.set_utils_conf(None)
self.assertEqual(cross_api_utils.conf, None)
def test_check_conf_initialization(self):
cross_api_utils.set_utils_conf(None)
self.assertRaises(AssertionError, cross_api_utils._check_conf_initialization)
@mock.patch('orm_common.utils.cross_api_utils.get_rms_region_group')
def test_is_region_group_exist(self, mock_rms_region_group):
mock_rms_region_group.return_value = 'test_group'
exist = cross_api_utils.is_region_group_exist('test_group_name')
self.assertEqual(exist, True)
@mock.patch('orm_common.utils.cross_api_utils.get_rms_region_group')
def test_is_region_group_exist_false(self, mock_rms_region_group):
mock_rms_region_group.return_value = None
exist = cross_api_utils.is_region_group_exist('test_group_name')
self.assertEqual(exist, False)
@mock.patch('orm_common.utils.cross_api_utils.get_rms_region_group')
def test_get_regions_of_group(self, mock_rms_region_group):
mock_rms_region_group.return_value = {'regions': 'group'}
exist = cross_api_utils.get_regions_of_group('test_group_name')
self.assertEqual(exist, 'group')
@mock.patch('orm_common.utils.cross_api_utils.get_rms_region_group')
def test_get_regions_of_group_false(self, mock_rms_region_group):
mock_rms_region_group.return_value = None
exist = cross_api_utils.get_regions_of_group('test_group_name')
self.assertEqual(exist, None)
@mock.patch('requests.get')
def test_get_rms_region_group(self, mock_get):
mock_get.return_value = self.respond({'result': 'success'}, 200)
result = cross_api_utils.get_rms_region_group('test_group_name')
self.assertEqual(result, {'result': 'success'})
def test_get_rms_region_group_cache_used(self):
cross_api_utils.prev_timestamp = time.time()
cross_api_utils.prev_group_name = 'test_group'
cross_api_utils.prev_resp = 'test_response'
cross_api_utils.conf.api.rms_server.cache_seconds = 14760251830
self.assertEqual(cross_api_utils.prev_resp,
cross_api_utils.get_rms_region_group(
cross_api_utils.prev_group_name))
@mock.patch.object(cross_api_utils, 'logger')
@mock.patch.object(time, 'time', side_effect=ValueError('test'))
def test_get_rms_region_group_cache_used(self, mock_time, mock_logger):
self.assertRaises(ValueError, cross_api_utils.get_rms_region_group,
'test')
# @mock.patch('requests.get')
# def test_get_rms_region_group_with_exception(self, mock_get):
# mock_get.side_affect = Exception('boom')
# self.assertRaises(Exception, cross_api_utils.get_rms_region_group, 'test_group_name')

View File

@ -0,0 +1,177 @@
import logging
import mock
from orm_common.utils import utils
import pprint
from testfixtures import log_capture
from unittest import TestCase
class TestUtil(TestCase):
@mock.patch('pecan.conf')
def setUp(self, mock_conf):
self.mock_response = mock.Mock()
utils.conf = mock_conf
def respond(self, value, code):
self.mock_response.json.return_value = value
self.mock_response.status_code = code
return self.mock_response
@mock.patch('requests.post')
def test_make_uuid(self, mock_post):
mock_post.return_value = self.respond({'uuid': '987654321'}, 200)
uuid = utils.create_or_validate_uuid('', 'uuidtype')
self.assertEqual(uuid, '987654321')
@mock.patch('requests.post')
@log_capture('orm_common.utils.utils', level=logging.INFO)
def test_make_uuid_offline(self, mock_post, l):
mock_post.side_effect = Exception('boom')
uuid = utils.create_or_validate_uuid('', 'uuidtype')
self.assertEqual(uuid, None)
l.check(('orm_common.utils.utils', 'INFO', 'Failed in make_uuid:boom'))
@mock.patch('requests.post')
def test_make_transid(self, mock_post):
mock_post.return_value = self.respond({'uuid': '987654321'}, 200)
uuid = utils.make_transid()
self.assertEqual(uuid, '987654321')
@mock.patch('requests.post')
@log_capture('orm_common.utils.utils', level=logging.INFO)
def test_make_transid_offline(self, mock_post, l):
mock_post.side_effect = Exception('boom')
uuid = utils.make_transid()
self.assertEqual(uuid, None)
l.check(
('orm_common.utils.utils', 'INFO', 'Failed in make_transid:boom'))
@mock.patch('audit_client.api.audit.init')
@mock.patch('audit_client.api.audit.audit')
def test_audit_trail(self, mock_init, mock_audit):
resp = utils.audit_trail('create customer', '1234',
{'X-RANGER-Client': 'Fred'}, '5678')
self.assertEqual(resp, 200)
@mock.patch('audit_client.api.audit.audit')
def test_audit_trail_offline(self, mock_audit):
mock_audit.side_effect = Exception('boom')
resp = utils.audit_trail('create customer', '1234',
{'X-RANGER-Client': 'Fred'}, '5678')
self.assertEqual(resp, None)
@mock.patch('audit_client.api.audit.init')
@mock.patch('audit_client.api.audit.audit')
def test_audit_service_args_least(self, mock_audit, mock_init):
resp = utils.audit_trail('create customer', '1234',
{'X-RANGER-Client': 'Fred'}, '5678')
self.assertEqual(mock_audit.call_args[0][1], 'Fred') # application_id
self.assertEqual(mock_audit.call_args[0][2], '1234') # tracking_id
self.assertEqual(mock_audit.call_args[0][3], '1234') # transaction_id
self.assertEqual(mock_audit.call_args[0][4],
'create customer') # transaction_type
self.assertEqual(mock_audit.call_args[0][5], '5678') # resource_id
# self.assertEqual(mock_audit.call_args[0][6], 'cms') # service
self.assertEqual(mock_audit.call_args[0][7], '') # user_id
self.assertEqual(mock_audit.call_args[0][8], 'NA') # external_id
self.assertEqual(mock_audit.call_args[0][9], '') # event_details
# self.assertEqual(mock_audit.call_args[0][10], 'Saved to DB') # status
@mock.patch('audit_client.api.audit.init')
@mock.patch('audit_client.api.audit.audit')
def test_audit_service_with_tracking(self, mock_audit, mock_init):
utils.audit_trail('create customer', '1234',
{'X-RANGER-Client': 'Fred',
'X-RANGER-Tracking-Id': 'Track12'}, '5678')
self.assertEqual(mock_audit.call_args[0][1], 'Fred') # application_id
self.assertEqual(mock_audit.call_args[0][2], 'Track12') # tracking_id
self.assertEqual(mock_audit.call_args[0][3], '1234') # transaction_id
self.assertEqual(mock_audit.call_args[0][4],
'create customer') # transaction_type
self.assertEqual(mock_audit.call_args[0][5], '5678') # resource_id
# self.assertEqual(mock_audit.call_args[0][6], 'cms') # service
self.assertEqual(mock_audit.call_args[0][7], '') # user_id
self.assertEqual(mock_audit.call_args[0][8], 'NA') # external_id
self.assertEqual(mock_audit.call_args[0][9], '') # event_details
# self.assertEqual(mock_audit.call_args[0][10], 'Saved to DB') # status
@mock.patch('audit_client.api.audit.init')
@mock.patch('audit_client.api.audit.audit')
def test_audit_service_with_requester(self, mock_audit, mock_init):
resp = utils.audit_trail('create customer', '1234',
{'X-RANGER-Client': 'Fred',
'X-RANGER-Requester': 'Req04'}, '5678')
self.assertEqual(mock_audit.call_args[0][1], 'Fred') # application_id
self.assertEqual(mock_audit.call_args[0][2], '1234') # tracking_id
self.assertEqual(mock_audit.call_args[0][3], '1234') # transaction_id
self.assertEqual(mock_audit.call_args[0][4], 'create customer') # transaction_type
self.assertEqual(mock_audit.call_args[0][5], '5678') # resource_id
# self.assertEqual(mock_audit.call_args[0][6], 'cms') # service
self.assertEqual(mock_audit.call_args[0][7], 'Req04') # user_id
self.assertEqual(mock_audit.call_args[0][8], 'NA') # external_id
self.assertEqual(mock_audit.call_args[0][9], '') # event_details
# self.assertEqual(mock_audit.call_args[0][10], 'Saved to DB') # status
def test_set_utils_conf(self):
utils.set_utils_conf('test')
self.assertEqual(utils.conf, 'test')
def test_check_conf_initialization(self):
utils.set_utils_conf(None)
self.assertRaises(AssertionError, utils._check_conf_initialization)
@mock.patch('requests.post')
def test_create_existing_uuid(self, mock_post):
uuid = '987654321'
uuid_type = 'testtype'
mock_post.return_value = self.respond(
{'uuid': uuid, 'uuid_type': uuid_type}, 200)
returned_uuid = utils.create_or_validate_uuid(uuid, uuid_type)
self.assertEqual(returned_uuid, uuid)
@mock.patch('requests.post')
def test_create_existing_uuid_with_exception(self, mock_post):
mock_post.side_effect = Exception('boom')
uuid = '987654321'
uuid_type = 'testtype'
returned_uuid = utils.create_or_validate_uuid(uuid, uuid_type)
self.assertEqual(returned_uuid, None)
@mock.patch('requests.post')
def test_create_existing_uuid_with_400(self, mock_post):
uuid = '987654321'
uuid_type = 'testId'
mock_post.return_value = self.respond({'uuid': uuid, 'uuid_type': uuid_type}, 409)
self.assertRaises(TypeError, utils.create_or_validate_uuid(uuid, uuid_type))
@mock.patch('pecan.conf')
def test_report_config(self, mock_conf):
expected_value = pprint.pformat(mock_conf.to_dict(), indent=4)
returned_value = utils.report_config(mock_conf)
self.assertEqual(expected_value, returned_value)
@mock.patch('pecan.conf')
def test_report_config_with_log_write(self, mock_conf):
expected_value = pprint.pformat(mock_conf.to_dict(), indent=4)
returned_value = utils.report_config(mock_conf, True)
self.assertEqual(expected_value, returned_value)
@mock.patch('requests.get')
def test_get_resource_status_sanity(self, mock_get):
my_response = mock.MagicMock()
my_response.status_code = 200
my_response.json.return_value = 'test'
mock_get.return_value = my_response
result = utils.get_resource_status('A')
self.assertEqual(result, 'test')
@mock.patch('requests.get', side_effect=ValueError())
def test_get_resource_status_get_failed(self, mock_get):
self.assertIsNone(utils.get_resource_status('A'))
@mock.patch('requests.get')
def test_get_resource_status_invalid_response(self, mock_get):
my_response = mock.MagicMock()
my_response.status_code = 404
mock_get.return_value = my_response
self.assertIsNone(utils.get_resource_status('A'))

View File

@ -1,5 +1,4 @@
import json
from orm.common.orm_common.utils import utils
from wsme.exc import ClientSideError
@ -40,7 +39,7 @@ error_message = {
404: {'message': 'The specific transaction was not found', 'type': 'Not Found'},
405: {'message': 'This method is not allowed', 'type': 'Method Not Allowed'},
409: {'message': 'Current resource is busy', 'type': 'Conflict'},
409.1: {'message': 'Customer UUID already exists', 'type': 'Conflict'},
409.1: {'message': 'UUID already exists', 'type': 'Conflict'},
409.2: {'message': 'Customer name already exists', 'type': 'Conflict'},
500: {'message': 'Server error occurred', 'type': 'Internal Server Error'}
}

View File

@ -1,9 +1,8 @@
import logging
import time
import requests
from pecan import conf
import requests
import string
import time
# from orm_common.logger import get_logger
@ -23,6 +22,28 @@ def _check_conf_initialization():
raise AssertionError('Configurations wasnt initiated, please run set_utils_conf and pass pecan configuration')
def validate_description(data_value):
""" only special characters commas, periods, and dashes allowed in
description field. Return 'False' if other special chars or
escape sequences detected
"""
allowed_punctuations = ['.', '-', ',']
# if type of data_value != 'string' then convert it to string
if not isinstance(data_value, str):
desc = str(data_value)
invalidChars = (string.punctuation).translate(None, ''.join(allowed_punctuations))
# detect any escape sequences or special characters in data string
encoded_string = desc.encode('string_escape')
if any(char in invalidChars for char in encoded_string):
return False
return True
def is_region_group_exist(group_name):
""" function to check whether region group exists
returns 200 for ok and None for error

View File

@ -0,0 +1,9 @@
class Error(Exception):
pass
class ErrorStatus(Error):
def __init__(self, status_code, message=""):
self.message = message

View File

@ -34,44 +34,28 @@ def _check_conf_initialization():
'pass pecan coniguration')
def make_uuid():
""" function to request new uuid from uuid_generator rest service
def create_or_validate_uuid(uuid, uuid_type):
""" function to:
1) request new uuid from uuid_generator rest service
2) validate a uuid if one is being set
returns uuid string
"""
_check_conf_initialization()
url = conf.api.uuid_server.base + conf.api.uuid_server.uuids
try:
if not uuid:
logger.debug('Requesting new UUID from URL: {}'.format(url))
resp = requests.post(url, verify=conf.verify)
except requests.exceptions.ConnectionError as exp:
nagios = 'CON{}UUIDGEN001'.format(conf.server.name.upper())
logger.critical('CRITICAL|{}|Failed in make_uuid: connection error: {}'.format(nagios, str(exp)))
exp.message = 'connection error: Failed to get uuid: unable to connect to server'
raise
except Exception as e:
logger.info('Failed in make_uuid:' + str(e))
return None
resp = resp.json()
return resp['uuid']
def create_existing_uuid(uuid):
""" function to request new uuid from uuid_generator rest service
returns uuid string
:param uuid:
:return:
"""
_check_conf_initialization()
url = conf.api.uuid_server.base + conf.api.uuid_server.uuids
else:
logger.debug('Creating UUID: {}, using URL: {}'.format(uuid, url))
try:
logger.debug('Creating UUID: {}, using URL: {}'.format(uuid, url))
resp = requests.post(url, data={'uuid': uuid}, verify=conf.verify)
resp = requests.post(url, data={'uuid': uuid, 'uuid_type': uuid_type},
verify=conf.verify)
except requests.exceptions.ConnectionError as exp:
nagios = 'CON{}UUIDGEN001'.format(conf.server.name.upper())
logger.critical('CRITICAL|{}|Failed in create_existing_uuid: connection error: {}'.format(nagios, str(exp)))
logger.critical(
'CRITICAL|{}|Failed in make_uuid: connection error: {}'.format(
nagios, str(exp)))
exp.message = 'connection error: Failed to get uuid: unable to connect to server'
raise
except Exception as e:
@ -79,7 +63,9 @@ def create_existing_uuid(uuid):
return None
if resp.status_code == 400:
raise TypeError('duplicate key for uuid')
logger.debug('Duplicate key for uuid: {}'.format(uuid))
raise TypeError('Duplicate key for uuid: ' + str(uuid))
resp = resp.json()
return resp['uuid']
@ -110,6 +96,7 @@ def make_transid():
else:
return None
audit_setup = False

View File

@ -1,49 +1,99 @@
import config as conf
import json
import logging
import os
log = logging.getLogger(__name__)
def _get_regions(customer):
regions = []
try:
customer_json = json.loads(customer)
if 'regions' not in customer_json:
raise Exception("got bad response from orm cli ")
for region in customer_json['regions']:
regions.append(region['name'])
except Exception as exp:
raise Exception("got bad response from orm cli {}".format(exp.message))
message = "got no regions from orm cli"
if regions:
message = "got regions from orm cli --{}--".format(regions)
log.debug(message)
return regions
def _build_get_customer_cli_command(resource_id):
cli_command = """get_customer %s""" % resource_id
log.debug('cli command {}'.format(cli_command))
return cli_command
def _get_customer_regions(cli_command, service):
client_header = service.upper()
log.debug("get customer with cli")
os.chdir(conf.cli_dir)
cwd = os.getcwd()
customer = os.popen('./orm %s %s ' % (service.lower(), cli_command))
log.debug("got cusmer with cli ... check if got regions")
return _get_regions(customer.read())
def get_resource_regions(resource_id, service):
log.debug("---ORM CLI---")
regions = None
if service.upper() == 'CMS':
regions = _get_customer_regions(
_build_get_customer_cli_command(resource_id), service)
return regions
import config as conf
import json
import logging
import os
import subprocess
log = logging.getLogger(__name__)
def _get_cms_regions(customer):
regions = []
try:
customer_json = json.loads(customer)
if 'regions' not in customer_json:
raise Exception("got bad response from orm cli ")
for region in customer_json['regions']:
regions.append(region['name'])
except Exception as exp:
raise Exception("got bad response from orm cli {}".format(exp.message))
message = "got no regions from orm cli"
if regions:
message = "got regions from orm cli --{}--".format(regions)
log.debug(message)
return regions
def _get_flavor_regions(flavor):
regions = []
try:
flavor_json = json.loads(flavor)
if 'regions' not in flavor_json['flavor']:
raise Exception("got bad response from orm cli ")
for region in flavor_json['flavor']['regions']:
regions.append(region['name'])
except Exception as exp:
raise Exception("got bad response from orm cli {}".format(exp.message))
message = "got no regions from orm cli"
if regions:
message = "got regions from orm cli --{}--".format(regions)
log.debug(message)
return regions
def _get_image_regions(image):
regions = []
try:
image_json = json.loads(image)
if 'regions' not in image_json['image']:
raise Exception("got bad response from orm cli ")
for region in image_json['image']['regions']:
regions.append(region['name'])
except Exception as exp:
raise Exception("got bad response from orm cli {}".format(exp.message))
message = "got no regions from orm cli"
if regions:
message = "got regions from orm cli --{}--".format(regions)
log.debug(message)
return regions
def get_resource_regions(resource_id, service):
regions = None
client_header = service.upper()
os.chdir(conf.cli_dir)
cwd = os.getcwd()
log.debug("---ORM CLI---")
if service.upper() == 'CMS':
log.debug("get customer with cli")
cli_command = """get_customer %s""" % resource_id
log.debug('cli command {}'.format(cli_command))
cmd = 'python orm %s %s ' % (service.lower(), cli_command)
customer = subprocess.check_output(cmd.split(), shell=False)
log.debug("got customer with cli ... check if got regions")
return _get_cms_regions(customer)
elif service.upper() == 'FMS':
log.debug("get flavor with cli")
cli_command = """get_flavor %s""" % resource_id
log.debug('cli command {}'.format(cli_command))
cmd = 'python orm %s %s ' % (service.lower(), cli_command)
log.debug("got flavor with cli ... check if got regions")
flavor = subprocess.check_output(cmd.split(), shell=False)
return _get_flavor_regions(flavor)
elif service.upper() == 'IMS':
log.debug("get image with cli")
cli_command = """get_image %s""" % resource_id
log.debug('cli command {}'.format(cli_command))
cmd = 'python orm %s %s ' % (service.lower(), cli_command)
log.debug("got image with cli ... check if got regions")
flavor = subprocess.check_output(cmd.split(), shell=False)
return _get_image_regions(flavor)

View File

@ -1,25 +1,38 @@
"""config module."""
# db configs
sql_user = 'root'
sql_password = 'stack'
sql_server = '127.0.0.1'
sql_port = '3306'
# cms configs
customer_table_name = "customer"
customer_region_table_name = "customer_region"
cms_db_name = "orm_cms_db"
# cli configs
cli_dir = '../ormcli'
# rds configs
rds_db_name = 'orm_rds'
resource_status_table_name = 'resource_status'
# sot configs
local_repository_path = '/opt/app/orm/ORM'
file_name_format = 's_{}.yml'
relative_path_format = '/{}/hot/{}/{}'
"""config module."""
# db configs
sql_user = 'root'
sql_password = 'xxxxxxxxxxx'
sql_server = '127.0.0.1'
sql_port = '3306'
# cms configs
customer_table_name = "customer"
customer_tbl_column = "uuid"
customer_region_table_name = "customer_region"
cms_db_name = "orm_cms_db"
# fms configs
flavor_table_name = "flavor"
flavor_tbl_column = "id"
flavor_region_table_name = "flavor_region"
fms_db_name = "orm_fms_db"
# ims configs
image_table_name = "image"
image_tbl_column = "id"
image_region_table_name = "image_region"
ims_db_name = "orm_ims_db"
# cli configs
cli_dir = '../ormcli'
# rds configs
rds_db_name = 'orm_rds'
resource_status_table_name = 'resource_status'
image_metadata_table_name = 'image_metadata'
# sot configs
local_repository_path = '/opt/app/orm/ORM'
file_name_format = 's_{}.yml'
relative_path_format = '/{}/hot/{}/{}'

View File

@ -1,130 +1,215 @@
import config as conf
import logging
import sqlalchemy
log = logging.getLogger(__name__)
db_engines = {}
def _db_create_engine(db_name):
global db_engines
if db_name not in db_engines:
db_address = 'mysql://{}:{}@{}:{}/{}'.format(conf.sql_user,
conf.sql_password,
conf.sql_server,
conf.sql_port,
db_name)
log.debug("DB:--- db address {}".format(db_address))
db_engines[db_name] = sqlalchemy.create_engine(db_address)
return db_engines
def _run_query(query, db_name):
db_engines = _db_create_engine(db_name)
connection = db_engines[db_name].connect()
try:
sqlres = connection.execute(query)
except Exception as exp:
sqlres = None
log.error("fail to delete resource {}".format(exp))
finally:
# close the connection
connection.close()
# db_engines[db_name].dispose()
return sqlres
def _build_delet_resource_status_query(resource_id, table_name):
query = '''
DELETE from %s
WHERE resource_id = '%s'
''' % (table_name, resource_id)
return query
def _build_delete_resource_query(resource_id, table_name):
query = '''
DELETE from %s
WHERE %s.uuid = '%s'
''' % (table_name, table_name, resource_id)
return query
def _build_get_resource_regions_query(resource_id, table_name):
query = '''
select region_id from %s
WHERE customer_id = '%s' and region_id != '-1'
''' % (table_name, resource_id)
return query
def _build_get_resource_id_query(resource_id, table_name):
query = '''
select * from %s
WHERE %s.uuid = '%s'
''' % (table_name, table_name, resource_id)
return query
def remove_cms_resource(resource_id):
query = _build_delete_resource_query(resource_id, conf.customer_table_name)
log.debug("DB---: deleting customer, query {}".format(query))
_run_query(query, conf.cms_db_name)
return
def remove_rds_resource_status(resource_id):
query = _build_delet_resource_status_query(resource_id,
conf.resource_status_table_name)
log.debug("DB---: deleting resource status, query {}".format(query))
_run_query(query, conf.rds_db_name)
return
def remove_ims_resource(resource_id):
return
def remove_fms_resource(resource_id):
return
def get_cms_db_resource_regions(resource_id):
regions = None
query = _build_get_resource_id_query(resource_id, conf.customer_table_name)
result = _run_query(query, conf.cms_db_name)
if not result.rowcount > 0:
raise Exception('resource {} not found'.format(resource_id))
resource_internal_id = result.first().__getitem__('id')
log.debug("got resource internal id {}".format(resource_internal_id))
# from resource id get regions
query = _build_get_resource_regions_query(resource_internal_id,
conf.customer_region_table_name)
log.debug(query)
result = _run_query(query, conf.cms_db_name)
if result.rowcount > 0:
regions = result.fetchall()
return regions
def get_ims_db_resource_regions(resource_id):
return
def get_fms_db_resource_regions(resource_id):
return
def get_rds_db_resource_status(resource_id):
return
def remove_resource_db(resource_id, service):
if service == 'CMS':
log.debug(
"cleaning {} db for resource {}".format(service, resource_id))
remove_cms_resource(resource_id)
return
import config as conf
import logging
import sqlalchemy
log = logging.getLogger(__name__)
db_engines = {}
def _db_create_engine(db_name):
global db_engines
if db_name not in db_engines:
db_address = 'mysql://{}:{}@{}:{}/{}'.format(conf.sql_user,
conf.sql_password,
conf.sql_server,
conf.sql_port,
db_name)
db_engines[db_name] = sqlalchemy.create_engine(db_address)
return db_engines
def _get_db_info(service):
if service.upper() == 'CMS':
db_name = conf.cms_db_name
table_col = conf.customer_tbl_column
table_name = conf.customer_table_name
region_table_name = conf.customer_region_table_name
elif service.upper() == 'FMS':
db_name = conf.fms_db_name
table_col = conf.flavor_tbl_column
table_name = conf.flavor_table_name
region_table_name = conf.flavor_region_table_name
elif service.upper() == 'IMS':
db_name = conf.ims_db_name
table_col = conf.image_tbl_column
table_name = conf.image_table_name
region_table_name = conf.image_region_table_name
return db_name, table_name, table_col, region_table_name
def _run_query(query, db_name):
db_engines = _db_create_engine(db_name)
connection = db_engines[db_name].connect()
try:
sqlres = connection.execute(query)
except Exception as exp:
sqlres = None
log.error("fail to delete resource {}".format(exp))
finally:
# close the connection
connection.close()
# db_engines[db_name].dispose()
return sqlres
def _build_delet_resource_status_query(resource_id, table_name):
query = '''
DELETE from %s
WHERE resource_id = '%s'
''' % (table_name, resource_id)
return query
def _build_delete_image_metadata(resource_id, image_metadata_table,
resource_table):
query = '''
DELETE from %s
WHERE image_meta_data_id in
(SELECT id from %s where resource_id = '%s')
''' % (image_metadata_table, resource_table, resource_id)
return query
def _build_delete_resource_query(resource_id, table_col, table_name):
query = '''
DELETE from %s
WHERE %s.%s = '%s'
''' % (table_name, table_name, table_col, resource_id)
return query
def _build_get_cms_regions_query(resource_id, table_name):
query = '''
select region_id from %s
WHERE customer_id = '%s' and region_id != '-1'
''' % (table_name, resource_id)
return query
def _build_get_fms_regions_query(resource_id, table_name):
query = '''
select region_name from %s
WHERE flavor_internal_id = '%s'
''' % (table_name, resource_id)
return query
def _build_get_ims_regions_query(resource_id, table_name):
query = '''
select region_name from %s
WHERE image_id = '%s'
''' % (table_name, resource_id)
return query
def _build_get_resource_id_query(resource_id, table_col, table_name):
query = '''
select * from %s
WHERE %s.%s = '%s'
''' % (table_name, table_name, table_col, resource_id)
return query
def remove_resource_id(resource_id, service):
db_name, table_name, table_col, region_table_name = _get_db_info(service)
resource_type = table_name
query = _build_delete_resource_query(resource_id, table_col, table_name)
log.debug("DB---: deleting {}, query {}".format(resource_type, query))
_run_query(query, db_name)
return
def remove_rds_resource_status(resource_id):
query = _build_delet_resource_status_query(resource_id,
conf.resource_status_table_name)
log.debug("DB---: deleting resource status, query {}".format(query))
_run_query(query, conf.rds_db_name)
return
def remove_rds_image_metadata(resource_id):
query = _build_delete_image_metadata(resource_id,
conf.image_metadata_table_name,
conf.resource_status_table_name)
log.debug("DB---: deleting image_metadata, query {}".format(query))
_run_query(query, conf.rds_db_name)
return
def get_cms_db_resource_regions(resource_id, service):
regions = None
db_name, table_name, table_col, region_table_name = _get_db_info(service)
query = _build_get_resource_id_query(resource_id, table_col, table_name)
result = _run_query(query, db_name)
if not result.rowcount > 0:
raise Exception('resource {} not found'.format(resource_id))
resource_internal_id = result.first().__getitem__('id')
log.debug("got resource internal id {}".format(resource_internal_id))
# from resource id get regions
query = _build_get_cms_regions_query(resource_internal_id,
region_table_name)
log.debug(query)
result = _run_query(query, db_name)
if result.rowcount > 0:
regions = result.fetchall()
return regions
def get_fms_db_resource_regions(resource_id, service):
regions = None
db_name, table_name, table_col, region_table_name = _get_db_info(service)
query = _build_get_resource_id_query(resource_id, table_col,
conf.flavor_table_name)
result = _run_query(query, db_name)
if not result.rowcount > 0:
raise Exception('resource {} not found'.format(resource_id))
resource_internal_id = result.first().__getitem__('internal_id')
log.debug("got resource internal id {}".format(resource_internal_id))
# from resource id get regions
query = _build_get_fms_regions_query(resource_internal_id,
region_table_name)
log.debug(query)
result = _run_query(query, db_name)
if result.rowcount > 0:
regions = result.fetchall()
return regions
def get_ims_db_resource_regions(resource_id, service):
regions = None
db_name, table_name, table_col, region_table_name = _get_db_info(service)
query = _build_get_resource_id_query(resource_id, table_col, table_name)
result = _run_query(query, db_name)
if not result.rowcount > 0:
raise Exception('resource {} not found'.format(resource_id))
resource_internal_id = result.first().__getitem__('id')
log.debug("got resource internal id {}".format(resource_internal_id))
# from resource id get regions
query = _build_get_ims_regions_query(resource_internal_id,
region_table_name)
log.debug(query)
result = _run_query(query, db_name)
if result.rowcount > 0:
regions = result.fetchall()
return regions
def get_rds_db_resource_status(resource_id):
return
def remove_resource_db(resource_id, service):
log.debug(
"cleaning {} db for resource {}".format(service, resource_id))
remove_resource_id(resource_id, service)
return

View File

@ -0,0 +1,111 @@
import cli_comander as cli
import db_comander as db
import initializer
import logging
import sys
import utils
import yaml_handler as yh
log = logging.getLogger(__name__)
def _validate_service(service):
allowed_services = ['CMS', 'FMS', 'IMS']
if service.upper() not in allowed_services:
raise Exception("service should be one of {}".format(allowed_services))
return service.upper()
def _init():
initializer.init_log()
return
def read_csv_file(file):
log.debug("reading file {}".format(file))
return utils.read_csv_file(file)
def resource_db_clean(resource_id, service):
log.debug("cleaning {} db for resource {}".format(service, resource_id))
db.remove_resource_db(resource_id, service)
return
def check_yaml_file(resource_id):
log.debug('checking yml file if exist for resource {}'.format(resource_id))
files = yh.check_yaml_exist(resource_id)
message = 'no yaml files found for this resource'
if files:
message = "found files please remove manualy {}".format(files)
log.debug(message)
return
def get_resource_regions(resource_id, service_name):
if service_name.upper() == 'CMS':
db_regions = db.get_cms_db_resource_regions(resource_id, service_name)
elif service_name.upper() == 'FMS':
db_regions = db.get_fms_db_resource_regions(resource_id, service_name)
elif service_name.upper() == 'IMS':
db_regions = db.get_ims_db_resource_regions(resource_id, service_name)
# db_regions = db.get_resource_regions(resource_id, service_name)
orm_regions = cli.get_resource_regions(resource_id, service_name)
return orm_regions, db_regions
def clean_rds_resource_status(resource_id):
log.debug("clean rds status db for resource {}".format(resource_id))
db.remove_rds_resource_status(resource_id)
return
def _start_cleaning():
log.info('start cleaning')
file_path = sys.argv[1]
service = _validate_service(sys.argv[2])
resourses_to_clean = read_csv_file(file_path)
for resource_id in resourses_to_clean:
try:
log.debug(
'check if resource {} has any regions before clean'.format(
resource_id))
resource_regions, db_regions = get_resource_regions(resource_id,
service)
if resource_regions or db_regions:
log.error(
"got regions {} {} please clean regions from orm before"
" removing the resource {}".format(resource_regions,
db_regions,
resource_id))
raise Exception(
"got regions {} {} please clean regions from orm before"
" removing the resource {}".format(resource_regions,
db_regions,
resource_id))
log.debug('cleaning {}'.format(resource_id))
resource_db_clean(resource_id, service)
check_yaml_file(resource_id)
clean_rds_resource_status(resource_id)
if service.upper() == "IMS":
db.remove_rds_image_metadata(resource_id)
except Exception as exp:
log.error("---------------{}---------------".format(exp.message))
if 'not found' not in exp.message:
log.exception(exp)
continue
return
if __name__ == '__main__':
warning_message = raw_input(
'IMPORTANT:- please note its your responsibility to backup the db'
' before running this script... click enter before continue'
)
_init()
_start_cleaning()

View File

@ -1,25 +1,25 @@
import config as conf
import fnmatch
import os
def _get_resource_file_path():
file_path = conf.local_repository_path
return file_path
def _find_file(resource_id):
file_name = conf.file_name_format.format(resource_id)
folder_to_search = _get_resource_file_path(resource_id)
matches = []
for root, dirnames, filenames in os.walk(folder_to_search):
for filename in fnmatch.filter(filenames, file_name):
matches.append(os.path.join(root, filename))
return matches
def check_yaml_exist(resource_id):
files = _find_file(resource_id)
if files:
return files
return None
import config as conf
import fnmatch
import os
def _get_resource_file_path():
file_path = conf.local_repository_path
return file_path
def _find_file(resource_id):
file_name = conf.file_name_format.format(resource_id)
folder_to_search = _get_resource_file_path()
matches = []
for root, dirnames, filenames in os.walk(folder_to_search):
for filename in fnmatch.filter(filenames, file_name):
matches.append(os.path.join(root, filename))
return matches
def check_yaml_exist(resource_id):
files = _find_file(resource_id)
if files:
return files
return None

View File

@ -18,24 +18,22 @@ You should normally create the list of flavors once.
Then when you want to add regions to all the flavors, use:
7. ./regionator.py --regions region1,region2
7. ./regionator.py region1,region2 series1,series2
The argument is a comma-separated list of regions with no internal whitespace.
The argument is a comma-separated list of regions and series
with no internal whitespace.
Use of -h will produce the following help:
./regionator.py -h
usage: regionator [-h] [--flavor_dir FLAVOR_DIR] [--host HOST]
[--cli_command CLI_COMMAND] [--regions REGIONS]
usage: regionator [-h] regions [series]
batch add region to flavor
positional arguments:
regions <comma-separated regions to add, e.g. region1,region2>
series <comma-separated flavor series to add, e.g. nd,gv>
optional arguments:
-h, --help show this help message and exit
--flavor_dir FLAVOR_DIR
<JSON flavor directory, default: ./flavor_dir>
--host HOST <orm host ip>
--cli_command CLI_COMMAND
<path to cli command>
--regions REGIONS <comma-separated regions to add, e.g. region1,region2>
-h, --help show this help message and exit

View File

@ -29,7 +29,7 @@ def sh(harg, file_name):
print '>> Starting: ' + cmd
start = time.time()
output = ''
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
p = subprocess.Popen(cmd.split(), shell=False, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
out = line.rstrip()

View File

@ -30,7 +30,7 @@ def get_region_list(regions):
REGION_NAME = region
res, output = sh('get_region')
if not res:
result_region = ast.literal_eval(output)
result_region = json.loads(output)
result.append({'name': result_region['name'],
'designType': result_region['designType']})
else:
@ -44,9 +44,9 @@ def create_command(cli_command):
if cli_command == 'add_region':
cmd = 'python %s fms add_region %s %s' % (CLI_PATH, FID, FILE_NAME,)
elif cli_command == 'get_flavor':
cmd = '%s fms get_flavor test %s' % (CLI_PATH, FLAVOR_NAME,)
cmd = 'python %s fms get_flavor test %s' % (CLI_PATH, FLAVOR_NAME,)
elif cli_command == 'get_region':
cmd = '%s rms get_region %s' % (CLI_PATH, REGION_NAME,)
cmd = 'python %s rms get_region %s' % (CLI_PATH, REGION_NAME,)
else:
raise ValueError('Received an unknown command: %s' % (cli_command,))
@ -79,7 +79,7 @@ def sh(cli_command):
start = time.time()
output = ''
errpat = re.compile('error', re.I)
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
p = subprocess.Popen(cmd.split(), shell=False, stdout=subprocess.PIPE)
for line in iter(p.stdout.readline, b''):
out = line.rstrip()
print(">>> " + out)

View File

@ -1,8 +1,8 @@
#!/usr/bin/env python
from os.path import isfile, join
import argparse
import json
import os
from os.path import isfile, join
import re
import subprocess
import tempfile
@ -29,7 +29,9 @@ def sh(cmd):
start = time.time()
output = ''
errpat = re.compile('error', re.I)
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
cmd = 'python ' + cmd
p = subprocess.Popen(cmd.split(), shell=False, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
out = line.rstrip()

View File

@ -1,9 +1,9 @@
#!/usr/bin/env python
from os.path import isfile, join
import argparse
import ast
import json
import os
from os.path import isfile, join
import re
import subprocess
import tempfile
@ -29,7 +29,7 @@ def sh(cmd):
start = time.time()
output = ''
errpat = re.compile('error', re.I)
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
p = subprocess.Popen(cmd.split(), shell=False, stdout=subprocess.PIPE)
for line in iter(p.stdout.readline, b''):
out = line.rstrip()
print(">>> " + out)
@ -74,7 +74,7 @@ os.close(fh)
img_dict = {}
# harg = '--orm-base-url %s' % args.host if args.host else ''
res, output = sh(
'%s ims %s list_images test ' % (CLI_PATH, ''))
'python %s ims %s list_images test ' % (CLI_PATH, ''))
if not res:
images = ast.literal_eval(output)
for img in images['images']:
@ -90,9 +90,10 @@ if not res:
if image_name in img_dict:
image_id = img_dict[image_name]
print 'image_id: ' + image_id
res, output = sh('%s ims add_regions test %s %s' % (
res, output = sh('python %s ims add_regions test %s %s' % (
CLI_PATH, image_id, file_name))
else:
print 'image_name: {} does not exist. ignore.'.format(image_name)
print 'python image_name: {} does not exist. ' \
'ignore.'.format(image_name)
os.unlink(file_name)

View File

@ -2,7 +2,6 @@
import argparse
import cli_common
import config
import orm.base_config as base_config
import os
import requests
@ -44,7 +43,7 @@ def add_to_parser(service_sub):
parser.add_argument('-v', '--verbose', help='show details',
action="store_true")
parser.add_argument('-f', '--faceless',
help='run without authentication',
help=argparse.SUPPRESS,
default=False,
action="store_true")
subparsers = parser.add_subparsers(dest='subcmd',
@ -112,11 +111,16 @@ def add_to_parser(service_sub):
parser_delete_region = subparsers.add_parser('delete_region',
help='[<"X-RANGER-Client" '
'header>] <customer id> '
'header>] '
'[--force_delete] '
'<customer id> '
'<region id>')
parser_delete_region.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_delete_region.add_argument('custid', type=str, help='<customer id>')
parser_delete_region.add_argument('regionid', type=str, help='<region id>')
parser_delete_region.add_argument('--force_delete',
help='force delete region',
action="store_true")
# add user
parser_add_user = subparsers.add_parser('add_user',
@ -216,11 +220,8 @@ def add_to_parser(service_sub):
help='<user id>')
# add metadata
h1, h2, h3 = \
'[<"X-RANGER-Client" header>]', '<customer id>', '<data file ' \
'with ' \
'metadata(' \
's) JSON>'
h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '<customer id>',
'<data file with metadata(s) JSON>')
parser_add_metadata = subparsers.add_parser('add_metadata',
help='%s %s %s' % (h1, h2, h3))
parser_add_metadata.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
@ -230,11 +231,8 @@ def add_to_parser(service_sub):
help=h3)
# replace metadata
h1, h2, h3 = \
'[<"X-RANGER-Client" header>]', '<customer id>', '<data file ' \
'with ' \
'metadata(' \
's) JSON>'
h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '<customer id>',
'<data file with metadata(s) JSON>')
parser_replace_metadata = subparsers.add_parser('replace_metadata',
help='%s %s %s' % (
h1, h2, h3))
@ -247,16 +245,16 @@ def add_to_parser(service_sub):
help=h3)
# get customer
h1, h2 = '[<"X-RANGER-Client" header>]', '<customer id or customer name>'
parser_get_customer = subparsers.add_parser('get_customer',
help='[<"X-RANGER-Client" '
'header>] <customer id>')
help='%s %s' % (h1, h2))
parser_get_customer.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_get_customer.add_argument('custid', type=str, help='<customer id>')
parser_get_customer.add_argument('custid', type=str, help=h2)
# list customers
h1 = '[<"X-RANGER-Client" header>]'
h2 = '[--region <name>] [--user <name>] [--metadata <key:value>]' \
' [starts_with <name>] [contains <name>]'
' [--starts_with <name>] [--contains <name>]'
parser_list_customer = subparsers.add_parser('list_customers',
help='%s %s' % (h1, h2))
parser_list_customer.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
@ -288,7 +286,9 @@ def cmd_details(args):
elif args.subcmd == 'replace_region':
return requests.put, '/%s/regions' % args.custid
elif args.subcmd == 'delete_region':
return requests.delete, '/%s/regions/%s' % (args.custid, args.regionid)
return requests.delete, '/%s/regions/%s/%s' % (args.custid,
args.regionid,
args.force_delete)
elif args.subcmd == 'add_user':
return requests.post, '/%s/regions/%s/users' % (
args.custid, args.regionid)
@ -353,12 +353,12 @@ def get_token(timeout, args, host):
globals()[argument] = configuration_value
else:
message = ('ERROR: {} for token generation was not supplied. '
'Please use its command-line '
'argument or environment variable.'.format(argument))
'Please use its command-line argument or '
'environment variable.'.format(argument))
print message
raise cli_common.MissingArgumentError(message)
keystone_ep = cli_common.get_keystone_ep('{}:{}'.format(host, base_config.rms['port']),
keystone_ep = cli_common.get_keystone_ep('{}:8080'.format(host),
auth_region)
if keystone_ep is None:
raise ConnectionError(
@ -386,7 +386,7 @@ def get_token(timeout, args, host):
def get_environment_variable(argument):
# The rules are: all caps, underscores instead of dashes and prefixed
environment_variable = 'RANGER_{}'.format(
environment_variable = 'AIC_ORM_{}'.format(
argument.replace('-', '_').upper())
return os.environ.get(environment_variable)
@ -394,7 +394,7 @@ def get_environment_variable(argument):
def run(args):
host = args.orm_base_url if args.orm_base_url else config.orm_base_url
port = args.port if args.port else base_config.cms['port']
port = args.port if args.port else 7080
data = args.datafile.read() if 'datafile' in args else '{}'
timeout = args.timeout if args.timeout else 10
@ -429,7 +429,7 @@ def run(args):
try:
resp = rest_cmd(url, timeout=timeout, data=data, headers=headers,
verify=False)
verify=config.verify)
except Exception as e:
print e
exit(1)

View File

@ -2,7 +2,6 @@
import argparse
import cli_common
import config
import orm.base_config as base_config
import os
import requests
@ -42,7 +41,7 @@ def add_to_parser(service_sub):
parser.add_argument('-v', '--verbose', help='show details',
action="store_true")
parser.add_argument('-f', '--faceless',
help='run without authentication',
help=argparse.SUPPRESS,
default=False,
action="store_true")
subparsers = parser.add_subparsers(dest='subcmd',
@ -126,7 +125,7 @@ def add_to_parser(service_sub):
h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '<flavor id>',
'<extra_spec key name>',)
parser_delete_extra_spec = subparsers.add_parser('delete_extra_spec',
help='%s%s%s' % (
help='%s %s %s' % (
h1, h2, h3))
parser_delete_extra_spec.add_argument('client',
**cli_common.ORM_CLIENT_KWARGS)
@ -136,7 +135,7 @@ def add_to_parser(service_sub):
h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '<flavor id>',
'<datafile with extra_specs json>',)
parser_add_extra_specs = subparsers.add_parser('add_extra_specs',
help='%s%s%s' % (
help='%s %s %s' % (
h1, h2, h3))
parser_add_extra_specs.add_argument('client',
**cli_common.ORM_CLIENT_KWARGS)
@ -151,7 +150,7 @@ def add_to_parser(service_sub):
parser_delete_flavor.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_delete_flavor.add_argument('flavorid', type=str, help=h2)
h1, h2 = '[<"X-RANGER-Client" header>]', '<flavor id or flavor_name>'
h1, h2 = '[<"X-RANGER-Client" header>]', '<flavor id or flavor name>'
parser_get_flavor = subparsers.add_parser('get_flavor',
help='%s %s' % (h1, h2))
parser_get_flavor.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
@ -159,7 +158,8 @@ def add_to_parser(service_sub):
h1, h2 = ('[<"X-RANGER-Client" header>]',
'[--visibility <public|private>] [--region <name>] [--tenant '
'<id>] [--series {gv,nv,ns,nd,ss}] [--alias <alias>]')
'<id>] [--series {gv,nv,ns,nd,ss}] [--alias <alias>] '
'[--vm_type <vm_type>] [--vnf_name <vnf_name>]')
parser_list_flavor = subparsers.add_parser('list_flavors',
help='%s %s' % (h1, h2))
parser_list_flavor.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
@ -174,6 +174,8 @@ def add_to_parser(service_sub):
parser_list_flavor.add_argument('--series', type=str,
choices=['gv', 'nv', 'ns', 'nd', 'ss'])
parser_list_flavor.add_argument('--alias', type=str, help='flavor alias')
parser_list_flavor.add_argument('--vm_type', type=str, help='vm type')
parser_list_flavor.add_argument('--vnf_name', type=str, help='vnf name')
# region for flavor
h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '<flavor id>',
@ -185,13 +187,17 @@ def add_to_parser(service_sub):
parser_add_region.add_argument('datafile', type=argparse.FileType('r'),
help=h3)
h1, h2, h3 = '[<"X-RANGER-Client" header>]', '<flavor id>', '<region id>'
h1, h2, h3 = '[<"X-RANGER-Client" header>] [--force_delete]', \
'<flavor id>', '<region id>'
parser_delete_region = subparsers.add_parser('delete_region',
help='%s %s %s' % (
h1, h2, h3))
parser_delete_region.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_delete_region.add_argument('flavorid', type=str, help=h2)
parser_delete_region.add_argument('regionid', type=str, help=h3)
parser_delete_region.add_argument('--force_delete',
help='force delete region',
action="store_true")
# tenant for flavor
h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '<flavor id>',
@ -236,8 +242,8 @@ def cmd_details(args):
elif args.subcmd == 'get_tags':
return requests.get, '/%s/tags' % args.flavorid
elif args.subcmd == 'delete_region':
return requests.delete, '/%s/regions/%s' % (
args.flavorid, args.regionid)
return requests.delete, '/%s/regions/%s/%s' % (
args.flavorid, args.regionid, args.force_delete)
elif args.subcmd == 'add_tenant':
return requests.post, '/%s/tenants' % args.flavorid
elif args.subcmd == 'delete_tenant':
@ -266,6 +272,10 @@ def cmd_details(args):
param += '%stenant=%s' % (preparm(param), args.tenant)
if args.series:
param += '%sseries=%s' % (preparm(param), args.series)
if args.vm_type:
param += '%svm_type=%s' % (preparm(param), args.vm_type)
if args.vnf_name:
param += '%svnf_name=%s' % (preparm(param), args.vnf_name)
if args.starts_with:
param += '%sstarts_with=%s' % (preparm(param), args.starts_with)
if args.contains:
@ -300,12 +310,12 @@ def get_token(timeout, args, host):
globals()[argument] = configuration_value
else:
message = ('ERROR: {} for token generation was not supplied. '
'Please use its command-line '
'argument or environment variable.'.format(argument))
'Please use its command-line argument or '
'environment variable.'.format(argument))
print message
raise cli_common.MissingArgumentError(message)
keystone_ep = cli_common.get_keystone_ep('{}:{}'.format(host, base_config.rms['port']),
keystone_ep = cli_common.get_keystone_ep('{}:8080'.format(host),
auth_region)
if keystone_ep is None:
raise ConnectionError(
@ -333,7 +343,7 @@ def get_token(timeout, args, host):
def get_environment_variable(argument):
# The rules are: all caps, underscores instead of dashes and prefixed
environment_variable = 'RANGER_{}'.format(
environment_variable = 'AIC_ORM_{}'.format(
argument.replace('-', '_').upper())
return os.environ.get(environment_variable)
@ -341,7 +351,7 @@ def get_environment_variable(argument):
def run(args):
host = args.orm_base_url if args.orm_base_url else config.orm_base_url
port = args.port if args.port else base_config.fms['port']
port = args.port if args.port else 8082
data = args.datafile.read() if 'datafile' in args else '{}'
timeout = args.timeout if args.timeout else 10
@ -375,7 +385,7 @@ def run(args):
timeout, data, headers, rest_cmd.__name__, url))
try:
resp = rest_cmd(url, timeout=timeout, data=data, headers=headers,
verify=False)
verify=config.verify)
except Exception as e:
print e
exit(1)

View File

@ -1,11 +1,11 @@
#!/usr/bin/python
import argparse
import cli_common
import config
import orm.base_config as base_config
import os
import requests
from orm.orm_client.ormcli import cli_common
class ResponseError(Exception):
pass
@ -42,7 +42,7 @@ def add_to_parser(service_sub):
parser.add_argument('-v', '--verbose', help='show details',
action="store_true")
parser.add_argument('-f', '--faceless',
help='run without authentication',
help=argparse.SUPPRESS,
default=False,
action="store_true")
subparsers = parser.add_subparsers(dest='subcmd',
@ -74,7 +74,7 @@ def add_to_parser(service_sub):
parser_delete_image.add_argument('imageid', type=str, help=h2)
# get images
h1, h2 = '[<"X-RANGER-Client" header>]', '<image id>'
h1, h2 = '[<"X-RANGER-Client" header>]', '<image id or image name>'
parser_get_image = subparsers.add_parser('get_image',
help='%s %s' % (h1, h2))
parser_get_image.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
@ -92,17 +92,15 @@ def add_to_parser(service_sub):
parser_list_images.add_argument('--customer', type=str, help='customer id')
# activate/deactivate image
h1, h2 = '[<"X-RANGER-Client" header>]', '<image id>'
parser_enable = subparsers.add_parser('enable',
help='%s %s' % (h1, h2))
parser_enable.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_enable.add_argument('imageid', type=str, help=h2)
parser_disable = subparsers.add_parser('disable',
help='%s %s' % (h1, h2))
parser_disable.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_disable.add_argument('imageid', type=str, help=h2)
h1, h2, h3 = '[<"X-RANGER-Client" header>]', '<image id>', \
'<data file with true/false JSON>'
parser_enable_image = subparsers.add_parser('enabled',
help='%s %s %s' % (h1, h2, h3))
parser_enable_image.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_enable_image.add_argument('imageid', type=str, help=h2)
parser_enable_image.add_argument('datafile',
type=argparse.FileType('r'),
help=h3)
# region for image
h1, h2, h3 = '[<"X-RANGER-Client" header>]', '<image id>', \
@ -128,7 +126,8 @@ def add_to_parser(service_sub):
type=argparse.FileType('r'),
help=h3)
h1, h2, h3 = '[<"X-RANGER-Client" header>]', '<image id>', '<region id>'
h1, h2, h3 = '[<"X-RANGER-Client" header>] [--force_delete]', \
'<image id>', '<region id>'
parser_delete_region = subparsers.add_parser('delete_region',
help='%s %s %s' % (h1,
h2,
@ -136,6 +135,9 @@ def add_to_parser(service_sub):
parser_delete_region.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_delete_region.add_argument('imageid', type=str, help=h2)
parser_delete_region.add_argument('regionid', type=str, help=h3)
parser_delete_region.add_argument('--force_delete',
help='force delete region',
action="store_true")
# customer for image
h1, h2, h3 = '[<"X-RANGER-Client" header>]', '<image id>', \
@ -200,12 +202,12 @@ def get_token(timeout, args, host):
globals()[argument] = configuration_value
else:
message = ('ERROR: {} for token generation was not supplied. '
'Please use its command-line '
'argument or environment variable.'.format(argument))
'Please use its command-line argument or '
'environment variable.'.format(argument))
print message
raise cli_common.MissingArgumentError(message)
keystone_ep = cli_common.get_keystone_ep('{}:{}'.format(host, base_config.rms['port']),
keystone_ep = cli_common.get_keystone_ep('{}:8080'.format(host),
auth_region)
if keystone_ep is None:
raise ConnectionError(
@ -236,40 +238,40 @@ def preparm(p):
def cmd_details(args):
data = args.datafile.read() if 'datafile' in args else '{}'
if args.subcmd == 'create_image':
cmd, url = requests.post, ''
return requests.post, ''
elif args.subcmd == 'update_image':
cmd, url = requests.put, '/%s' % args.imageid
return requests.put, '/%s' % args.imageid
elif args.subcmd == 'delete_image':
cmd, url = requests.delete, '/%s' % args.imageid
return requests.delete, '/%s' % args.imageid
# activate/deactivate image
elif args.subcmd in ('enable', 'disable'):
cmd, url = requests.put, '/%s/enabled' % args.imageid
data = '{"enabled": %s}' % ('true' if args.subcmd == 'enable' else
'false')
elif args.subcmd == 'enabled':
return requests.put, '/%s/enabled' % args.imageid
# image regions
elif args.subcmd == 'add_regions':
cmd, url = requests.post, '/%s/regions' % args.imageid
return requests.post, '/%s/regions' % args.imageid
elif args.subcmd == 'update_regions':
cmd, url = requests.put, '/%s/regions' % args.imageid
return requests.put, '/%s/regions' % args.imageid
elif args.subcmd == 'delete_region':
cmd, url = requests.delete, '/%s/regions/%s' % (args.imageid,
args.regionid)
return requests.delete, '/%s/regions/%s/%s' % (args.imageid,
args.regionid,
args.force_delete)
# image customers
elif args.subcmd == 'add_customers':
cmd, url = requests.post, '/%s/customers' % args.imageid
return requests.post, '/%s/customers' % args.imageid
elif args.subcmd == 'update_customers':
cmd, url = requests.put, '/%s/customers' % args.imageid
return requests.put, '/%s/customers' % args.imageid
elif args.subcmd == 'delete_customer':
cmd, url = requests.delete, '/%s/customers/%s' % (args.imageid,
args.customerid)
return requests.delete, '/%s/customers/%s' % (args.imageid,
args.customer)
# list images
elif args.subcmd == 'get_image':
cmd, url = requests.get, '/%s' % args.imageid
return requests.get, '/%s' % args.imageid
elif args.subcmd == 'list_images':
param = ''
if args.visibility:
@ -281,26 +283,22 @@ def cmd_details(args):
if args.customer:
param += '%scustomer=%s' % (preparm(param),
args.customer)
cmd, url = requests.get, '/%s' % param
return cmd, url, data
return requests.get, '/%s' % param
def cmd_data(args):
# This is a special case where api has a payload needed but the CLI is
# seperated into 2 different commands. In this case we need to set the
# payload.
if args.subcmd == 'enable':
if args.subcmd == 'enabled':
return "{\n \"enabled\": true\n}"
elif args.subcmd == 'disable':
return "{\n \"enabled\": false\n}"
else:
return args.datafile.read() if 'datafile' in args else '{}'
def get_environment_variable(argument):
# The rules are: all caps, underscores instead of dashes and prefixed
environment_variable = 'RANGER_{}'.format(
environment_variable = 'AIC_ORM_{}'.format(
argument.replace('-', '_').upper())
return os.environ.get(environment_variable)
@ -308,10 +306,11 @@ def get_environment_variable(argument):
def run(args):
host = args.orm_base_url if args.orm_base_url else config.orm_base_url
port = args.port if args.port else base_config.ims['port']
port = args.port if args.port else 8084
data = args.datafile.read() if 'datafile' in args else '{}'
timeout = args.timeout if args.timeout else 10
rest_cmd, cmd_url, data = cmd_details(args)
rest_cmd, cmd_url = cmd_details(args)
url = '%s:%d/v1/orm/images' % (host, port,) + cmd_url
if args.faceless:
auth_token = auth_region = requester = client = ''
@ -343,7 +342,7 @@ def run(args):
url))
try:
resp = rest_cmd(url, timeout=timeout, data=data, headers=headers,
verify=False)
verify=config.verify)
except Exception as e:
print e
exit(1)

View File

@ -1,9 +1,9 @@
#!/usr/bin/python
import argparse
import cmscli
import fmscli
import imscli
import rmscli
from orm.orm_client.ormcli import cmscli
from orm.orm_client.ormcli import fmscli
from orm.orm_client.ormcli import imscli
from orm.orm_client.ormcli import rmscli
import sys

View File

@ -2,7 +2,6 @@
import argparse
import cli_common
import config
import orm.base_config as base_config
import os
import requests
@ -35,50 +34,61 @@ def add_to_parser(service_sub):
parser.add_argument('--orm-base-url', type=str, help='ORM base URL',
default=get_environment_variable('orm-base-url'))
parser.add_argument('--tracking_id', type=str, help='tracking id')
parser.add_argument('--port', type=int, help='port number of IMS server')
parser.add_argument('--port', type=int, help='port number of RMS server')
parser.add_argument('--timeout', type=int,
help='request timeout in seconds (default: 10)')
parser.add_argument('-v', '--verbose', help='show details',
action="store_true")
parser.add_argument('-f', '--faceless',
help='run without authentication',
help=argparse.SUPPRESS,
default=False,
action="store_true")
subparsers = parser.add_subparsers(dest='subcmd',
metavar='<subcommand> [-h] <args>')
clnt_hdr = '[<"X-RANGER-Client" header>] '
# get group
h1 = '<group_id>'
parser_get_group = subparsers.add_parser('get_group', help=h1)
parser_get_group.add_argument('group_id', help=h1)
parser_get_group.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_get_group.add_argument('group_id', type=str, help=h1)
# get all groups
parser_list_groups = subparsers.add_parser('list_groups', help="")
parser_list_groups.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
# create group
h1 = '<group json file>'
parser_create_group = subparsers.add_parser('create_group', help=h1)
h1 = '<data file group json file>'
parser_create_group = subparsers.add_parser('create_group',
help='%s %s' % (clnt_hdr, h1))
parser_create_group.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_create_group.add_argument('datafile', type=argparse.FileType('r'),
help=h1)
help='<data file with new group JSON>')
# update group
h1, h2 = '<group json file>', '<group_id>'
h1, h2 = '<group_id>', '<group json file>'
parser_update_group = subparsers.add_parser('update_group',
help="%s %s" % (h2, h1))
help="%s %s %s" % (clnt_hdr,
h1, h2))
parser_update_group.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_update_group.add_argument('group_id', help=h2)
parser_update_group.add_argument('datafile', type=argparse.FileType('r'),
help=h1)
help='<data file with updated group '
'JSON>')
# delete group
h1 = '<group id>'
parser_delete_group = subparsers.add_parser('delete_group',
help='%s' % (h1))
help='%s %s' % (clnt_hdr, h1))
parser_delete_group.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_delete_group.add_argument('group_id', type=str, help=h1)
# get region
h1, h2 = '<region_name_or_id>', '[--use_version <api version>]'
parser_get_region = subparsers.add_parser('get_region',
help='%s %s' % (h1, h2))
parser_get_region.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_get_region.add_argument('--use_version', type=int,
help='<api version to use (1 or 2)>')
parser_get_region.add_argument('region_name_or_id', type=str, help=h1)
@ -86,32 +96,39 @@ def add_to_parser(service_sub):
# update region
h1, h2 = '<region_id>', '<full region json file>'
parser_update_region = subparsers.add_parser('update_region',
help='%s %s' % (h1, h2))
help='%s %s %s' % (clnt_hdr,
h1, h2))
parser_update_region.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_update_region.add_argument('region_id', type=str, help=h1)
parser_update_region.add_argument('datafile', type=argparse.FileType('r'),
help=h2)
help='<data file with updated region '
'JSON>')
# create region
h1 = '<full region json file>'
parser_create_region = subparsers.add_parser('create_region',
help='%s' % (h1))
help='%s %s' % (clnt_hdr, h1))
parser_create_region.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_create_region.add_argument('datafile', type=argparse.FileType('r'),
help=h2)
help='<data file with new region JSON>')
# delete region
h1 = '<region id>'
parser_delete_region = subparsers.add_parser('delete_region',
help='%s' % (h1))
help='%s %s' % (clnt_hdr, h1))
parser_delete_region.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_delete_region.add_argument('region_id', type=str, help=h1)
# list regions
parser_list_region = subparsers.add_parser('list_regions',
help='\
[--use_version <api version>] [--type <type>] [--status <status>]\
[--use_version <api version>] [--type <type>][--status <status>]\
[--metadata <metadata>] [--aicversion <aicversion>][--clli <clli>]\
[--regionname <regionname>] [--osversion <osversion>] [--valet <valet>]\
[--regionname <regionname>] [--osversion <osversion>]\
[--location_type <location_type>]\
[--state <state>] [--country <country>] [--city <city>] [--street <street>]\
[--zip <zip>] [--vlcp_name <vlcp_name>]')
parser_list_region.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_list_region.add_argument('--use_version', type=int,
help='<api version to use>')
parser_list_region.add_argument('--type', type=str, help='<type>')
@ -125,7 +142,8 @@ def add_to_parser(service_sub):
help='<regionname>')
parser_list_region.add_argument('--osversion', type=str,
help='<osversion>')
parser_list_region.add_argument('--valet', type=str, help='<valet>')
parser_list_region.add_argument('--location_type', type=str,
help='<location_type>')
parser_list_region.add_argument('--state', type=str, help='<state>')
parser_list_region.add_argument('--country', type=str, help='<country>')
parser_list_region.add_argument('--city', type=str, help='<city>')
@ -137,7 +155,9 @@ def add_to_parser(service_sub):
# add metadata to region
h1, h2 = '<region_id>', '<metadata json file>'
parser_add_metadata = subparsers.add_parser('add_metadata',
help='%s %s' % (h1, h2))
help='%s %s %s' % (clnt_hdr,
h1, h2))
parser_add_metadata.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_add_metadata.add_argument('region_id', type=str, help=h1)
parser_add_metadata.add_argument('datafile', type=argparse.FileType('r'),
help=h2)
@ -145,7 +165,10 @@ def add_to_parser(service_sub):
# update region's metadata
h1, h2 = '<region_id>', '<metadata json file>'
parser_update_metadata = subparsers.add_parser('update_metadata',
help='%s %s' % (h1, h2))
help='%s %s %s' % (clnt_hdr,
h1, h2))
parser_update_metadata.add_argument('client',
**cli_common.ORM_CLIENT_KWARGS)
parser_update_metadata.add_argument('region_id', type=str, help=h1)
parser_update_metadata.add_argument('datafile',
type=argparse.FileType('r'),
@ -153,7 +176,10 @@ def add_to_parser(service_sub):
# delete metadata key from region
h1, h2 = '<region id>', '<metadata key>'
parser_delete_metadata = subparsers.add_parser('delete_metadata',
help='%s %s' % (h1, h2))
help='%s %s %s' % (clnt_hdr,
h1, h2))
parser_delete_metadata.add_argument('client',
**cli_common.ORM_CLIENT_KWARGS)
parser_delete_metadata.add_argument('region_id', type=str, help=h1)
parser_delete_metadata.add_argument('metadata_key', type=str, help=h2)
@ -161,12 +187,15 @@ def add_to_parser(service_sub):
h1 = '<region id>'
parser_get_metadata = subparsers.add_parser('get_metadata',
help='%s' % (h1))
parser_get_metadata.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_get_metadata.add_argument('region_id', type=str, help=h1)
# update region's status
h1, h2 = '<region_id>', '<status>'
parser_update_status = subparsers.add_parser('update_status',
help='%s %s' % (h1, h2))
help='%s %s %s' % (clnt_hdr,
h1, h2))
parser_update_status.add_argument('client', **cli_common.ORM_CLIENT_KWARGS)
parser_update_status.add_argument('region_id', type=str, help=h1)
parser_update_status.add_argument('status', type=str, help=h2)
@ -198,12 +227,12 @@ def get_token(timeout, args, host):
globals()[argument] = configuration_value
else:
message = ('ERROR: {} for token generation was not supplied. '
'Please use its command-line '
'argument or environment variable.'.format(argument))
'Please use its command-line argument or '
'environment variable.'.format(argument))
print message
raise cli_common.MissingArgumentError(message)
keystone_ep = cli_common.get_keystone_ep('{}:{}'.format(host, base_config.rms['port']),
keystone_ep = cli_common.get_keystone_ep('{}:8080'.format(host),
auth_region)
if keystone_ep is None:
raise ConnectionError(
@ -259,8 +288,9 @@ def cmd_details(args):
param += '%sregionname=%s' % (preparm(param), args.regionname)
if args.osversion:
param += '%sosversion=%s' % (preparm(param), args.osversion)
if args.valet:
param += '%svalet=%s' % (preparm(param), args.valet)
if args.location_type:
param += '%slocation_type=%s' % (preparm(param),
args.location_type)
if args.state:
param += '%sstate=%s' % (preparm(param), args.state)
if args.country:
@ -306,7 +336,7 @@ def get_path(args):
def get_environment_variable(argument):
# The rules are: all caps, underscores instead of dashes and prefixed
environment_variable = 'RANGER_{}'.format(
environment_variable = 'AIC_ORM_{}'.format(
argument.replace('-', '_').upper())
return os.environ.get(environment_variable)
@ -315,12 +345,16 @@ def get_environment_variable(argument):
def run(args):
url_path = get_path(args)
host = args.orm_base_url if args.orm_base_url else config.orm_base_url
port = args.port if args.port else base_config.rms['port']
port = args.port if args.port else 8080
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:%d/%s' % (host, port, url_path) + cmd_url
if args.faceless:
if args.faceless or \
args.subcmd == 'get_region' or \
args.subcmd == 'list_regions' or \
args.subcmd == 'list_groups' or \
args.subcmd == 'get_group':
auth_token = auth_region = requester = client = ''
else:
try:
@ -361,7 +395,7 @@ def run(args):
url))
try:
resp = rest_cmd(url, data=data, timeout=timeout, headers=headers,
verify=False)
verify=config.verify)
except Exception as e:
print e
exit(1)

View File

@ -1,9 +0,0 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
# Hacking already pins down pep8, pyflakes and flake8
mock
coverage
testfixtures
pytest-pep8

View File

@ -1,19 +0,0 @@
[tox]
envlist=py27,cover
[testenv]
deps= -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands=
py.test --pep8 -m pep8
[testenv:cover]
commands=
coverage run setup.py test
coverage report --omit=.tox/*,ormcli/tests/*,setup.py
coverage html --omit=.tox/*,ormcli/tests/*,setup.py
#commands={envpython} setup.py test -v {posargs}
[testenv:pep8]
commands =
py.test --pep8 -m pep8

View File

@ -1,11 +1,9 @@
"""app module."""
import logging
import os
from orm.services.audit_trail_manager.audit_server import model
from orm.services.audit_trail_manager.audit_server.storage import factory
from pecan.commands import CommandRunner
from pecan import make_app
logger = logging.getLogger(__name__)
@ -26,11 +24,3 @@ def setup_app(config):
logger.info('Starting Audit...')
return app
def main():
dir_name = os.path.dirname(__file__)
drive, path_and_file = os.path.splitdrive(dir_name)
path, filename = os.path.split(path_and_file)
runner = CommandRunner()
runner.run(['serve', path + '/config.py'])

View File

@ -88,9 +88,16 @@ class RegionController(rest.RestController):
return result
@wsexpose(None, str, str, status_code=204)
def delete(self, customer_id, region_id):
LOG.info("RegionController - Delete Region (delete) customer id {0} region_id: {1}".format(customer_id, region_id))
@wsexpose(None, str, str, str, status_code=204)
def delete(self, customer_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 (delete) customer id {0} region_id: {1} by RDS Proxy: {2} ".format(customer_id, region_id, is_rds_client_request))
authentication.authorize(request, 'customers:delete_region')
try:
customer_logic = CustomerLogic()

View File

@ -52,18 +52,15 @@ class CustomerController(rest.RestController):
authentication.authorize(request, 'customers:create')
try:
uuid = None
if not customer.custId:
uuid = utils.make_uuid()
else:
if not CustomerController.validate_cust_id(customer.custId):
utils.audit_trail('create customer', request.transaction_id, request.headers, customer.custId)
raise ErrorStatus('400', None)
try:
uuid = utils.create_existing_uuid(customer.custId)
except TypeError:
raise ErrorStatus(409.1, 'Customer ID {0} already exists'.format(customer.custId))
if not customer.uuid:
customer.uuid = None
customer_logic = CustomerLogic()
try:
uuid = utils.create_or_validate_uuid(customer.uuid, 'custId')
except TypeError:
raise ErrorStatus(409.1, 'Unable to create Customer ID {0}'.format(customer.uuid))
try:
result = customer_logic.create_customer(customer, uuid, request.transaction_id)
except oslo_db.exception.DBDuplicateEntry as exception:
@ -121,19 +118,25 @@ class CustomerController(rest.RestController):
return result
@wsexpose(CustomerSummaryResponse, str, str, str, str, [str],
@wsexpose(CustomerSummaryResponse, str, str, str, str, [str], int, int,
rest_content_types='json')
def get_all(self, region=None, user=None, starts_with=None,
contains=None, metadata=None):
contains=None, metadata=None, start=0, limit=0):
LOG.info("CustomerController - GetCustomerlist")
authentication.authorize(request, 'customers: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
try:
customer_logic = CustomerLogic()
result = customer_logic.get_customer_list_by_criteria(region, user,
starts_with,
contains,
metadata)
metadata,
start,
limit)
return result
except ErrorStatus as exception:
LOG.log_exception("CustomerController - Failed to GetCustomerlist", exception)
@ -174,9 +177,3 @@ class CustomerController(rest.RestController):
raise err_utils.get_error(request.transaction_id,
status_code=500,
error_details=exception.message)
@staticmethod
def validate_cust_id(cust_id):
# regex = re.compile('[a-zA-Z]')
# return regex.match(cust_id[0])
return True

View File

@ -161,11 +161,19 @@ class UserController(rest.RestController):
status_code=404)
except Exception as exception:
result = UserResultWrapper(transaction_id="Users Not Added", users=[])
LOG.log_exception("UserController - Failed to Add Users (post)", exception)
raise err_utils.get_error(request.transaction_id,
status_code=500,
error_details=str(exception))
if exception.inner_exception.orig[0] == 1452:
result = UserResultWrapper(transaction_id="Users Not Added", users=[])
LOG.log_exception("UserController - Failed to Add Users (post)", exception)
LOG.log_exception("Region specified must be added to customer first.", exception)
raise err_utils.get_error(request.transaction_id,
status_code=500,
message="Region specified must be added to customer first.")
else:
result = UserResultWrapper(transaction_id="Users Not Added", users=[])
LOG.log_exception("UserController - Failed to Add Users (post)", exception)
raise err_utils.get_error(request.transaction_id,
status_code=500,
error_details=str(exception))
return result
@ -225,6 +233,7 @@ class UserController(rest.RestController):
except ErrorStatus as exception:
LOG.log_exception("DefaultUserController - Failed to delete users", exception)
raise err_utils.get_error(request.transaction_id,
message=exception.message,
status_code=exception.status_code)
except LookupError as exception:

View File

@ -86,20 +86,20 @@ class DataManager(object):
cms_users = self.session.query(CmsUser)
return cms_users.all()
def get_cusomer_by_id(self, customer_id):
def get_customer_by_id(self, customer_id):
customer = self.session.query(Customer).filter(
Customer.id == customer_id)
return customer.first()
def get_cusomer_by_uuid(self, uuid):
def get_customer_by_uuid(self, uuid):
customer = self.session.query(Customer).filter(Customer.uuid == uuid)
return customer.first()
def get_cusomer_by_name(self, name):
def get_customer_by_name(self, name):
customer = self.session.query(Customer).filter(Customer.name == name)
return customer.first()
def get_cusomer_by_uuid_or_name(self, cust):
def get_customer_by_uuid_or_name(self, cust):
customer = self.session.query(Customer).filter(
or_(Customer.uuid == cust,
Customer.name == cust))

View File

@ -42,7 +42,7 @@ class CustomerRecord:
raise
def delete_by_primary_key(self, customer_id):
result = self.session.connection().execute("delete from customer where id = %d" % (customer_id))
result = self.session.connection().execute("delete from customer where id = {}".format(customer_id))
return result
def read_by_primary_key(self):
@ -69,13 +69,23 @@ class CustomerRecord:
raise
def get_customer_id_from_uuid(self, uuid):
result = self.session.connection().scalar("SELECT id from customer WHERE uuid = \"%s\"" % uuid)
result = self.session.connection().scalar("SELECT id from customer WHERE uuid = \"{}\"".format(uuid))
if result:
return int(result)
else:
return None
def get_customers_status_by_uuids(self, uuid_str):
results = self.session.connection().execute("SELECT resource_id, status from rds_resource_status_view"
" WHERE resource_id in ({})".format(uuid_str))
resource_status_dict = {}
if results:
resource_status_dict = dict((resource_id, status) for resource_id, status in results)
results.close()
return resource_status_dict
def delete_customer_by_uuid(self, uuid):
try:
result = self.session.query(Customer).filter(

View File

@ -68,7 +68,7 @@ class CustomerRegionRecord:
'region with the region name {0} not found'.format(
region_name))
result = self.session.connection().execute(
"delete from customer_region where customer_id = %d and region_id = %d" % (customer_id, region_id))
"delete from customer_region where customer_id = {} and region_id = {}".format(customer_id, region_id))
self.session.flush()
if result.rowcount == 0:

View File

@ -27,7 +27,7 @@ class RegionRecord:
@region.setter
def region(self, region):
self.__regionn = region
self.__region = region
def insert(self, region):
try:
@ -37,7 +37,7 @@ class RegionRecord:
raise
def get_region_id_from_name(self, region_name):
result = self.session.connection().scalar("SELECT id from region WHERE name = \"%s\"" % (region_name))
result = self.session.connection().scalar("SELECT id from region WHERE name = \"{}\"".format(region_name))
if result is not None:
return int(result)
return result

View File

@ -61,8 +61,19 @@ class UserRoleRecord:
if user_id is None:
raise NotFound("user %s is not found" % user_query)
result = self.session.connection().execute("delete from user_role where customer_id = %d and region_id = %d and user_id = %d" % (customer_id, region_id, user_id))
print "num records deleted: " + str(result.rowcount)
if region_id == -1:
delete_query = "DELETE ur FROM user_role ur,user_role u " \
"where ur.user_id=u.user_id and ur.role_id=u.role_id " \
"and ur.customer_id = u.customer_id and u.region_id =-1 " \
"and ur.customer_id = %d and ur.user_id=%d" % (customer_id, user_id)
else:
delete_query = "DELETE ur FROM user_role as ur LEFT JOIN user_role AS u " \
"ON ur.customer_id = u.customer_id and u.user_id=ur.user_id " \
"and u.region_id=-1 where ur.customer_id = %d and ur.region_id= %d " \
"and ur.user_id =%d and ur.role_id !=IFNULL(u.role_id,'')" \
% (customer_id, region_id, user_id)
result = self.session.connection().execute(delete_query)
return result
def delete_all_users_from_region(self, customer_id, region_id):
@ -75,9 +86,19 @@ class UserRoleRecord:
if isinstance(region_id, basestring):
region_record = RegionRecord(self.session)
region_id = region_record.get_region_id_from_name(region_id)
if region_id == -1:
delete_query = "DELETE ur FROM user_role ur,user_role u " \
"where ur.user_id=u.user_id and ur.role_id=u.role_id " \
"and ur.customer_id = u.customer_id and u.region_id =-1 " \
"and ur.customer_id = %d" % (customer_id)
else:
delete_query = "DELETE ur FROM user_role as ur LEFT JOIN user_role AS u " \
"ON ur.customer_id = u.customer_id and u.user_id=ur.user_id " \
"and u.region_id=-1 where ur.customer_id = %d and ur.region_id= %d " \
"and ur.role_id !=IFNULL(u.role_id,'')" \
% (customer_id, region_id)
result = self.session.connection().execute(
"delete from user_role where customer_id = {} and region_id = {}".format(customer_id, region_id))
result = self.session.connection().execute(delete_query)
print "num records deleted: " + str(result.rowcount)
return result

View File

@ -1,31 +1,32 @@
{
"default": "!",
"admin": "role:admin",
"admin_support": "role:admin_support",
"admin_viewer": "role:admin_viewer",
"admin_or_admin_support": "rule:admin or rule:admin_support",
"admin_or_admin_support_or_admin_viewer": "rule:admin or rule:admin_support or rule:admin_viewer",
"admin": "role:admin and tenant:admin or role:admin and tenant:services",
"admin_support": "role:admin_support and tenant:admin or role:admin_support and tenant:services",
"admin_viewer": "role:admin_viewer and tenant:admin or role:admin_viewer and tenant:services",
"customers:get_one": "rule:admin_or_admin_support_or_admin_viewer",
"customers:get_all": "rule:admin_or_admin_support_or_admin_viewer",
"customers:create": "rule:admin_or_admin_support",
"admin_or_support": "rule:admin or rule:admin_support",
"admin_or_support_or_viewer": "rule:admin or rule:admin_support or rule:admin_viewer",
"customers:get_one": "rule:admin_or_support_or_viewer",
"customers:get_all": "rule:admin_or_support_or_viewer",
"customers:create": "rule:admin_or_support",
"customers:update": "rule:admin",
"customers:delete": "rule:admin",
"customers:add_region": "rule:admin_or_admin_support",
"customers:add_region": "rule:admin_or_support",
"customers:update_region": "rule:admin",
"customers:delete_region": "rule:admin",
"customers:add_region_user": "rule:admin",
"customers:add_region_user": "rule:admin_or_support",
"customers:update_region_user": "rule:admin",
"customers:delete_region_user": "rule:admin",
"customers:add_default_user": "rule:admin",
"customers:add_default_user": "rule:admin_or_support",
"customers:update_default_user": "rule:admin",
"customers:delete_default_user": "rule:admin",
"customers:add_metadata": "rule:admin",
"customers:add_metadata": "rule:admin_or_support",
"customers:update_metadata": "rule:admin",
"customers:enable": "rule:admin"

View File

@ -6,7 +6,7 @@ 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.data.sql_alchemy.models import CustomerMetadata, UserRole
from orm.services.customer_manager.cms_rest.data.sql_alchemy.models import CustomerMetadata
from orm.services.customer_manager.cms_rest.logger import get_logger
from orm.services.customer_manager.cms_rest.logic.error_base import (DuplicateEntryError, ErrorStatus,
NotFound)
@ -20,49 +20,35 @@ LOG = get_logger(__name__)
class CustomerLogic(object):
def build_full_customer(self, customer, uuid, datamanager):
if any(char in ":" for char in customer.name):
raise ErrorStatus(400, "Customer Name does not allow colon(:).")
if customer.name.strip() == '':
raise ErrorStatus(400, "Customer Name can not be blank.")
sql_customer = datamanager.add_customer(customer, uuid)
for key, value in customer.metadata.iteritems():
metadata = CustomerMetadata(field_key=key, field_value=value)
sql_customer.customer_metadata.append(metadata)
datamanager.add_customer_region(sql_customer.id, -1)
sql_customer_id = sql_customer.id
datamanager.add_customer_region(sql_customer_id, -1)
default_region_users = []
for user in customer.users:
sql_user = datamanager.add_user(user)
default_region_users.append(sql_user)
sql_user.sql_roles = []
for role in user.role:
sql_role = datamanager.add_role(role)
sql_user.sql_roles.append(sql_role)
default_users_requested = customer.users
default_region_users =\
self.add_default_user_db(datamanager, default_users_requested, [], sql_customer_id)
default_quotas = []
for quota in customer.defaultQuotas:
sql_quota = datamanager.add_quota(sql_customer.id, -1, quota)
sql_quota = datamanager.add_quota(sql_customer_id, -1, quota)
default_quotas.append(sql_quota)
for sql_user in default_region_users:
for sql_role in sql_user.sql_roles:
datamanager.add_user_role(sql_user.id, sql_role.id,
sql_customer.id, -1)
self.add_regions_to_db(customer.regions, sql_customer.id, datamanager, customer.users)
self.add_regions_to_db(customer.regions, sql_customer_id, datamanager, default_region_users)
return sql_customer
def add_regions_to_db(self, regions, sql_customer_id, datamanager, default_users=[]):
for region in regions:
users_roles = self.add_user_and_roles_to_db(region.users, default_users,
datamanager)
# NOTE: if region has no users there is no need to update the
# default users in that region
# if len(region.users) == 0:
# users_roles.extend(self.add_user_and_roles_to_db(
# customer.users, datamanager))
# else:
# users_roles.extend(self.add_user_and_roles_to_db(
# region.users, datamanager))
sql_region = datamanager.add_region(region)
try:
@ -73,9 +59,8 @@ class CustomerLogic(object):
'Error, duplicate entry, region ' + region.name + ' already associated with customer')
raise ex
for user_role in users_roles:
datamanager.add_user_role(user_role[0].id, user_role[1].id,
sql_customer_id, sql_region.id)
self.add_user_and_roles_to_db(region.users, default_users,
sql_customer_id, sql_region.id, datamanager)
for quota in region.quotas:
datamanager.add_quota(sql_customer_id, sql_region.id, quota)
@ -91,20 +76,76 @@ class CustomerLogic(object):
# datamanager.add_quota(sql_customer_id,
# sql_region.id, quota)
def add_user_and_roles_to_db(self, users, default_users, datamanager):
users_roles = []
for user in users:
sql_user = datamanager.add_user(user)
for role in user.role:
sql_role = datamanager.add_role(role)
users_roles.append((sql_user, sql_role))
for default_user in default_users:
sql_user = datamanager.add_user(default_user)
for role in default_user.role:
sql_role = datamanager.add_role(role)
users_roles.append((sql_user, sql_role))
def add_default_user_db(self, datamanager, default_users_requested, existing_default_users_roles, sql_customer_id):
default_region_users = []
default_users_dic = {}
return users_roles
for sql_user in existing_default_users_roles:
default_users_dic[sql_user.name] = sql_user
for user in default_users_requested:
is_default_user_exist = user.id in default_users_dic.keys()
if not is_default_user_exist:
sql_user = datamanager.add_user(user)
default_region_users.append(sql_user)
sql_user.sql_roles = []
for role in user.role:
sql_role = datamanager.add_role(role)
sql_user.sql_roles.append(sql_role)
else:
sql_user = default_users_dic.get(user.id)
new_sql_roles = []
for role in user.role:
role_match = False
for sql_role in sql_user.sql_roles:
if sql_role.name == role:
role_match = True
break
if not role_match:
sql_role = datamanager.add_role(role)
new_sql_roles.append(sql_role)
if new_sql_roles:
sql_user.sql_roles = new_sql_roles
default_region_users.append(sql_user)
for sql_user in default_region_users:
for sql_role in sql_user.sql_roles:
datamanager.add_user_role(sql_user.id, sql_role.id,
sql_customer_id, -1)
return default_region_users
def add_user_and_roles_to_db(self, users, sql_default_users, sql_customer_id, sql_region_id, datamanager):
users_roles = []
default_users_dic = {}
for sql_user in sql_default_users:
default_users_dic[sql_user.name] = sql_user
for role in sql_user.sql_roles:
users_roles.append((sql_user, role))
# Default user will be given priority over region user
for user in users:
is_default_user_in_region = user.id in default_users_dic.keys()
if not is_default_user_in_region:
sql_user = datamanager.add_user(user)
for role in user.role:
sql_role = datamanager.add_role(role)
users_roles.append((sql_user, sql_role))
else:
sql_user = default_users_dic.get(user.id)
for role in user.role:
role_match = False
for sql_role in sql_user.sql_roles:
if sql_role.name == role:
role_match = True
break
if not role_match:
sql_role = datamanager.add_role(role)
users_roles.append((sql_user, sql_role))
for user_role in users_roles:
datamanager.add_user_role(user_role[0].id, user_role[1].id,
sql_customer_id, sql_region_id)
def create_customer(self, customer, uuid, transaction_id):
datamanager = DataManager()
@ -113,7 +154,6 @@ class CustomerLogic(object):
sql_customer = self.build_full_customer(customer, uuid, datamanager)
customer_result_wrapper = build_response(uuid, transaction_id, 'create')
sql_customer = self.add_default_users_to_empty_regions(sql_customer)
if sql_customer.customer_customer_regions and len(sql_customer.customer_customer_regions) > 1:
customer_dict = sql_customer.get_proxy_dict()
for region in customer_dict["regions"]:
@ -150,7 +190,6 @@ class CustomerLogic(object):
sql_customer = self.build_full_customer(customer, customer_uuid,
datamanager)
sql_customer = self.add_default_users_to_empty_regions(sql_customer)
new_customer_dict = sql_customer.get_proxy_dict()
new_customer_dict["regions"] = self.resolve_regions_actions(old_customer_dict["regions"],
new_customer_dict["regions"])
@ -202,11 +241,19 @@ class CustomerLogic(object):
if region_id is None:
raise ErrorStatus(404, "region {} not found".format(region_name))
self.add_users_to_db(datamanager, customer_id, region_id, users, adding=True)
customer_record = datamanager.get_record('customer')
customer = customer_record.read_customer(customer_id)
defaultRegion = customer.get_default_customer_region()
default_users_roles = defaultRegion.customer_region_user_roles if defaultRegion else []
default_users = []
for default_user in default_users_roles:
if default_user.user not in default_users:
default_users.append(default_user.user)
default_user.user.sql_roles = []
default_user.user.sql_roles.append(default_user.role)
self.add_user_and_roles_to_db(users, default_users,
customer_id, region_id, datamanager)
timestamp = utils.get_time_human()
datamanager.flush() # i want to get any exception created by this insert
RdsProxy.send_customer(customer, transaction_id, "PUT")
@ -256,29 +303,12 @@ class CustomerLogic(object):
LOG.log_exception("Failed to replace_default_users", exception)
raise
def add_users_to_db(self, datamanager, customer_id, region_id, users, adding=False):
try:
users_roles = []
for user in users:
sql_user = datamanager.add_user(user)
for role in user.role:
sql_role = datamanager.add_role(role)
users_roles.append((sql_user, sql_role))
for user_role in users_roles:
# TODO: change add_use_role to receive sqlalchemy model (UserRole)
datamanager.add_user_role(user_role[0].id, user_role[1].id,
customer_id, region_id, adding)
datamanager.flush()
except Exception as exception:
LOG.log_exception("Failed to add users", exception)
raise
def delete_users(self, customer_uuid, region_id, user_id, transaction_id):
datamanager = DataManager()
try:
user_role_record = datamanager.get_record('user_role')
customer = datamanager.get_cusomer_by_uuid(customer_uuid)
customer = datamanager.get_customer_by_uuid(customer_uuid)
if customer is None:
raise ErrorStatus(404, "customer {} does not exist".format(customer_uuid))
@ -286,13 +316,24 @@ class CustomerLogic(object):
region_id,
user_id)
if result.rowcount == 0:
raise NotFound("user {} is not found".format(user_id))
'''when result.rowcount returns 0, this indicates that the region user marked
for deletion also exists - and has the same exact roles - in the default user
level. Since default_user supersedes region user, use 'delete_default_user'
instead of 'delete_user' command.
'''
message = "Cannot use 'delete_user' as user '%s' exists and has " \
"the exact same roles in both the default and '%s' "\
"region levels for customer %s. "\
"Use 'delete_default_user' instead." \
% (user_id, region_id, customer_uuid)
raise ErrorStatus(400, message)
RdsProxy.send_customer(customer, transaction_id, "PUT")
datamanager.commit()
print "User {0} from region {1} in customer {2} deleted".format(
user_id, region_id, customer_uuid)
LOG.info("User {0} from region {1} in customer {2} deleted".
format(user_id, region_id, customer_uuid))
except NotFound as e:
datamanager.rollback()
LOG.log_exception("Failed to delete_users, user not found",
@ -318,10 +359,25 @@ class CustomerLogic(object):
if customer_id is None:
raise ErrorStatus(404, "customer {} does not exist".format(customer_uuid))
self.add_users_to_db(datamanager, customer_id, -1, users, adding=True)
customer_record = datamanager.get_record('customer')
customer = customer_record.read_customer(customer_id)
defaultRegion = customer.get_default_customer_region()
existing_default_users_roles = defaultRegion.customer_region_user_roles if defaultRegion else []
default_users = []
for default_user in existing_default_users_roles:
if default_user.user not in default_users:
default_users.append(default_user.user)
default_user.user.sql_roles = []
default_user.user.sql_roles.append(default_user.role)
default_region_users = \
self.add_default_user_db(datamanager, users, default_users, customer_id)
regions = customer.get_real_customer_regions()
for region in regions:
self.add_user_and_roles_to_db(users, default_region_users,
customer_id, region.region_id, datamanager)
timestamp = utils.get_time_human()
datamanager.flush() # i want to get any exception created by this insert
@ -374,7 +430,7 @@ class CustomerLogic(object):
def delete_default_users(self, customer_uuid, user_id, transaction_id):
datamanager = DataManager()
try:
customer = datamanager.get_cusomer_by_uuid(customer_uuid)
customer = datamanager.get_customer_by_uuid(customer_uuid)
if customer is None:
raise ErrorStatus(404, "customer {} does not exist".format(customer_uuid))
@ -382,20 +438,23 @@ class CustomerLogic(object):
result = user_role_record.delete_user_from_region(customer_uuid,
'DEFAULT',
user_id)
if result.rowcount == 0:
raise NotFound("user {} is not found".format(user_id))
raise NotFound("user {} ".format(user_id))
datamanager.flush()
if len(customer.customer_customer_regions) > 1:
RdsProxy.send_customer(customer, transaction_id, "PUT")
datamanager.commit()
print "User {0} from region {1} in customer {2} deleted".format(
user_id, 'DEFAULT', customer_uuid)
LOG.info("User {0} from region {1} in customer {2} deleted".
format(user_id, 'DEFAULT', customer_uuid))
except NotFound as e:
datamanager.rollback()
LOG.log_exception("Failed to delete_users, user not found",
e.message)
raise NotFound("Failed to delete users, %s not found" %
raise NotFound("Failed to delete user(s), %s not found" %
e.message)
except Exception as exp:
@ -412,11 +471,26 @@ class CustomerLogic(object):
raise ErrorStatus(404,
"customer with id {} does not exist".format(
customer_uuid))
self.add_regions_to_db(regions, customer_id, datamanager)
sql_customer = customer_record.read_customer_by_uuid(customer_uuid)
sql_customer = self.add_default_users_to_empty_regions(sql_customer)
defaultRegion = sql_customer.get_default_customer_region()
existing_default_users_roles = defaultRegion.customer_region_user_roles if defaultRegion else []
default_users = []
for default_user in existing_default_users_roles:
if default_user.user not in default_users:
default_users.append(default_user.user)
default_user.user.sql_roles = []
default_user.user.sql_roles.append(default_user.role)
self.add_regions_to_db(regions, customer_id, datamanager, default_users)
datamanager.commit()
datamanager.session.expire(sql_customer)
sql_customer = datamanager.get_customer_by_id(customer_id)
new_customer_dict = sql_customer.get_proxy_dict()
for region in new_customer_dict["regions"]:
@ -427,9 +501,7 @@ class CustomerLogic(object):
region["action"] = "modify"
timestamp = utils.get_time_human()
datamanager.flush() # i want to get any exception created by this insert
RdsProxy.send_customer_dict(new_customer_dict, transaction_id, "POST")
datamanager.commit()
base_link = '{0}{1}/'.format(conf.server.host_ip,
pecan.request.path)
@ -462,16 +534,23 @@ class CustomerLogic(object):
"customer with id {} does not exist".format(
customer_id))
old_customer_dict = old_sql_customer.get_proxy_dict()
defaultRegion = old_sql_customer.get_default_customer_region()
existing_default_users_roles = defaultRegion.customer_region_user_roles if defaultRegion else []
default_users = []
for default_user in existing_default_users_roles:
if default_user.user not in default_users:
default_users.append(default_user.user)
default_user.user.sql_roles = []
default_user.user.sql_roles.append(default_user.role)
datamanager.session.expire(old_sql_customer)
customer_region.delete_all_regions_for_customer(customer_id)
self.add_regions_to_db(regions, customer_id, datamanager)
self.add_regions_to_db(regions, customer_id, datamanager, default_users)
timestamp = utils.get_time_human()
new_sql_customer = datamanager.get_cusomer_by_id(customer_id)
new_sql_customer = datamanager.get_customer_by_id(customer_id)
new_sql_customer = self.add_default_users_to_empty_regions(new_sql_customer)
new_customer_dict = new_sql_customer.get_proxy_dict()
datamanager.flush() # i want to get any exception created by this insert
@ -496,12 +575,15 @@ class CustomerLogic(object):
datamanager.rollback()
raise exp
def delete_region(self, customer_id, region_id, transaction_id):
def delete_region(self, customer_id, region_id, transaction_id, on_success_by_rds,
force_delete):
datamanager = DataManager()
try:
customer_region = datamanager.get_record('customer_region')
sql_customer = datamanager.get_cusomer_by_uuid(customer_id)
sql_customer = datamanager.get_customer_by_uuid(customer_id)
if on_success_by_rds and sql_customer is None:
return
if sql_customer is None:
raise ErrorStatus(404,
"customer with id {} does not exist".format(
@ -509,36 +591,42 @@ class CustomerLogic(object):
customer_dict = sql_customer.get_proxy_dict()
customer_region.delete_region_for_customer(customer_id, region_id)
datamanager.flush() # i want to get any exception created by this insert
datamanager.flush() # Get any exception created by this insert
# i want to get any exception created by this insert
datamanager.flush()
if on_success_by_rds:
datamanager.commit()
LOG.debug("Region {0} in customer {1} deleted".format(region_id,
customer_id))
else:
region = next((r.region for r in sql_customer.customer_customer_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 customer_dict['regions']:
if region['name'] in regions:
region['action'] = 'delete'
region = next((r.region for r in sql_customer.customer_customer_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)
RdsProxy.send_customer_dict(customer_dict, transaction_id, "PUT")
if force_delete:
datamanager.commit()
else:
regions = [region_id]
for region in customer_dict['regions']:
if region['name'] in regions:
region['action'] = 'delete'
datamanager.rollback()
RdsProxy.send_customer_dict(customer_dict, transaction_id, "PUT")
datamanager.commit()
LOG.debug("Region {0} in customer {1} deleted".format(region_id,
customer_id))
except Exception as exp:
datamanager.rollback()
raise
finally:
datamanager.close()
def get_customer(self, customer):
datamanager = DataManager()
sql_customer = datamanager.get_cusomer_by_uuid_or_name(customer)
sql_customer = datamanager.get_customer_by_uuid_or_name(customer)
if not sql_customer:
raise ErrorStatus(404, 'customer: {0} not found'.format(customer))
@ -564,24 +652,28 @@ class CustomerLogic(object):
return ret_customer
def get_customer_list_by_criteria(self, region, user, starts_with, contains,
metadata):
metadata, start=0, limit=0):
datamanager = DataManager()
customer_record = datamanager.get_record('customer')
sql_customers = customer_record.get_customers_by_criteria(region=region,
user=user,
starts_with=starts_with,
contains=contains,
metadata=metadata)
metadata=metadata,
start=start,
limit=limit)
response = CustomerSummaryResponse()
for sql_customer in sql_customers:
# get aggregate status for each customer
customer_status = RdsProxy.get_status(sql_customer.uuid)
customer = CustomerSummary.from_db_model(sql_customer)
if customer_status.status_code == 200:
customer.status = customer_status.json()['status']
response.customers.append(customer)
if sql_customers:
uuids = ','.join(str("\'" + sql_customer.uuid + "\'")
for sql_customer in sql_customers if sql_customer and sql_customer.uuid)
resource_status_dict = customer_record.get_customers_status_by_uuids(uuids)
for sql_customer in sql_customers:
customer = CustomerSummary.from_db_model(sql_customer)
if sql_customer.uuid:
status = resource_status_dict.get(sql_customer.uuid)
customer.status = not status and 'no regions' or status
response.customers.append(customer)
return response
def enable(self, customer_uuid, enabled, transaction_id):
@ -601,29 +693,14 @@ class CustomerLogic(object):
datamanager.flush() # get any exception created by this action
datamanager.commit()
customer_result_wrapper = build_response(customer_uuid, transaction_id, 'update')
return customer_result_wrapper
except Exception as exp:
datamanager.rollback()
raise exp
def add_default_users_to_empty_regions(self, sql_customer):
if len(sql_customer.customer_customer_regions) > 0:
for region in sql_customer.customer_customer_regions:
if region.region_id == -1:
users = region.customer_region_user_roles[:]
break
for region in sql_customer.customer_customer_regions:
if region.region_id != -1:
for user in users:
u = UserRole()
u.customer_id = region.customer_id
u.region_id = region.region_id
u.user_id = user.user_id
u.role_id = user.role_id
region.customer_region_user_roles.append(u)
return sql_customer
def delete_customer_by_uuid(self, customer_id):
datamanager = DataManager()
@ -633,9 +710,7 @@ class CustomerLogic(object):
sql_customer = customer_record.read_customer_by_uuid(customer_id)
if sql_customer is None:
# The customer does not exist, so the delete operation is
# considered successful
return
raise ErrorStatus(404, "Customer '{0}' not found".format(customer_id))
real_regions = sql_customer.get_real_customer_regions()
if len(real_regions) > 0:
@ -706,7 +781,7 @@ def build_response(customer_uuid, transaction_id, context):
link_elements = request.url.split('/')
base_link = '/'.join(link_elements)
if context == 'create':
base_link += customer_uuid
base_link = base_link + '/' + customer_uuid
timestamp = utils.get_time_human()
customer_result_wrapper = CustomerResultWrapper(

View File

@ -112,17 +112,19 @@ class Network(Model):
subnets = wsme.wsattr(wsme.types.text, mandatory=True)
security_groups = wsme.wsattr(wsme.types.text, mandatory=False, name="security-groups")
security_group_rules = wsme.wsattr(wsme.types.text, mandatory=False, name="security-group-rules")
health_monitor = wsme.wsattr(wsme.types.text, mandatory=False, name="health-monitor")
member = wsme.wsattr(wsme.types.text, mandatory=False)
health_monitors = wsme.wsattr(wsme.types.text, mandatory=False, name="health-monitors")
members = wsme.wsattr(wsme.types.text, mandatory=False)
nat_instance = wsme.wsattr(wsme.types.text, mandatory=False, name="nat-instance")
pool = wsme.wsattr(wsme.types.text, mandatory=False)
pools = wsme.wsattr(wsme.types.text, mandatory=False)
route_table = wsme.wsattr(wsme.types.text, mandatory=False, name="route-table")
vip = wsme.wsattr(wsme.types.text, mandatory=False)
vips = wsme.wsattr(wsme.types.text, mandatory=False)
loadbalancer = wsme.wsattr(wsme.types.text, mandatory=False, name='loadbalancer')
listener = wsme.wsattr(wsme.types.text, mandatory=False, name='listener')
def __init__(self, floating_ips='', networks='', ports='', routers='',
subnets='', security_groups=None, security_group_rules=None,
health_monitor='', member='', nat_instance='',
pool='', route_table='', vip=''):
health_monitors='', members='', nat_instance='',
pools='', route_table='', vips='', loadbalancer='', listener=''):
"""Create a new Network instance.
:param floating_ips: num of floating_ips
@ -132,12 +134,14 @@ class Network(Model):
:param subnets: num of subnets
:param security_groups: security groups
:param security_group_rules: security group rules
:param health_monitor:
:param member:
:param health_monitors:
:param members:
:param nat_instance:
:param pool:
:param pools:
:param route_table:
:param vip:
:param vips:
:param loadbalancer:
:param listener:
"""
self.floating_ips = floating_ips
self.networks = networks
@ -153,17 +157,18 @@ class Network(Model):
else:
self.security_group_rules = security_group_rules
self.health_monitor = health_monitor
self.member = member
self.health_monitors = health_monitors
self.members = members
self.nat_instance = nat_instance
self.pool = pool
self.pools = pools
self.route_table = route_table
self.vip = vip
self.vips = vips
self.loadbalancer = loadbalancer
self.listener = listener
class Quota(Model):
"""network model the customer
"""
compute = wsme.wsattr([Compute], mandatory=False)
storage = wsme.wsattr([Storage], mandatory=False)
@ -183,7 +188,6 @@ class Quota(Model):
class User(Model):
"""user model the customer
"""
id = wsme.wsattr(wsme.types.text, mandatory=True)
role = wsme.wsattr([str])
@ -200,7 +204,6 @@ class User(Model):
class Region(Model):
"""network model the customer
"""
name = wsme.wsattr(wsme.types.text, mandatory=True)
type = wsme.wsattr(wsme.types.text, default="single", mandatory=False)
@ -232,7 +235,6 @@ class Region(Model):
class Customer(Model):
"""customer entity with all it's related data
"""
description = wsme.wsattr(wsme.types.text, mandatory=True)
enabled = wsme.wsattr(bool, mandatory=True)

View File

@ -88,3 +88,8 @@ create table if not exists user_role
foreign key (role_id) references cms_role(id),
index region_id (region_id),
index user_id (user_id));
CREATE OR REPLACE VIEW rds_resource_status_view AS
(
SELECT ID, RESOURCE_ID, REGION,STATUS,
ERR_CODE,OPERATION from orm_rds.resource_status);

View File

@ -78,14 +78,16 @@ SELECT q.*, qfd.* FROM quota_field_detail qfd
DELIMITER ;;
# account for the old procedure name in DROP PROCEDURE before the name change
DROP PROCEDURE IF EXISTS add_regoion_type ;;
CREATE PROCEDURE add_regoion_type()
DROP PROCEDURE IF EXISTS add_region_type ;;
CREATE PROCEDURE add_region_type()
BEGIN
-- add a column safely
IF NOT EXISTS( (SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE()
AND COLUMN_NAME='type' AND TABLE_NAME='region') ) THEN
ALTER TABLE region ADD type varchar(32) NOT NULL DEFAULT 'single';
ALTER TABLE region ADD type varchar(64) NOT NULL DEFAULT 'single';
ELSE
UPDATE region set type = "single" where id = -1;
END IF;
@ -96,7 +98,7 @@ BEGIN
END ;;
CALL add_regoion_type() ;;
CALL add_region_type() ;;
DELIMITER ;

View File

@ -886,17 +886,17 @@ definitions:
type: string
security_group_rules:
type: string
health_monitor:
health_monitors:
type: string
member:
members:
type: string
nat_instance:
type: string
pool:
pools:
type: string
route_table:
type: string
vip:
vips:
type: string
Quota:

View File

@ -153,3 +153,19 @@ authentication = {
"keystone_version": "2.0",
"policy_file": config.fms['policy_file'],
}
# valid_flavor_options
flavor_options = {
'valid_cpin_opt_values': [
'c2', 'c4'
],
'valid_stor_opt_values': [
's1', 's2'
],
'valid_vnf_opt_values': [
'v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'v7'
],
'valid_numa_values': ['n0'],
'valid_nd_vnf_values': ['v8'],
'valid_ss_vnf_values': ['v3']
}

View File

@ -1,11 +1,10 @@
import os
from orm.common.orm_common.policy import policy
from orm.services.flavor_manager.fms_rest.data import wsme
from orm.services.flavor_manager.fms_rest.logger import get_logger
from orm.services.flavor_manager.fms_rest.utils import authentication
from pecan.commands import CommandRunner
from pecan import make_app
logger = get_logger(__name__)
@ -27,8 +26,8 @@ def setup_app(config):
def main():
dir_name = os.path.dirname(__file__)
drive, path_and_file = os.path.splitdrive(dir_name)
path, filename = os.path.split(path_and_file)
runner = CommandRunner()
runner.run(['serve', path + '/config.py'])
runner.run(['serve', '../config.py'])
if __name__ == "__main__":
main()

View File

@ -2,6 +2,7 @@ from __future__ import absolute_import
from orm.common.orm_common.injector import injector
from orm.common.orm_common.utils import api_error_utils as err_utils
from orm.common.orm_common.utils import utils as common_utils
from orm.services.flavor_manager.fms_rest.controllers.v1.orm.flavors.os_extra_specs import OsExtraSpecsController
from orm.services.flavor_manager.fms_rest.controllers.v1.orm.flavors.regions import RegionController
from orm.services.flavor_manager.fms_rest.controllers.v1.orm.flavors.tags import TagsController
@ -11,7 +12,7 @@ from orm.services.flavor_manager.fms_rest.logger import get_logger
from orm.services.flavor_manager.fms_rest.logic.error_base import ErrorStatus
from orm.services.flavor_manager.fms_rest.utils import authentication
from pecan import request, rest
from pecan import conf, request, rest
from wsmeext.pecan import wsexpose
di = injector.get_di()
@ -31,21 +32,17 @@ class FlavorController(rest.RestController):
@wsexpose(FlavorWrapper, body=FlavorWrapper, rest_content_types='json', status_code=201)
def post(self, flavors):
flavor_logic, utils = di.resolver.unpack(FlavorController)
uuid = "FailedToGetFromUUIDGen"
uuid = ""
LOG.info("FlavorController - Createflavor: " + str(flavors))
authentication.authorize(request, 'flavor:create')
common_utils.set_utils_conf(conf)
try:
if not flavors.flavor.id:
uuid = utils.make_uuid()
else:
try:
uuid = utils.create_existing_uuid(
flavor_logic.get_fixed_uuid(flavors.flavor.id))
except TypeError:
LOG.error("UUID already exist")
raise ErrorStatus(409, 'UUID already exists')
try:
uuid = common_utils.create_or_validate_uuid(flavors.flavor.id, 'fmsId')
except TypeError:
LOG.error("UUID already exists")
raise ErrorStatus(409, 'UUID already exists')
result = flavor_logic.create_flavor(flavors, uuid, request.transaction_id)
@ -106,17 +103,20 @@ class FlavorController(rest.RestController):
status_code=500,
error_details=str(exception))
@wsexpose(FlavorListFullResponse, str, str, str, str, str, str, str, rest_content_types='json')
@wsexpose(FlavorListFullResponse, str, str, str, str, str, str, str,
str, str, rest_content_types='json')
def get_all(self, visibility=None, region=None, tenant=None, series=None,
starts_with=None, contains=None, alias=None):
vm_type=None, vnf_name=None, starts_with=None, contains=None,
alias=None):
flavor_logic, utils = di.resolver.unpack(FlavorController)
LOG.info("FlavorController - GetFlavorlist")
authentication.authorize(request, 'flavor:get_all')
try:
result = flavor_logic.get_flavor_list_by_params(visibility, region,
tenant, series, starts_with, contains, alias)
tenant, series,
vm_type, vnf_name,
starts_with, contains, alias)
return result
except ErrorStatus as exception:
LOG.log_exception("FlavorController - Failed to GetFlavorlist", exception)

View File

@ -1,5 +1,6 @@
from __future__ import absolute_import
from orm.common.orm_common.injector import injector
from orm.common.orm_common.utils import api_error_utils as err_utils
from orm.services.flavor_manager.fms_rest.data.wsme.models import RegionWrapper
@ -49,23 +50,30 @@ class RegionController(rest.RestController):
status_code=500,
error_details=str(exception))
@wsexpose(None, str, str, rest_content_types='json', status_code=204)
def delete(self, flavor_id, region_name):
@wsexpose(None, str, str, str, rest_content_types='json', status_code=204)
def delete(self, flavor_id, region_name, force_delete='False'):
if force_delete == 'True':
force_delete = True
else:
force_delete = False
flavor_logic, utils = di.resolver.unpack(RegionController)
requester = request.headers.get('X-RANGER-Requester')
is_rds_client_request = requester == 'rds_resource_service_proxy'
LOG.info("RegionController - Delete region:{0} by RDS Proxy: {1} ".format(region_name, is_rds_client_request))
LOG.info("RegionController - delete region: " + str(region_name))
authentication.authorize(request, 'flavor:delete_flavor_region')
try:
result = flavor_logic.delete_region(flavor_id, region_name, request.transaction_id)
result = flavor_logic.delete_region(flavor_id, region_name, request.transaction_id,
is_rds_client_request, force_delete)
LOG.info("RegionController - region deleted: " + str(result))
if is_rds_client_request:
LOG.info("RegionController - region deleted: " + str(result))
event_details = 'Flavor {} region {} deleted'.format(flavor_id,
region_name)
utils.audit_trail('delete region', request.transaction_id,
request.headers, flavor_id,
event_details=event_details)
event_details = 'Flavor {} region {} deleted'.format(flavor_id,
region_name)
utils.audit_trail('delete region', request.transaction_id,
request.headers, flavor_id,
event_details=event_details)
except ErrorStatus as exception:
LOG.log_exception("RegionController - Failed to delete region", exception)

View File

@ -24,7 +24,6 @@ LOG = logging.getLogger(__name__)
# event handling
def on_before_flush(session, flush_context, instances):
LOG.info("on_before_flush:", str(flush_context))
for model in session.new:
if hasattr(model, "validate"):
model.validate("new")

View File

@ -31,9 +31,9 @@ class FMSBaseModel(models.ModelBase):
class Flavor(Base, FMSBaseModel):
"""DataObject containing all the fields defined in Flavor table record.
'''Flavor is a DataObject contains all the fields defined in Flavor table record.
defined as SqlAlchemy model map to a table
"""
'''
__tablename__ = "flavor"
internal_id = Column(BigInteger, primary_key=True)
@ -187,7 +187,7 @@ class Flavor(Base, FMSBaseModel):
self.add_tags(flavor_tags)
except Exception as exception:
LOG.log_exception("Failed to add region {0} to flavor {1}".format(
LOG.log_exception("Failed to replace tags {0} to flavor {1}".format(
str(flavor_tags), str(self)), exception)
raise
@ -196,7 +196,7 @@ class Flavor(Base, FMSBaseModel):
LOG.debug("remove all tags from flavor {}".format(str(self)))
self.flavor_tags = []
except Exception as exception:
LOG.log_exception("Failed to remove all tags from flavor {1}".format(str(self)), exception)
LOG.log_exception("Failed to remove all tags from flavor {}".format(str(self)), exception)
raise
def remove_tag(self, tag_name):
@ -239,6 +239,7 @@ class Flavor(Base, FMSBaseModel):
raise
def remove_tenant(self, tenant_id):
deleted_flag = False
assert isinstance(tenant_id, basestring)
try:
LOG.debug("remove tenants {0} from flavor {1}".format(tenant_id,
@ -247,6 +248,12 @@ class Flavor(Base, FMSBaseModel):
for tenant in reversed(self.flavor_tenants):
if tenant.tenant_id == tenant_id:
self.flavor_tenants.remove(tenant)
deleted_flag = True
if not deleted_flag:
raise ErrorStatus(404,
"tenant {0} does not exist for flavor id {1}".format(
tenant_id, str(self.id)))
except Exception as exception:
LOG.log_exception(
@ -292,10 +299,9 @@ class Flavor(Base, FMSBaseModel):
deleted_flag = True
if not deleted_flag:
# no need to raise in delete not found
LOG.debug(
"Failed to remove extra_spec {0} from flavor id {1}".format(
extra_spec_key_name, str(self.id)))
raise ErrorStatus(404,
"extra spec {0} does not exist for flavor id {1}".format(
extra_spec_key_name, str(self.id)))
except ErrorStatus as e:
raise
@ -305,66 +311,6 @@ class Flavor(Base, FMSBaseModel):
"Failed to remove extra_spec {0} from flavor {1}".format(extra_spec_key_name, str(self)), exception)
raise
def add_tags(self, flavor_tags):
assert isinstance(flavor_tags, list) and all(isinstance(ft, FlavorTag) for ft in flavor_tags)
try:
LOG.debug("add tags {0} to flavor {1}".format(str(flavor_tags),
str(self)))
for tag in flavor_tags:
self.flavor_tags.append(tag)
except Exception as exception:
LOG.log_exception("Failed to add region {0} to flavor {1}".format(
str(flavor_tags), str(self)), exception)
raise
def replace_tags(self, flavor_tags):
assert isinstance(flavor_tags, list) and all(isinstance(ft, FlavorTag) for ft in flavor_tags)
try:
LOG.debug("replace tags {0} for flavor {1}".format(str(flavor_tags),
str(self)))
self.remove_all_tags()
self.add_tags(flavor_tags)
except Exception as exception:
LOG.log_exception("Failed to add region {0} to flavor {1}".format(
str(flavor_tags), str(self)), exception)
raise
def remove_all_tags(self):
try:
LOG.debug("remove all tags from flavor {}".format(str(self)))
self.flavor_tags = []
except Exception as exception:
LOG.log_exception("Failed to remove all tags from flavor {1}".format(str(self)), exception)
raise
def remove_tag(self, tag_name):
deleted_flag = False
assert isinstance(tag_name, basestring)
try:
LOG.debug("remove tag {0} from flavor {1}".format(tag_name,
str(self)))
for tag in reversed(self.flavor_tags):
if tag.key_name == tag_name:
self.flavor_tags.remove(tag)
deleted_flag = True
if not deleted_flag:
raise ErrorStatus(404,
"Failed to remove tag {0} from flavor id {1}".format(
tag_name, str(self.id)))
except ErrorStatus as e:
raise
except Exception as exception:
LOG.log_exception(
"Failed to remove tag {0} from flavor {1}".format(
tag_name, str(self)), exception)
raise
def validate(self, type):
''' type can be "new" or "dirty" - comes from event
'''
@ -456,8 +402,8 @@ class FlavorTag(Base, FMSBaseModel):
)
def __str__(self):
tag = "\"{0}\":\"{1}\"".format(self.key_name, self.key_value)
return tag
tags = "\"{0}\":\"{1}\"".format(self.key_name, self.key_value)
return tags
'''

View File

@ -1,5 +1,6 @@
from orm.services.flavor_manager.fms_rest.data.sql_alchemy.db_models import (Flavor, FlavorRegion,
from orm.services.flavor_manager.fms_rest.data.sql_alchemy.db_models import (Flavor,
FlavorRegion,
FlavorTag,
FlavorTenant)
from orm.services.flavor_manager.fms_rest.logger import get_logger
@ -148,6 +149,16 @@ class FlavorRecord:
LOG.log_exception(message, exception)
raise
def get_flavors_status_by_uuids(self, uuid_str):
results = self.session.connection().execute("SELECT resource_id, status from rds_resource_status_view"
" WHERE resource_id in ({})".format(uuid_str))
resource_status_dict = {}
if results:
resource_status_dict = dict((resource_id, status) for resource_id, status in results)
results.close()
return resource_status_dict
def get_flavors_by_criteria(self, **criteria):
try:
@ -156,6 +167,8 @@ class FlavorRecord:
region = criteria['region'] if 'region' in criteria else None
tenant = criteria['tenant'] if 'tenant' in criteria else None
series = criteria['series'] if 'series' in criteria else None
vm_type = criteria['vm_type'] if 'vm_type' in criteria else None
vnf_name = criteria['vnf_name'] if 'vnf_name' 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
alias = criteria['alias'] if 'alias' in criteria else None
@ -177,7 +190,14 @@ class FlavorRecord:
if tenant:
query = query.join(FlavorTenant).filter(FlavorTenant.flavor_internal_id == Flavor.internal_id,
FlavorTenant.tenant_id == tenant)
if vm_type:
query = query.join(FlavorTag).filter(FlavorTag.flavor_internal_id == Flavor.internal_id,
FlavorTag.key_name == 'vm_type',
FlavorTag.key_value == vm_type)
if vnf_name:
query = query.join(FlavorTag).filter(FlavorTag.flavor_internal_id == Flavor.internal_id,
FlavorTag.key_name == 'vnf_name',
FlavorTag.key_value == vnf_name)
if visibility:
query = query.filter(Flavor.visibility == visibility)

View File

@ -1,6 +1,8 @@
import wsme
from orm.common.orm_common.utils.cross_api_utils import set_utils_conf, get_regions_of_group
from orm.common.orm_common.utils.cross_api_utils import (set_utils_conf,
get_regions_of_group,
validate_description)
from orm.services.flavor_manager.fms_rest.data.sql_alchemy import db_models
from orm.services.flavor_manager.fms_rest.data.wsme.model import Model
from orm.services.flavor_manager.fms_rest.logic.error_base import ErrorStatus
@ -42,7 +44,6 @@ class ExtraSpecsWrapper(Model):
def to_db_model(self):
extra_spec = []
for key, value in self.os_extra_specs.iteritems():
if Flavor.ignore_extra_specs_input(key.replace(":", "____")):
continue
@ -164,7 +165,6 @@ class Flavor(Model):
visibility = wsme.wsattr(wsme.types.text, mandatory=True)
tenants = wsme.wsattr(wsme.types.ArrayType(str), mandatory=False)
status = wsme.wsattr(wsme.types.text, mandatory=False)
tags = wsme.wsattr(wsme.types.DictType(str, str), mandatory=False)
tag = wsme.wsattr(wsme.types.DictType(str, str), mandatory=False)
options = wsme.wsattr(wsme.types.DictType(str, str), mandatory=False)
extra_specs = wsme.wsattr(wsme.types.DictType(str, str), mandatory=False,
@ -182,7 +182,6 @@ class Flavor(Model):
swap="0",
ephemeral="0",
extra_specs={},
tags={},
tag={},
options={},
regions=[],
@ -199,7 +198,7 @@ class Flavor(Model):
:param vcpus:
:param disk: Disk in GB
:param swap: is optional and default is 0
:param ephemeral: is optional and default is 0
:param ephemeral: is optional and default is 0, size in GB
:param extra_spec: key-value dictionary
:param tags: key-value dictionary
:param options: key-value dictionary
@ -220,7 +219,6 @@ class Flavor(Model):
self.swap = swap
self.ephemeral = "0" if not ephemeral else ephemeral
self.extra_specs = extra_specs
self.tags = tags
self.tag = tag
self.options = options
self.regions = regions
@ -232,13 +230,20 @@ class Flavor(Model):
bundle = ['b1', 'b2']
numa = ['n0', 'n1']
vlan = ['v1', 'v2', 'v3', 'v4', 'v5', 'v6']
vcpu_limit = int(conf.flavor_limits.vcpu_limit)
vram_limit = int(conf.flavor_limits.vram_limit)
swap_file_limit = int(conf.flavor_limits.swap_file_limit)
ephemeral_limit = int(conf.flavor_limits.ephemeral_limit)
try:
isValid = validate_description(self.description)
if not isValid:
raise ErrorStatus(400, "Flavor description does not allow special characters :"
" only dashes, commas, and period allowed.")
if not self.ram.isdigit():
raise ErrorStatus(400, "ram must be a number")
if not self.vcpus.isdigit():
raise ErrorStatus(400, "vcpus must be a number")
if not self.disk.isdigit():
if not self.validInt(self.disk):
raise ErrorStatus(400, "disk must be a number")
if not self.swap.isdigit():
raise ErrorStatus(400, "swap must be a number")
@ -249,20 +254,24 @@ class Flavor(Model):
if self.series not in allowed_series:
raise ErrorStatus(400, "series possible values are {}".format(
allowed_series))
if int(self.ram) not in range(1024, 327680 + 1, 1024):
if int(self.ram) not in range(1024, vram_limit + 1, 1024):
raise ErrorStatus(400,
"ram value is out of range. Expected range is 1024(1GB)-327680(320GB) "
"and must be a multiple of 1024")
if int(self.vcpus) not in range(1, 48 + 1):
raise ErrorStatus(400, "vcpus value is out of range. Expected range is 1-48")
"ram value is out of range. Expected range is 1024(1GB)-"
"%6d(%3dGB) and must be a multiple of 1024" %
(vram_limit, vram_limit / 1024))
if int(self.vcpus) not in range(1, vcpu_limit + 1):
raise ErrorStatus(400, "vcpus value is out of range. Expected range is 1-"
"%2d" % (vcpu_limit))
if int(self.disk) < 0:
raise ErrorStatus(400, "disk must be a non negative number")
if int(self.ephemeral) not in range(0, 320 + 1):
raise ErrorStatus(400, "ephemeral value is out of range. Expected range is 0-320")
if int(self.swap) not in range(0, 327680 + 1, 1024):
raise ErrorStatus(400, "disk cannot be less than zero")
if int(self.ephemeral) not in range(0, ephemeral_limit + 1):
raise ErrorStatus(400, "ephemeral value is out of range. Expected range is 0-"
"%5d(%2dTB)" % (ephemeral_limit, ephemeral_limit / 1000))
if int(self.swap) not in range(0, swap_file_limit + 1, 1024):
raise ErrorStatus(400,
"swap value is out of range. Expected range is 0-327680(320GB) "
"and must be a multiple of 1024")
"swap value is out of range. Expected range is 0-"
"%6d(%3dGB) and must be a multiple of 1024" %
(swap_file_limit, swap_file_limit / 1024))
except ValueError:
raise ErrorStatus(400, "ram, vcpus, disk, ephemeral and swap must be integers")
for symbol, value in self.extra_specs.iteritems():
@ -284,13 +293,6 @@ class Flavor(Model):
"region type \'group\' is invalid in this "
"action, \'group\' can be only in create flavor action")
# check if user entered tag instead of tags
if self.tags and self.tag:
raise ErrorStatus(400, "you entered \'tag\' and \'tags\' arguments, "
"please remove the \'tag\'")
if self.tag and not self.tags:
self.tags = self.tag
def to_db_model(self):
flavor = db_models.Flavor()
extra_spec = []
@ -310,7 +312,7 @@ class Flavor(Model):
if self.series:
extra_spec.extend(self.get_extra_spec_needed())
for symbol, value in self.tags.iteritems():
for symbol, value in self.tag.iteritems():
tag = db_models.FlavorTag()
tag.key_name = symbol
tag.key_value = value
@ -389,7 +391,7 @@ class Flavor(Model):
flavor.extra_specs[extra_spec.key_name] = extra_spec.key_value
for tag in sql_flavor.flavor_tags:
flavor.tags[tag.key_name] = tag.key_value
flavor.tag[tag.key_name] = tag.key_value
for option in sql_flavor.flavor_options:
flavor.options[option.key_name] = option.key_value
@ -406,38 +408,52 @@ class Flavor(Model):
return False
def get_extra_spec_needed(self):
valid_vnf_opts = conf.flavor_options.valid_vnf_opt_values[:]
valid_stor_opts = conf.flavor_options.valid_stor_opt_values[:]
valid_cpin_opts = conf.flavor_options.valid_cpin_opt_values[:]
extra_spec_needed = []
items = conf.extra_spec_needed_table.to_dict()
for symbol, value in items[self.series].iteritems():
es = db_models.FlavorExtraSpec()
es.key_name = symbol.replace("____", ":")
es.key_value = value
# update extra_spec default values as needed
if self.series == "gv" and "c2" in es.key_name:
if "c4" in self.options and self.options['c4'].lower() == "true":
es.key_name = es.key_name.replace("c2", "c4")
elif self.series == "ss" and "s1" in es.key_name:
if "s2" in self.options and self.options['s2'].lower() == "true":
es.key_name = es.key_name.replace("s1", "s2")
extra_spec_needed.append(es)
options_items = self.options
# check some keys if they exist in option add values to extra specs
if len(options_items) > 0 and self.series in ('ns', 'nv', 'nd'):
if self.series in ('ns', 'nv', 'nd', 'ss'):
c2_c4_in = False
n0_in = False
for symbol, value in options_items.iteritems():
es = db_models.FlavorExtraSpec()
es.key_name = "aggregate_instance_extra_specs:%s" % symbol
es.key_value = "true"
# format numa node extra spec as appropriate
if symbol == "n0" and options_items[symbol].lower() == "true":
n0_in = True
es.key_value = 2
es.key_name = "hw:numa_nodes"
extra_spec_needed.append(es)
elif symbol in ('c2', 'c4') and options_items[symbol].lower() == "true":
# format cpu pinnin extra spec as appropriate
elif symbol in valid_cpin_opts and options_items[symbol].lower() == "true":
c2_c4_in = True
extra_spec_needed.append(es)
# format vnf profile extra spec as appropriate
try:
if len(symbol) == 2 and symbol[0] == 'v' and 0 < int(symbol[1]) < 9 and options_items[symbol].lower() == "true":
if self.series == 'ns' and symbol in valid_vnf_opts and options_items[symbol].lower() == "true":
extra_spec_needed.append(es)
except Exception:
pass
# if c4, c2 and n0 not in options keys add these values to extra specs
if not c2_c4_in:
es = db_models.FlavorExtraSpec()
@ -449,6 +465,33 @@ class Flavor(Model):
es.key_value = 1
es.key_name = "hw:numa_nodes"
extra_spec_needed.append(es)
if {'v5', 'i1'}.issubset(options_items.keys()):
es = db_models.FlavorExtraSpec()
es.key_name = "hw:cpu_sockets"
es.key_value = "1"
extra_spec_needed.append(es)
es = db_models.FlavorExtraSpec()
es.key_name = "hw:cpu_threads"
es.key_value = "1"
extra_spec_needed.append(es)
es = db_models.FlavorExtraSpec()
es.key_name = "hw:pci_numa_custom_policy"
es.key_value = "ignore"
extra_spec_needed.append(es)
es = db_models.FlavorExtraSpec()
es.key_name = "hw:cpu_cores"
es.key_value = self.vcpus
extra_spec_needed.append(es)
# convert the key_value to a string to avoid/fix pecan json rendering error in update extra_specs
i = 0
while i < len(extra_spec_needed):
extra_spec_needed[i].key_value = str(extra_spec_needed[i].key_value)
i += 1
return extra_spec_needed
def get_as_summary_dict(self):
@ -478,6 +521,13 @@ class Flavor(Model):
regions = get_regions_of_group(group_name)
return regions
def validInt(self, check_value):
try:
int(check_value)
except ValueError:
return False
return True
class FlavorWrapper(Model):
"""flavor model

View File

@ -1,10 +1,11 @@
{
"default": "!",
"admin": "role:admin",
"admin_support": "role:admin_support",
"admin_viewer": "role:admin_viewer",
"admin_or_support": "role:admin or role:admin_support",
"admin": "role:admin and tenant:admin or role:admin and tenant:services",
"admin_support": "role:admin_support and tenant:admin or role:admin_support and tenant:services",
"admin_viewer": "role:admin_viewer and tenant:admin or role:admin_viewer and tenant:services",
"admin_or_support": "rule:admin or rule:admin_support",
"admin_or_support_or_viewer": "rule:admin or rule:admin_support or rule:admin_viewer",
"flavor:create": "rule:admin_or_support",
@ -12,9 +13,9 @@
"flavor:get_all": "rule:admin_or_support_or_viewer",
"flavor:delete": "rule:admin",
"flavor:get_flavor_extra_specs": "rule:admin",
"flavor:get_flavor_extra_specs": "rule:admin_or_support_or_viewer",
"flavor:add_flavor_extra_specs": "rule:admin_or_support",
"flavor:replace_flavor_extra_specs": "rule:admin_or_support",
"flavor:replace_flavor_extra_specs": "rule:admin",
"flavor:delete_flavor_extra_specs": "rule:admin",
"flavor:add_flavor_regions": "rule:admin_or_support",
@ -22,7 +23,7 @@
"flavor:get_flavor_tags": "rule:admin_or_support_or_viewer",
"flavor:add_flavor_tags": "rule:admin_or_support",
"flavor:replace_flavor_tags": "rule:admin_or_support",
"flavor:replace_flavor_tags": "rule:admin",
"flavor:delete_flavor_tags": "rule:admin",
"flavor:add_flavor_tenants": "rule:admin_or_support",

View File

@ -1,5 +1,3 @@
import uuid
from orm.services.flavor_manager.fms_rest.data.sql_alchemy.db_models import FlavorRegion, FlavorTenant
from orm.services.flavor_manager.fms_rest.data.wsme.models import (ExtraSpecsWrapper, Flavor,
FlavorListFullResponse, FlavorWrapper,
@ -9,6 +7,8 @@ from orm.services.flavor_manager.fms_rest.logger import get_logger
from orm.services.flavor_manager.fms_rest.logic.error_base import ConflictError, ErrorStatus, NotFoundError
from orm.common.orm_common.injector import injector
from pecan import conf
LOG = get_logger(__name__)
di = injector.get_di()
@ -18,7 +18,6 @@ di = injector.get_di()
def create_flavor(flavor, flavor_uuid, transaction_id):
DataManager = di.resolver.unpack(create_flavor)
datamanager = DataManager()
try:
flavor.flavor.handle_region_groups()
flavor.flavor.validate_model("create")
@ -120,9 +119,7 @@ def delete_flavor_by_uuid(flavor_uuid): # , transaction_id):
sql_flavor = flavor_rec.get_flavor_by_id(flavor_uuid)
if sql_flavor is None:
# The flavor does not exist, so the delete operation is
# considered successful
return
raise NotFoundError(message="Flavor '{}' not found".format(flavor_uuid))
existing_region_names = sql_flavor.get_existing_region_names()
if len(existing_region_names) > 0:
@ -228,33 +225,43 @@ def add_regions(flavor_uuid, regions, transaction_id):
@di.dependsOn('data_manager')
def delete_region(flavor_uuid, region_name, transaction_id):
def delete_region(flavor_uuid, region_name, transaction_id, on_success_by_rds,
force_delete):
DataManager = di.resolver.unpack(delete_region)
datamanager = DataManager()
try:
flavor_rec = datamanager.get_record('flavor')
sql_flavor = flavor_rec.get_flavor_by_id(flavor_uuid)
if not sql_flavor and on_success_by_rds:
return
if not sql_flavor:
raise ErrorStatus(404, 'flavor id {0} not found'.format(flavor_uuid))
existing_region_names = sql_flavor.get_existing_region_names()
sql_flavor.remove_region(region_name)
datamanager.flush() # i want to get any exception created by previous actions against the database
send_to_rds_if_needed(sql_flavor, existing_region_names, "put", transaction_id)
datamanager.commit()
datamanager.flush() # Get any exception created by previous actions against the database
if on_success_by_rds:
datamanager.commit()
else:
send_to_rds_if_needed(sql_flavor, existing_region_names, "put",
transaction_id)
if force_delete:
datamanager.commit()
else:
datamanager.rollback()
except ErrorStatus as exp:
LOG.log_exception("FlavorLogic - Failed to update flavor", exp)
datamanager.rollback()
raise exp
except Exception as exp:
LOG.log_exception("FlavorLogic - Failed to delete region", exp)
datamanager.rollback()
raise exp
finally:
datamanager.close()
@ -328,11 +335,18 @@ def delete_tenant(flavor_uuid, tenant_id, transaction_id):
datamanager.flush() # i want to get any exception created by previous actions against the database
send_to_rds_if_needed(sql_flavor, existing_region_names, "put", transaction_id)
datamanager.commit()
except ErrorStatus as exp:
LOG.log_exception("FlavorLogic - Failed to update flavor", exp)
except NotFoundError as exp:
datamanager.rollback()
LOG.log_exception("FlavorLogic - Flavor not found", exp)
raise
except ErrorStatus as exp:
datamanager.rollback()
if exp.status_code == 404:
LOG.log_exception("FlavorLogic - Tenant not found", exp)
raise
else:
LOG.log_exception("FlavorLogic - failed to delete tenant", exp)
raise
except Exception as exp:
LOG.log_exception("FlavorLogic - Failed to delete tenant", exp)
datamanager.rollback()
@ -424,8 +438,12 @@ def delete_extra_specs(flavor_id, transaction_id, extra_spec=None):
except ErrorStatus as exp:
datamanager.rollback()
LOG.log_exception("error in adding extra specs", exp)
raise
if exp.status_code == 404:
LOG.log_exception("FlavorLogic - extra specs not found", exp)
raise
else:
LOG.log_exception("FlavorLogic - failed to delete extra specs", exp)
raise
except Exception as exp:
datamanager.rollback()
@ -487,8 +505,7 @@ def delete_tags(flavor_id, tag, transaction_id):
except ErrorStatus as exp:
if exp.status_code == 404:
LOG.log_exception("FlavorLogic - Tag not found", exp)
# Do not raise an exception if the tag was not found
return
raise
else:
LOG.log_exception("FlavorLogic - failed to delete tags", exp)
raise
@ -702,7 +719,6 @@ def get_flavor_by_uuid_or_name(flavor_uuid_or_name):
DataManager, rds_proxy = di.resolver.unpack(get_flavor_by_uuid)
datamanager = DataManager()
try:
flavor_record = datamanager.get_record('flavor')
@ -727,33 +743,46 @@ def get_flavor_by_uuid_or_name(flavor_uuid_or_name):
@di.dependsOn('rds_proxy')
def update_region_statuses(flavor, sql_flavor):
rds_proxy = di.resolver.unpack(update_region_statuses)
# remove the regions comes from database and return the regions which return from rds,
# because there might be group region there (in the db) and in the response from the
# rds we will have a list of all regions belong to this group
flavor.regions[:] = []
resp = rds_proxy.get_status(sql_flavor.id)
if resp.status_code == 200:
status_resp = resp.json()
if sql_flavor.flavor_regions and len(sql_flavor.flavor_regions) > 0:
if 'regions' in status_resp.keys():
for region_status in status_resp['regions']:
flavor.regions.append(
Region(name=region_status['region'], type="single",
status=region_status['status'],
error_message=region_status['error_msg']))
rds_status_resp = resp.json()
# store all regions for the flavor in the flavor_regions_list
flavor_regions_list = []
for region_data in sql_flavor.flavor_regions:
flavor_regions_list.append(region_data.region_name)
# get region status if region in flavor_regions_list
if flavor_regions_list and 'regions' in rds_status_resp.keys():
for rds_region_status in rds_status_resp['regions']:
# check that the region read from RDS is in the flavor_regions_list
if rds_region_status['region'] in flavor_regions_list:
flavor.regions.append(
Region(name=rds_region_status['region'], type="single",
status=rds_region_status['status'],
error_message=rds_region_status['error_msg']))
if 'status' in rds_status_resp.keys():
# if flavor not assigned to region set flavor.status to 'no regions'
if flavor_regions_list:
flavor.status = rds_status_resp['status']
else:
flavor.status = 'no regions'
if 'status' in status_resp.keys():
flavor.status = status_resp['status']
elif resp.status_code == 404:
flavor.status = "Success"
# flavor id not in rds resource_status table as no region is assigned
flavor.status = "no regions"
else:
flavor.status = "N/A"
@di.dependsOn('data_manager')
@di.dependsOn('rds_proxy')
def get_flavor_list_by_params(visibility, region, tenant, series, starts_with, contains, alias):
def get_flavor_list_by_params(visibility, region, tenant, series, vm_type,
vnf_name, starts_with, contains, alias):
DataManager, rds_proxy = di.resolver.unpack(get_flavor_list_by_params)
datamanager = DataManager()
@ -764,15 +793,25 @@ def get_flavor_list_by_params(visibility, region, tenant, series, starts_with, c
region=region,
tenant=tenant,
series=series,
vm_type=vm_type,
vnf_name=vnf_name,
starts_with=starts_with,
contains=contains,
alias=alias)
response = FlavorListFullResponse()
for sql_flavor in sql_flavors:
flavor = Flavor.from_db_model(sql_flavor)
update_region_statuses(flavor, sql_flavor)
response.flavors.append(flavor)
if sql_flavors:
uuids = ','.join(str("\'" + sql_flavor.id + "\'")
for sql_flavor in sql_flavors if sql_flavor and sql_flavor.id)
resource_status_dict = flavor_record.get_flavors_status_by_uuids(uuids)
for sql_flavor in sql_flavors:
flavor = Flavor.from_db_model(sql_flavor)
if sql_flavor.id:
status = resource_status_dict.get(sql_flavor.id)
flavor.status = not status and 'no regions' or status
response.flavors.append(flavor)
except Exception as exp:
LOG.log_exception("Fail to get_flavor_list_by_params", exp)
raise
@ -783,10 +822,18 @@ def get_flavor_list_by_params(visibility, region, tenant, series, starts_with, c
def calculate_name(flavor):
valid_vnf_opts = conf.flavor_options.valid_vnf_opt_values[:]
valid_stor_opts = conf.flavor_options.valid_stor_opt_values[:]
valid_cpin_opts = conf.flavor_options.valid_cpin_opt_values[:]
valid_nd_vnf_opts = conf.flavor_options.valid_nd_vnf_values[:]
valid_numa_opts = conf.flavor_options.valid_numa_values[:]
valid_ss_vnf_opts = conf.flavor_options.valid_ss_vnf_values[:]
name = "{0}.c{1}r{2}d{3}".format(flavor.flavor.series, flavor.flavor.vcpus,
int(flavor.flavor.ram) / 1024,
flavor.flavor.disk)
series = name[:2]
swap = getattr(flavor.flavor, 'swap', 0)
if swap and int(swap):
name += '{}{}'.format('s', int(swap) / 1024)
@ -796,9 +843,23 @@ def calculate_name(flavor):
name += '{}{}'.format('e', ephemeral)
if len(flavor.flavor.options) > 0:
name += '.'
for key in sorted(flavor.flavor.options.iterkeys()):
name += key
# only include valid option parameters in flavor name
if ((series == 'nd' and key[0] == 'v' and key in valid_nd_vnf_opts) or
(series == 'ns' and key[0] == 'v' and key in valid_vnf_opts) or
(series == 'ss' and key[0] == 'v' and key in valid_ss_vnf_opts) or
(key[0] == 'n' and key in valid_numa_opts) or
(key[0] == 's' and key in valid_stor_opts) or
(key[0] == 'c' and key in valid_cpin_opts)):
if name.count('.') < 2:
name += '.'
name += key
if key == 'v5':
for k in flavor.flavor.options.iterkeys():
if k == 'i1':
name += k
return name
@ -833,17 +894,3 @@ def region_name_exist_in_regions(region_name, regions):
def set_regions_action(flavor_dict, action):
for region in flavor_dict["regions"]:
region["action"] = action
def get_fixed_uuid(uuid_to_fix):
"""Fix a version 4 UUID."""
try:
new_uuid = uuid.UUID(uuid_to_fix, version=4)
if (uuid_to_fix == new_uuid.hex) or (uuid_to_fix == str(new_uuid)):
# It is a version 4 UUID, remove its dashes
return new_uuid.hex
except ValueError:
# Not a UUID (of any version)
pass
raise ErrorStatus(400, 'Flavor ID must be a version 4 UUID!')

View File

@ -1,12 +1,10 @@
from oslo_config import cfg
from orm import base_config as config
CONF = cfg.CONF
# Server Specific Configurations
server = {
'port': CONF.uuid.port,
'host': CONF.api.host
'port': config.uuid['port'],
'host': config.orm_host
}
# Pecan Application Configurations
app = {
@ -15,10 +13,9 @@ app = {
'debug': True,
}
verify = CONF.api.ssl_verify
verify = config.ssl_verify
database = {
'connection_string': CONF.database.connection + '/orm'
'connection_string': config.db_url + 'orm'
}
# Custom Configurations must be in Python dictionary format::
#

View File

@ -1,26 +1,14 @@
import os
from oslo_log import log as logging
from pecan.commands import CommandRunner
import logging
from pecan import make_app
LOG = logging.getLogger(__name__)
logger = logging.getLogger(__name__)
def setup_app(config):
app_conf = dict(config.app)
app = make_app(app_conf.pop('root'),
logging=getattr(config, 'logging', {}),
**app_conf)
LOG.info('Starting uuidgen...')
logger.info('Starting uuidgen...')
return app
def main():
dir_name = os.path.dirname(__file__)
drive, path_and_file = os.path.splitdrive(dir_name)
path, filename = os.path.split(path_and_file)
runner = CommandRunner()
runner.run(['serve', path + '/config.py'])

View File

@ -1,11 +1,13 @@
import datetime
import logging
import re
import uuid
from orm.services.id_generator.uuidgen.db.db_manager import DBManager
from pecan import expose, response
from pecan.rest import RestController
from orm.services.id_generator.uuidgen.db.db_manager import DBManager
LOG = logging.getLogger(__name__)
@ -22,8 +24,7 @@ def respond(reason, code, message):
class UUIDController(RestController):
@expose(template='json')
def post(self, **kw):
"""Method to handle POST /v1/uuids
create and return a new uuid
"""Method to handle POST /v1/uuids - create and return a new uuid
prameters:
uuid_type (optional)
return: dict describing success or failure of post command
@ -45,18 +46,23 @@ class UUIDController(RestController):
LOG.info("UUIDController.post - " + str(messageToReturn))
return messageToReturn
if not customer_id:
if not customer_id or customer_id == 'Unset':
return self.create_new_uuid(uuid_type)
return self.validate_and_add_uuid(customer_id)
if not re.match(r'^[A-Za-z0-9]+$', customer_id):
response.status = 400
messageToReturn = respond("badRequest", 400, "Only alphanumeric characters allowed!")
LOG.info("UUIDController.post - " + str(messageToReturn))
return messageToReturn
def validate_and_add_uuid(self, customer_id):
return self.validate_and_add_uuid(customer_id, uuid_type)
def validate_and_add_uuid(self, uuid, uuid_type):
try:
uuid_type = "custId"
db_manager = DBManager()
db_manager.create_uuid(customer_id, uuid_type)
db_manager.create_uuid(uuid, uuid_type)
return {
"uuid": customer_id,
"uuid": uuid,
"issued_at": datetime.datetime.utcnow().isoformat() + 'Z',
"uuid_type": uuid_type
}
@ -65,13 +71,15 @@ class UUIDController(RestController):
# we just need to save it in the database that we will not give this value in the future requests
# but we don't need to throw exception if already exist, this is not our responsible
# if it is duplicate uuid it will fail in the service which uses this uuid (cms, fms)
if e.orig.args[0] != 1062:
if e.inner_exception.orig[0] == 1062:
LOG.info("Duplicate UUID=" + uuid)
else:
response.status = 500
messageToReturn = respond("badRequest", 500, 'Database error')
LOG.error(str(messageToReturn) + "Exception: " + str(e))
return messageToReturn
return {
"uuid": customer_id,
"uuid": uuid,
"issued_at": datetime.datetime.utcnow().isoformat() + 'Z',
"uuid_type": uuid_type
}

View File

@ -10,7 +10,6 @@ logger = logging.getLogger(__name__)
class DBManager(object):
def __init__(self, connection_string=None):
if not connection_string:
connection_string = conf.database.connection_string

View File

@ -1,5 +1,3 @@
import os
from orm.common.orm_common.policy import policy
from orm.common.orm_common.utils.utils import set_utils_conf
from orm.services.image_manager.ims.logger import get_logger
@ -29,8 +27,8 @@ def setup_app(config):
def main():
dir_name = os.path.dirname(__file__)
drive, path_and_file = os.path.splitdrive(dir_name)
path, filename = os.path.split(path_and_file)
runner = CommandRunner()
runner.run(['serve', path + '/config.py'])
runner.run(['serve', '../config.py'])
if __name__ == "__main__":
main()

View File

@ -1,11 +0,0 @@
"""Init package."""
import os
from orm.common.orm_common.injector import injector
import orm.services.image_manager.ims.di_providers as di_providers
from orm.services.image_manager.ims.logger import get_logger
logger = get_logger(__name__)
_current_dirname = os.path.dirname(os.path.realpath(di_providers.__file__))
injector.register_providers('IMS_ENV', _current_dirname, logger)

View File

@ -43,13 +43,10 @@ class ImageController(rest.RestController):
LOG.info("ImageController - Create image: " + str(image_wrapper.image.name))
image_wrapper.image.owner = request.headers.get('X-RANGER-Owner') or ''
if not image_wrapper.image.id:
uuid = utils.make_uuid()
else:
try:
uuid = utils.create_existing_uuid(image_wrapper.id)
except TypeError:
raise ErrorStatus(409.1, message='Image UUID already exists')
try:
uuid = utils.create_or_validate_uuid(image_wrapper.image.id, 'imsId')
except TypeError:
raise ErrorStatus(409.1, message='Image UUID already exists')
try:
ret_image = image_logic.create_image(image_wrapper, uuid,
@ -125,7 +122,7 @@ class ImageController(rest.RestController):
auth.authorize(request, "image:get_one")
try:
return image_logic.get_image_by_uuid(image_uuid)
return image_logic.get_image_by_uuid(image_uuid, query_by_id_or_name=True)
except ErrorStatus as exception:
LOG.log_exception("ImageController - Failed to GetImageDetails", exception)
@ -140,14 +137,14 @@ class ImageController(rest.RestController):
error_details=str(exception))
@wsexpose(ImageSummaryResponse, str, str, str, rest_content_types='json')
def get_all(self, visibility=None, region=None, tenant=None):
def get_all(self, visibility=None, region=None, customer=None):
image_logic, utils = di.resolver.unpack(ImageController)
auth.authorize(request, "image:list")
try:
LOG.info("ImageController - GetImagelist")
result = image_logic.get_image_list_by_params(visibility, region, tenant)
result = image_logic.get_image_list_by_params(visibility, region, customer)
return result
except ErrorStatus as exception:

View File

@ -90,22 +90,28 @@ class RegionController(rest.RestController):
status_code=500,
error_details=exception.message)
@wsexpose(None, str, str, rest_content_types='json', status_code=204)
def delete(self, image_id, region_name):
@wsexpose(None, str, str, str, rest_content_types='json', status_code=204)
def delete(self, image_id, region_name, force_delete='False'):
if force_delete == 'True':
force_delete = True
else:
force_delete = False
image_logic, utils = di.resolver.unpack(RegionController)
auth.authorize(request, "region:delete")
try:
LOG.info("RegionController - delete region: " + str(region_name))
requester = request.headers.get('X-RANGER-Requester')
is_rds_client_request = requester == 'rds_resource_service_proxy'
LOG.info("RegionController - Delete region:{0} by RDS Proxy: {1} ".format(region_name, is_rds_client_request))
result = image_logic.delete_region(image_id, region_name, request.transaction_id, is_rds_client_request,
force_delete)
if is_rds_client_request:
LOG.info("RegionController - region deleted: " + str(result))
result = image_logic.delete_region(image_id, region_name, request.transaction_id)
LOG.info("RegionController - region deleted: " + str(result))
event_details = 'Image {} region {} deleted'.format(image_id,
region_name)
utils.audit_trail('delete region', request.transaction_id,
request.headers, image_id,
event_details=event_details)
event_details = 'Image {} region {} deleted'.format(image_id,
region_name)
utils.audit_trail('delete region', request.transaction_id,
request.headers, image_id,
event_details=event_details)
except ErrorStatus as exception: # include NotFoundError
LOG.log_exception("RegionController - Failed to delete region", exception)

View File

@ -1,25 +1,27 @@
{
"default": "!",
"admin": "role:admin",
"admin_support": "role:admin_support",
"admin_viewer": "role:admin_viewer",
"orm": "user:m01687",
"default": "!",
"admin_or_support": "role:admin or role:admin_support",
"admin_or_support_or_viewer": "rule:admin or rule:admin_support or rule:admin_viewer",
"admin": "role:admin and tenant:admin or role:admin and tenant:services",
"admin_support": "role:admin_support and tenant:admin or role:admin_support and tenant:services",
"admin_viewer": "role:admin_viewer and tenant:admin or role:admin_viewer and tenant:services",
"image:create": "rule:admin_or_support",
"image:list": "rule:admin_or_support_or_viewer",
"image:get_one": "rule:admin_or_support_or_viewer",
"image:update": "rule:admin",
"image:delete": "rule:admin",
"region:delete": "rule:admin",
"region:create": "rule:admin_or_support",
"region:update": "rule:admin",
"image:enable": "rule:admin",
"tenant:create": "rule:admin_or_support",
"tenant:delete": "rule:admin",
"tenant:update": "rule:admin",
"admin_or_support": "rule:admin or rule:admin_support",
"admin_or_support_or_viewer": "rule:admin or rule:admin_support or rule:admin_viewer",
"metadata:create": "rule:orm"
"image:create": "rule:admin_or_support",
"image:list": "rule:admin_or_support_or_viewer",
"image:get_one": "rule:admin_or_support_or_viewer",
"image:update": "rule:admin",
"image:delete": "rule:admin",
"image:enable": "rule:admin",
"region:create": "rule:admin_or_support",
"region:update": "rule:admin",
"region:delete": "rule:admin",
"tenant:create": "rule:admin_or_support",
"tenant:update": "rule:admin",
"tenant:delete": "rule:admin",
"metadata:create": "rule:admin_or_support"
}

View File

@ -78,8 +78,6 @@ def update_image(image_wrapper, image_uuid, transaction_id, http_action="put"):
new_image = image_wrapper.to_db_model()
new_image.id = image_uuid
datamanager.begin_transaction()
image_rec = datamanager.get_record('image')
sql_image = image_rec.get_image_by_id(image_uuid)
@ -88,6 +86,10 @@ def update_image(image_wrapper, image_uuid, transaction_id, http_action="put"):
message="Image {0} does not exist for update".format(
image_uuid))
image_wrapper.validate_update(sql_image, new_image)
datamanager.begin_transaction()
new_image.owner = sql_image.owner
existing_regions = sql_image.get_existing_region_names()
new_image.created_at = int(sql_image.created_at)
@ -126,7 +128,7 @@ def delete_image_by_uuid(image_uuid, transaction_id):
sql_image = image_rec.get_image_by_id(image_uuid)
if sql_image is None:
return
raise NotFoundError(message="Image '{}' not found".format(image_uuid))
image_existing_region_names = sql_image.get_existing_region_names()
if len(image_existing_region_names) > 0:
@ -254,27 +256,39 @@ def replace_regions(image_uuid, regions, transaction_id):
@di.dependsOn('data_manager')
def delete_region(image_uuid, region_name, transaction_id):
def delete_region(image_uuid, region_name, transaction_id, on_success_by_rds,
force_delete):
DataManager = di.resolver.unpack(delete_region)
datamanager = DataManager()
try:
image_rec = datamanager.get_record('image')
sql_image = image_rec.get_image_by_id(image_uuid)
if on_success_by_rds and not sql_image:
return
if not sql_image:
raise ErrorStatus(404, 'image with id: {0} not found'.format(
image_uuid))
image_uuid))
# do not allow delete_region for protected images
if sql_image.protected:
protect_msg = "Protected image {} cannot be deleted. Please " \
"update image with protected=false and try again"
raise ErrorStatus(400, protect_msg.format(image_uuid))
existing_region_names = sql_image.get_existing_region_names()
sql_image.remove_region(region_name)
datamanager.flush() # i want to get any exception created by
datamanager.flush() # Get any exception created by
# previous actions against the database
send_to_rds_if_needed(sql_image, existing_region_names, "put",
transaction_id)
datamanager.commit()
if on_success_by_rds:
datamanager.commit()
else:
send_to_rds_if_needed(sql_image, existing_region_names, "put",
transaction_id)
if force_delete:
datamanager.commit()
else:
datamanager.rollback()
except ErrorStatus as exp:
LOG.log_exception("ImageLogic - Failed to update image", exp)
@ -286,6 +300,9 @@ def delete_region(image_uuid, region_name, transaction_id):
datamanager.rollback()
raise
finally:
datamanager.close()
@di.dependsOn('data_manager')
def add_customers(image_uuid, customers, transaction_id):
@ -399,7 +416,12 @@ def delete_customer(image_uuid, customer_id, transaction_id):
@di.dependsOn('data_manager')
@di.dependsOn('rds_proxy')
def get_image_by_uuid(image_uuid):
def get_image_by_uuid(image_uuid, query_by_id_or_name=False):
"""This function includes an optional boolean parameter "query_by_id_or_name".
If query_by_id_or_name evaluates to true, IMS logic will fetch the image
record whose "image_uuid" parameter value matches either the image id or name value.
Otherwise it defaults to query by image ID value only.
"""
DataManager, rds_proxy = di.resolver.unpack(get_image_by_uuid)
datamanager = DataManager()
@ -407,10 +429,14 @@ def get_image_by_uuid(image_uuid):
try:
datamanager.begin_transaction()
image_rec = datamanager.get_record('image')
sql_image = image_rec.get_image_by_id(image_uuid)
# Only the get_image API will pass the optional parameter and set it to true
if query_by_id_or_name:
sql_image = image_rec.get_image(image_uuid)
else:
# all other image APIs will NOT pass the optional parameter
sql_image = image_rec.get_image_by_id(image_uuid)
if not sql_image:
raise NotFoundError(status_code=404,
message="Image {0} not found ".format(
@ -428,15 +454,28 @@ def get_image_by_uuid(image_uuid):
# Get the status from RDS
image_status = rds_proxy.get_status(image_wrapper.image.id, False)
if image_status.status_code != 200:
return image_wrapper
image_status = image_status.json()
image_wrapper.image.status = image_status['status']
# update status for all regions
for result_regions in image_wrapper.image.regions:
for status_region in image_status['regions']:
if result_regions.name == status_region['region']:
result_regions.status = status_region['status']
if image_status.status_code == 404:
# image not on rds resource table - applicable to images created with no region assigned
image_wrapper.image.status = 'no regions'
elif image_status.status_code == 200:
image_status = image_status.json()
if image_wrapper.image.regions:
image_wrapper.image.status = image_status['status']
else:
image_wrapper.image.status = 'no regions'
# update status for all regions
for result_regions in image_wrapper.image.regions:
for status_region in image_status['regions']:
if result_regions.name == status_region['region']:
result_regions.status = status_region['status']
if status_region['error_msg']:
result_regions.set_error_message(status_region['error_msg'])
# status codes not falling under 404 (not found) or 200 (success)
else:
raise ErrorStatus(500, "unsuccessful GET - failed to get status for this resource")
except NotFoundError as exp:
datamanager.rollback()
@ -452,8 +491,9 @@ def get_image_by_uuid(image_uuid):
@di.dependsOn('data_manager')
@di.dependsOn('rds_proxy')
def get_image_list_by_params(visibility, region, Customer):
DataManager = di.resolver.unpack(get_image_list_by_params)
DataManager, rds_proxy = di.resolver.unpack(get_image_list_by_params)
datamanager = DataManager()
try:
@ -463,10 +503,17 @@ def get_image_list_by_params(visibility, region, Customer):
Customer=Customer)
response = ImageSummaryResponse()
for sql_image in sql_images:
image = ImageSummary.from_db_model(sql_image)
response.images.append(image)
if sql_images:
uuids = ','.join(str("\'" + sql_image.id + "\'")
for sql_image in sql_images if sql_image and sql_image.id)
resource_status_dict = image_record.get_images_status_by_uuids(uuids)
for sql_image in sql_images:
image = ImageSummary.from_db_model(sql_image)
if sql_image.id:
status = resource_status_dict.get(sql_image.id)
image.status = not status and 'no regions' or status
response.images.append(image)
return response
except ErrorStatus as exp:
@ -518,7 +565,7 @@ def enable_image(image_uuid, int_enabled, transaction_id):
try:
image_rec = datamanager.get_record('image')
sql_image = image_rec.get_image(image_uuid)
sql_image = image_rec.get_image_by_id(image_uuid)
if not sql_image:
raise ErrorStatus(404, 'Image with id: {0} not found'.format(
image_uuid))

View File

@ -37,8 +37,9 @@ class ImageRecord(Record):
raise
def get_image(self, id):
"""function to get image by name or id"""
try:
query = self.session.query(Image).filter(Image.id == id)
query = self.session.query(Image).filter((Image.id == id) | (Image.name == id))
return query.first()
except Exception as exception:
message = "Failed to read_image: id: {0}".format(id)
@ -93,6 +94,16 @@ class ImageRecord(Record):
LOG.log_exception(message, exception)
raise
def get_images_status_by_uuids(self, uuid_str):
results = self.session.connection().execute("SELECT resource_id, status from rds_resource_status_view"
" WHERE resource_id in ({})".format(uuid_str))
resource_status_dict = {}
if results:
resource_status_dict = dict((resource_id, status) for resource_id, status in results)
results.close()
return resource_status_dict
def create_images_by_visibility_query(self, visibility):
try:
query = self.session.query(Image).filter(Image.visibility == visibility)

View File

@ -4,7 +4,7 @@ from orm.services.image_manager.ims.persistency.sql_alchemy import db_models
from orm.services.image_manager.ims.persistency.wsme.base import Model
from orm.common.orm_common.utils.cross_api_utils import (get_regions_of_group,
set_utils_conf)
from pecan import conf, request
from pecan import conf
import wsme
@ -52,6 +52,7 @@ class Region(Model):
checksum = wsme.wsattr(wsme.types.text, mandatory=False)
size = wsme.wsattr(wsme.types.text, mandatory=False)
virtual_size = wsme.wsattr(wsme.types.text, mandatory=False)
error_message = wsme.wsattr(wsme.types.text, mandatory=False)
def __init__(self, name="", type="single", status="", checksum='',
size='', virtual_size=''):
@ -82,6 +83,9 @@ class Region(Model):
return region_rec
def set_error_message(self, error_message):
self.error_message = error_message
class RegionWrapper(Model): # pragma: no cover
"""regions model
@ -133,9 +137,9 @@ class Image(Model):
owner = wsme.wsattr(wsme.types.text, mandatory=False)
schema = wsme.wsattr(wsme.types.text, mandatory=False)
protected = wsme.wsattr(bool, mandatory=False, default=default_protected)
id = wsme.wsattr(wsme.types.text, mandatory=False, name='id')
# Output-only fields
id = wsme.wsattr(wsme.types.text, mandatory=False)
status = wsme.wsattr(wsme.types.text, mandatory=False)
created_at = wsme.wsattr(wsme.types.IntegerType(minimum=0),
mandatory=False, name='created-at')
@ -214,6 +218,13 @@ class Image(Model):
self.links = links
def validate_model(self, context=None):
if self.name.strip() == '':
raise ErrorStatus(400, "Image name is required.")
if self.url.strip() == '':
raise ErrorStatus(400, "Image location URL is required.")
# Validate visibility
if self.visibility == 'public' and self.customers:
raise ErrorStatus(400,
@ -223,6 +234,9 @@ class Image(Model):
raise ErrorStatus(400,
'Visibility is private but no customers were'
' specified!')
elif self.visibility not in ["private", "public"]:
raise ErrorStatus(400,
"Image visibility can only be 'public' or 'private'")
# Validate disk format
valid_disk_formats = ('ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw',
@ -242,22 +256,9 @@ class Image(Model):
if self.container_format not in valid_container_formats:
raise ErrorStatus(400, 'Invalid container format! {}'.format(self.container_format))
# Validate min-disk and min-ram (wsme automatically converts booleans
# to int, and isinstance(False, int) returns True, so that is how we
# validate the type)
if 'min-disk' in request.json['image'] and not type(
request.json['image']['min-disk']) == int:
raise ErrorStatus(400, 'min-disk must be an integer!')
if 'min-ram' in request.json['image'] and not type(
request.json['image']['min-ram']) == int:
raise ErrorStatus(400, 'min-ram must be an integer!')
if int(self.min_ram) not in range(0, self.min_ram + 1, 1024):
raise ErrorStatus(400, "mininum RAM value must be a multiple of 1024")
if self.min_disk != wsme.Unset and int(self.min_disk) > 2147483646 or int(self.min_disk) < 0:
raise ErrorStatus(400,
'value must be positive less than 2147483646')
if self.min_ram != wsme.Unset and int(self.min_ram) > 2147483646 or int(self.min_ram) < 0:
raise ErrorStatus(400,
'value must be positive less than 2147483646')
if context == "update":
for region in self.regions:
if region.type == "group":
@ -406,6 +407,32 @@ class ImageWrapper(Model):
def validate_model(self, context=None):
return self.image.validate_model(context)
def validate_update(self, sql_image=None, new_image=None):
if sql_image and new_image:
if sql_image.name != new_image.name:
raise ErrorStatus(400, "Cannot change name of existing image")
if sql_image.container_format != new_image.container_format:
raise ErrorStatus(400, "Cannot change container format of "
"existing image")
if sql_image.disk_format != new_image.disk_format:
raise ErrorStatus(400,
"Cannot change disk format of existing image")
if sql_image.min_ram != new_image.min_ram:
raise ErrorStatus(400,
"Cannot change min_ram of existing image")
if sql_image.min_disk != new_image.min_disk:
raise ErrorStatus(400,
"Cannot change min_disk of existing image")
if sql_image.url != new_image.url:
raise ErrorStatus(400, "Cannot change source data URL of "
"existing image")
def handle_region_group(self):
return self.image.handle_region_group()
@ -419,20 +446,26 @@ class ImageWrapper(Model):
return image
# ImageSummary a DataObject contains all the fields defined in ImageSummary.
'''
' ImageSummary a DataObject contains all the fields defined in ImageSummary.
'''
class ImageSummary(Model):
name = wsme.wsattr(wsme.types.text)
id = wsme.wsattr(wsme.types.text)
visibility = wsme.wsattr(wsme.types.text)
status = wsme.wsattr(wsme.types.text, mandatory=True)
regions = wsme.wsattr([str], mandatory=True)
def __init__(self, name='', id='', visibility=''):
def __init__(self, name='', id='', visibility='', status='', regions=[]):
Model.__init__(self)
self.name = name
self.id = id
self.visibility = visibility
self.status = status
self.regions = regions
@staticmethod
def from_db_model(sql_image):
@ -440,6 +473,11 @@ class ImageSummary(Model):
image.id = sql_image.id
image.name = sql_image.name
image.visibility = sql_image.visibility
image.regions = []
for sql_region in sql_image.regions:
region = Region()
region.name = sql_region.region_name
image.regions.append(region.name)
return image

View File

@ -109,7 +109,7 @@ def build_zone_response(zone):
design_type=zone.design_type,
location_type=zone.location_type,
vLCP_name=zone.vlcp_name,
AIC_version=zone.ranger_agent_version,
ranger_agent_version=zone.ranger_agent_version,
OS_version=zone.open_stack_version,
keystone_EP=end_points_dict["identity"],
horizon_EP=end_points_dict["dashboard"],

View File

@ -1,6 +1,5 @@
"""rest module."""
import logging
import time
import wsme
from orm.common.orm_common.utils import api_error_utils as err_utils
@ -11,6 +10,7 @@ from orm.services.region_manager.rms.services import services as GroupService
from orm.services.region_manager.rms.utils import authentication
from pecan import request, rest
from wsme import types as wtypes
from wsmeext.pecan import wsexpose
@ -24,8 +24,11 @@ class Groups(wtypes.DynamicBase):
name = wsme.wsattr(wtypes.text, mandatory=True)
description = wsme.wsattr(wtypes.text, mandatory=True)
regions = wsme.wsattr([str], mandatory=True)
created = wsme.wsattr(wtypes.dt_types.__getitem__(0), mandatory=False, name="created")
modified = wsme.wsattr(wtypes.dt_types.__getitem__(0), mandatory=False, name="modified")
def __init__(self, id=None, name=None, description=None, regions=[]):
def __init__(self, id=None, name=None, description=None, regions=[],
created=None, modified=None):
"""init function.
:param regions:
@ -35,6 +38,8 @@ class Groups(wtypes.DynamicBase):
self.name = name
self.description = description
self.regions = regions
self.created = created
self.modified = modified
def _to_python_obj(self):
obj = PythonModel.Groups()
@ -42,6 +47,8 @@ class Groups(wtypes.DynamicBase):
obj.name = self.name
obj.description = self.description
obj.regions = self.regions
obj.created = self.created
obj.modified = self.modified
return obj
@ -63,20 +70,27 @@ class OutputResource(wtypes.DynamicBase):
id = wsme.wsattr(wtypes.text, mandatory=True)
name = wsme.wsattr(wtypes.text, mandatory=True)
created = wsme.wsattr(wtypes.text, mandatory=True)
description = wsme.wsattr(wtypes.text, mandatory=True)
links = wsme.wsattr({str: str}, mandatory=True)
created = wsme.wsattr(wtypes.dt_types.__getitem__(0), mandatory=False, name="created")
modified = wsme.wsattr(wtypes.dt_types.__getitem__(0), mandatory=False, name="modified")
def __init__(self, id=None, name=None, created=None, links={}):
def __init__(self, id=None, name=None, description=None, links={},
created=None, modified=None):
"""init function.
:param id:
:param created:
:param links:
:param created
:param modified
"""
self.id = id
self.name = name
self.created = created
self.description = description
self.links = links
self.created = created
self.modified = modified
class Result(wtypes.DynamicBase):
@ -159,19 +173,17 @@ class GroupsController(rest.RestController):
try:
# May raise an exception which will return status code 400
GroupService.create_group_in_db(group_input.id,
group_input.name,
group_input.description,
group_input.regions)
GroupService.create_group_in_db(group_input)
logger.debug("Group created successfully in DB")
result = GroupService.get_groups_data(group_input.id)
# Create the group output data with the correct timestamp and link
group = OutputResource(group_input.id,
group_input.name,
repr(int(time.time() * 1000)),
group_input.description,
{'self': '{}/v2/orm/groups/{}'.format(
request.application_url,
group_input.id)})
group_input.id)},
result.created, result.modified)
event_details = 'Region group {} {} created with regions: {}'.format(
group_input.id, group_input.name, group_input.regions)
@ -207,6 +219,13 @@ class GroupsController(rest.RestController):
request.headers, group_id,
event_details=event_details)
# issue NotFoundError for "delete group" when group_id not found
except error_base.NotFoundError as e:
logger.error("GroupsController - Group not found")
raise err_utils.get_error(request.transaction_id,
message="Cannot delete - " + e.message,
status_code=404)
except Exception as exp:
logger.exception("fail to delete group :- {}".format(exp))
@ -225,13 +244,14 @@ class GroupsController(rest.RestController):
logger.debug("update group - id {}".format(group_id))
result = GroupService.update_group(group, group_id)
logger.debug("group updated to :- {}".format(result))
result = GroupService.get_groups_data(group_id)
# build result
group_result = OutputResource(result.id, result.name,
repr(int(time.time() * 1000)), {
result.description, {
'self': '{}/v2/orm/groups/{}'.format(
request.application_url,
result.id)})
result.id)},
result.created, result.modified)
event_details = 'Region group {} {} updated with regions: {}'.format(
group_id, group.name, group.regions)

View File

@ -11,7 +11,7 @@ from orm.services.region_manager.rms.services import error_base
from orm.services.region_manager.rms.services import services as RegionService
from orm.services.region_manager.rms.utils import authentication
from pecan import request, rest
from pecan import conf, request, rest
import wsme
from wsme import types as wtypes
from wsmeext.pecan import wsexpose
@ -30,7 +30,7 @@ class Address(wtypes.DynamicBase):
def __init__(self, country=None, state=None, city=None,
street=None, zip=None):
"""Init function
"""init function
:param country:
:param state:
@ -83,6 +83,7 @@ class RegionsData(wtypes.DynamicBase):
status = wsme.wsattr(wtypes.text, mandatory=True)
id = wsme.wsattr(wtypes.text, mandatory=True)
name = wsme.wsattr(wtypes.text, mandatory=False)
description = wsme.wsattr(wtypes.text, mandatory=True)
ranger_agent_version = wsme.wsattr(wtypes.text, mandatory=True, name="rangerAgentVersion")
open_stack_version = wsme.wsattr(wtypes.text, mandatory=True, name="OSVersion")
clli = wsme.wsattr(wtypes.text, mandatory=True, name="CLLI")
@ -92,16 +93,19 @@ class RegionsData(wtypes.DynamicBase):
design_type = wsme.wsattr(wtypes.text, mandatory=True, name="designType")
location_type = wsme.wsattr(wtypes.text, mandatory=True, name="locationType")
vlcp_name = wsme.wsattr(wtypes.text, mandatory=True, name="vlcpName")
created = wsme.wsattr(wtypes.dt_types.__getitem__(0), mandatory=False, name="created")
modified = wsme.wsattr(wtypes.dt_types.__getitem__(0), mandatory=False, name="modified")
def __init__(self, status=None, id=None, name=None, clli=None, design_type=None,
location_type=None, vlcp_name=None, open_stack_version=None,
address=Address(), ranger_agent_version=None, metadata={},
endpoint=[EndPoint()]):
"""init function
def __init__(self, status=None, id=None, name=None, description=None, clli=None,
design_type=None, location_type=None, vlcp_name=None,
open_stack_version=None, address=Address(), ranger_agent_version=None,
metadata={}, endpoint=[EndPoint()], created=None, modified=None):
"""init
:param status:
:param id:
:param name:
:param description:
:param clli:
:param design_type:
:param location_type:
@ -111,10 +115,13 @@ class RegionsData(wtypes.DynamicBase):
:param ranger_agent_version:
:param metadata:
:param endpoint:
:param created
:param modified
"""
self.status = status
self.id = id
self.name = self.id
self.description = description
self.clli = clli
self.ranger_agent_version = ranger_agent_version
self.metadata = metadata
@ -124,6 +131,8 @@ class RegionsData(wtypes.DynamicBase):
self.vlcp_name = vlcp_name
self.address = address
self.open_stack_version = open_stack_version
self.created = created
self.modified = modified
def _to_clean_python_obj(self):
obj = PythonModel.RegionData()
@ -131,6 +140,7 @@ class RegionsData(wtypes.DynamicBase):
obj.status = self.status
obj.id = self.id
obj.name = self.id
obj.description = self.description
obj.ranger_agent_version = self.ranger_agent_version
obj.clli = self.clli
obj.metadata = self.metadata
@ -163,11 +173,53 @@ class RegionsController(rest.RestController):
metadata = RegionMetadataController()
status = RegionStatusController()
def has_no_resources(self, region_id):
""" function to check if any resource (flavor, customer, or image) is
assigned to the region_id
"""
_check_conf_initialization()
try:
resources = {
'flavors': [conf.api.fms_server.base,
conf.api.fms_server.flavors],
'customers': [conf.api.cms_server.base,
conf.api.cms_server.customers],
'images': [conf.api.ims_server.base,
conf.api.ims_server.images]
}
empty = True
keystone_ep = authentication.get_keystone_ep(
request.headers['X-Auth-Region'])
request.headers['Keystone-Endpoint'] = keystone_ep
for resource in resources:
resource_get_url = '%s%s/?region=%s' % (
resources[resource][0],
resources[resource][1], region_id)
resp = requests.get(resource_get_url,
headers=request.headers,
verify=conf.verify)
resp_dict = resp.json()
if resp_dict[resource]:
return False
return True
except Exception as e:
raise err_utils.get_error(request.transaction_id,
status_code=401,
message=e.message)
@wsexpose(Regions, str, str, [str], str, str, str, str, str, str, str,
str, str, str, status_code=200, rest_content_types='json')
str, str, str, str, status_code=200, rest_content_types='json')
def get_all(self, type=None, status=None, metadata=None, rangerAgentVersion=None,
clli=None, regionname=None, osversion=None, valet=None,
state=None, country=None, city=None, street=None, zip=None):
clli=None, regionname=None, osversion=None, location_type=None,
state=None, country=None, city=None, street=None, zip=None,
vlcp_name=None):
"""get regions.
:param type: query field
@ -177,12 +229,13 @@ class RegionsController(rest.RestController):
:param clli: query field
:param regionname: query field
:param osversion: query field
:param valet: query field
:param location_type: query field
:param state: query field
:param country: query field
:param city: query field
:param street: query field
:param zip: query field
:param vlcp_name query field
:return: json from db
:exception: EntityNotFoundError 404
"""
@ -191,8 +244,9 @@ class RegionsController(rest.RestController):
url_args = {'type': type, 'status': status, 'metadata': metadata,
'rangerAgentVersion': rangerAgentVersion, 'clli': clli, 'regionname': regionname,
'osversion': osversion, 'valet': valet, 'state': state,
'country': country, 'city': city, 'street': street, 'zip': zip}
'osversion': osversion, 'location_type': location_type, 'state': state,
'country': country, 'city': city, 'street': street, 'zip': zip,
'vlcp_name': vlcp_name}
logger.debug("Parameters: {}".format(str(url_args)))
try:
@ -248,8 +302,10 @@ class RegionsController(rest.RestController):
result = RegionService.create_full_region(full_region_input)
logger.debug("API: region created : {}".format(result))
event_details = 'Region {} {} created: AICversion {}, OSversion {}, CLLI {}'.format(
full_region_input.name, full_region_input.design_type,
event_details = 'Region {} {} created: rangerAgentVersion {}, OSversion {}, CLLI {}'.format(
full_region_input.name,
full_region_input.description,
full_region_input.design_type,
full_region_input.ranger_agent_version,
full_region_input.open_stack_version, full_region_input.clli)
utils.audit_trail('create region', request.transaction_id,
@ -277,27 +333,44 @@ class RegionsController(rest.RestController):
@wsexpose(None, str, rest_content_types='json', status_code=204)
def delete(self, region_id):
logger.info("Delete Region")
authentication.authorize(request, 'region:delete')
utils.set_utils_conf(conf)
# currently ORM resource types are 'flavor', 'customer', and 'image'
proceed_to_delete = self.has_no_resources(region_id)
if proceed_to_delete:
logger.info("Delete Region")
authentication.authorize(request, 'region:delete')
try:
try:
logger.debug("delete region {}".format(region_id))
result = RegionService.delete_region(region_id)
logger.debug("region deleted")
logger.debug("delete region {}".format(region_id))
result = RegionService.delete_region(region_id)
logger.debug("region deleted")
event_details = 'Region {} deleted'.format(region_id)
utils.audit_trail('delete region', request.transaction_id,
request.headers, region_id,
event_details=event_details)
event_details = 'Region {} deleted'.format(region_id)
utils.audit_trail('delete region', request.transaction_id,
request.headers, region_id,
event_details=event_details)
# issue NotFoundError for "Delete Region" when group_id not found
# which is returned by RegionService.delete_region function
except error_base.NotFoundError as exp:
logger.error("RegionsController - Region not found")
raise err_utils.get_error(request.transaction_id,
message="Cannot delete - " + exp.message,
status_code=exp.status_code)
except Exception as exp:
logger.exception(
"error in deleting region .. reason:- {}".format(exp))
raise err_utils.get_error(request.transaction_id,
status_code=500,
message=exp.message)
return
else:
region_resources_exist_msg = "Region '{}' cannot be deleted as resources are assigned.".format(region_id)
except Exception as exp:
logger.exception(
"error in deleting region .. reason:- {}".format(exp))
raise err_utils.get_error(request.transaction_id,
status_code=500,
message=exp.message)
return
status_code=400,
message=region_resources_exist_msg)
@wsexpose(RegionsData, str, body=RegionsData, status_code=201,
rest_content_types='json')
@ -312,7 +385,7 @@ class RegionsController(rest.RestController):
result = RegionService.update_region(region_id, region)
logger.debug("API: region {} updated".format(region_id))
event_details = 'Region {} {} modified: AICversion {}, OSversion {}, CLLI {}'.format(
event_details = 'Region {} {} modified: rangerAgentVersion {}, OSversion {}, CLLI {}'.format(
region.name, region.design_type, region.ranger_agent_version,
region.open_stack_version, region.clli)
utils.audit_trail('update region', request.transaction_id,

View File

@ -1,24 +1,35 @@
{
"default": "!",
"orm_admin": "role:admin and tenant:admin",
"admin": "role:admin and tenant:admin or role:admin and tenant:services",
"admin_support": "role:admin_support and tenant:admin or role:admin_support and tenant:services",
"admin_viewer": "role:admin_viewer and tenant:admin or role:admin_viewer and tenant:services",
"admin_or_support": "rule:admin or rule:admin_support",
"admin_or_support_or_viewer": "rule:admin or rule:admin_support or rule:admin_viewer",
"lcp:get_one": "",
"lcp:get_all": "",
"region:get_one": "",
"region:get_all": "",
"region:create": "rule:orm_admin",
"region:update": "rule:orm_admin",
"region:delete": "rule:orm_admin",
"region:create": "rule:admin_or_support",
"region:update": "rule:admin",
"region:delete": "rule:admin",
"group:get_one": "",
"group:get_all": "",
"group:create": "rule:orm_admin",
"group:update": "rule:orm_admin",
"group:delete": "rule:orm_admin",
"configuration:get": "rule:orm_admin",
"log:update": "rule:orm_admin",
"metadata:get": "rule:orm_admin",
"metadata:create": "rule:orm_admin",
"metadata:update": "rule:orm_admin",
"metadata:delete": "rule:orm_admin",
"status:put": "rule:orm_admin"
"group:create": "rule:admin_or_support",
"group:update": "rule:admin",
"group:delete": "rule:admin",
"configuration:get": "rule:admin_or_support_or_viewer",
"log:update": "rule:admin",
"metadata:get": "rule:admin_or_support_or_viewer",
"metadata:create": "rule:admin_or_support",
"metadata:update": "rule:admin",
"metadata:delete": "rule:admin",
"status:put": "rule:admin"
}

View File

@ -9,7 +9,7 @@ class Address(object):
def __init__(self, country=None, state=None, city=None,
street=None, zip=None):
"""init
"""init function
:param country:
:param state:
@ -41,15 +41,18 @@ class EndPoint(object):
class RegionData(object):
"""class method json header."""
def __init__(self, status=None, id=None, name=None, clli=None,
ranger_agent_version=None, design_type=None, location_type=None,
def __init__(self, status=None, id=None, name=None, description=None,
clli=None, ranger_agent_version=None, design_type=None,
location_type=None,
vlcp_name=None, open_stack_version=None,
address=Address(), metadata={}, endpoints=[EndPoint()]):
"""init
address=Address(), metadata={}, endpoints=[EndPoint()],
created=None, modified=None):
"""init function
:param status:
:param id:
:param name:
:param description:
:param clli:
:param ranger_agent_version:
:param design_type:
@ -59,11 +62,14 @@ class RegionData(object):
:param address:
:param metadata:
:param endpoints:
:param created
:param modified
"""
self.status = status
self.id = id
# make id and name always the same
self.name = self.id
self.description = description
self.clli = clli
self.ranger_agent_version = ranger_agent_version
self.metadata = metadata
@ -73,6 +79,38 @@ class RegionData(object):
self.vlcp_name = vlcp_name
self.open_stack_version = open_stack_version
self.address = address
self.created = created
self.modified = modified
def _validate_fields(self):
"""The following fields are mandatory for create/update json:
id, clli, design_type, ranger_agent_version, vlcp_name
Also check that all input field values (except 'description',
"location_type", and address fields) do not contain a space.
Validation for 'endpoints' and 'status' as mandatory fields
are handled by other methods.
"""
mandatory_fields = ['id', 'clli', 'design_type', 'ranger_agent_version',
'vlcp_name']
check_fields_for_spaces = ['id', 'clli', 'design_type', 'ranger_agent_version',
'open_stack_version', 'vlcp_name']
for field in check_fields_for_spaces:
value = getattr(self, field)
if field in mandatory_fields:
# if mandatory field, check if field is empty
if not value:
raise error_base.InputValueError(
message="'{}' field value is required.".format(field))
# check if field contains spaces, then issue error message
if ' ' in value:
raise error_base.InputValueError(
message="'{}' field value cannot contain "
"spaces.".format(field))
def _validate_end_points(self, endpoints_types_must_have):
ep_duplicate = []
@ -99,11 +137,22 @@ class RegionData(object):
"one of {}".format(allowed_status))
return
def _validate_name(self):
if not self.name:
raise error_base.InputValueError(
message="Region ID/name is required")
if ' ' in self.name:
raise error_base.InputValueError(
message="Region ID/name must match and not contain spaces")
def _validate_model(self):
allowed_status = conf.region_options.allowed_status_values[:]
endpoints_types_must_have = conf.region_options.endpoints_types_must_have[:]
self._validate_status(allowed_status)
self._validate_end_points(endpoints_types_must_have)
self._validate_name()
self._validate_fields()
return
def _to_db_model_dict(self):
@ -118,6 +167,7 @@ class RegionData(object):
db_model_dict = {}
db_model_dict['region_id'] = self.id
db_model_dict['name'] = self.name
db_model_dict['description'] = self.description
db_model_dict['address_state'] = self.address.state
db_model_dict['address_country'] = self.address.country
db_model_dict['address_city'] = self.address.city
@ -132,6 +182,7 @@ class RegionData(object):
db_model_dict['clli'] = self.clli
db_model_dict['end_point_list'] = end_points
db_model_dict['meta_data_dict'] = self.metadata
return db_model_dict
@ -151,7 +202,8 @@ class Groups(object):
"""main json header."""
def __init__(self, id=None, name=None,
description=None, regions=[]):
description=None, regions=[],
created=None, modified=None):
"""init function.
:param regions:
@ -161,6 +213,8 @@ class Groups(object):
self.name = name
self.description = description
self.regions = regions
self.created = created
self.modified = modified
def _to_db_model_dict(self):
db_dict = {}
@ -169,12 +223,23 @@ class Groups(object):
db_dict['group_regions'] = self.regions
return db_dict
def _validate_model(self):
if not self.name or not self.id:
raise error_base.InputValueError(
message="Group ID/name is required")
if ' ' in self.name or ' ' in self.id:
raise error_base.InputValueError(
message="Group ID/name must not contain spaces")
if not self.description.rstrip():
raise error_base.InputValueError(
message="Description is required")
class GroupsWrraper(object):
"""list of groups."""
def __init__(self, groups=None):
"""init
"""init function
:param groups:
"""

View File

@ -5,8 +5,9 @@ class UrlParms(object):
"""class method."""
def __init__(self, type=None, status=None, metadata=None, rangerAgentVersion=None,
clli=None, regionname=None, osversion=None, valet=None,
state=None, country=None, city=None, street=None, zip=None):
clli=None, regionname=None, osversion=None, location_type=None,
state=None, country=None, city=None, street=None, zip=None,
vlcp_name=None):
"""init method.
:param type:
@ -16,15 +17,16 @@ class UrlParms(object):
:param clli:
:param regionname:
:param osversion:
:param valet:
:param location_type:
:param state:
:param country:
:param city:
:param street:
:param zip:
:param vlcp_name:
"""
if type:
self.location_type = type
self.design_type = type
if status:
self.region_status = status
if metadata:
@ -37,8 +39,8 @@ class UrlParms(object):
self.name = regionname
if osversion:
self.open_stack_version = osversion
if valet:
self.valet = valet
if location_type:
self.location_type = location_type
if state:
self.address_state = state
if country:
@ -49,6 +51,8 @@ class UrlParms(object):
self.address_street = street
if zip:
self.address_zip = zip
if vlcp_name:
self.vlcp_name = vlcp_name
def _build_query(self):
"""nuild db query.

View File

@ -1,2 +1 @@
region_id,region_name,address_state,address_country,address_city,address_street,address_zip,region_status,ranger_agent_version,open_stack_version,design_type,location_type,vlcp_name,clli,description,keystone_url,horizon_url,ord_url
LOCAL,LOCAL,NY,US,FIL,n/a,3333,functional,ranger_agent1.0,kilo,n/a,n/a,n/a,n/a,DPK lcp in FIL,http://127.0.0.1:5000/v2.0,http://horizon3.com,http://127.0.0.1:9010

1 region_id region_name address_state address_country address_city address_street address_zip region_status ranger_agent_version open_stack_version design_type location_type vlcp_name clli description keystone_url horizon_url ord_url
LOCAL LOCAL NY US FIL n/a 3333 functional ranger_agent1.0 kilo n/a n/a n/a n/a DPK lcp in FIL http://127.0.0.1:5000/v2.0 http://horizon3.com http://127.0.0.1:9010

View File

@ -79,8 +79,14 @@ def delete_region(region_id):
LOG.debug("logic:- delete region {}".format(region_id))
try:
db = data_manager_factory.get_data_manager()
# logic to allow 'delete_region' to issue NotFoundError when region_id is non-existent
region = db.get_region_by_id_or_name(region_id)
if not region:
raise error_base.NotFoundError(message="Region '{}' not found".format(region_id))
db.delete_region(region_id)
LOG.debug("region deleted")
except Exception as exp:
LOG.exception("fail to delete region {}".format(exp))
raise
@ -206,8 +212,12 @@ def delete_group(group_id):
"""
LOG.debug("delete group logic")
try:
db = data_manager_factory.get_data_manager()
# logic to allow 'delete_group' to issue NotFoundError when group_id is non-existent
groups = db.get_group(group_id)
if not groups:
raise error_base.NotFoundError(message="Group '{}' not found".format(group_id))
LOG.debug("delete group id {} from db".format(group_id))
db.delete_group(group_id)
@ -217,7 +227,7 @@ def delete_group(group_id):
return
def create_group_in_db(group_id, group_name, description, regions):
def create_group_in_db(group):
"""Create a region group in the database.
:param group_id: The ID of the group to create
@ -227,16 +237,18 @@ def create_group_in_db(group_id, group_name, description, regions):
:raise: GroupExistsError (status code 400) if the group already exists
"""
try:
group = group._to_python_obj()
group._validate_model()
manager = data_manager_factory.get_data_manager()
manager.add_group(group_id, group_name, description, regions)
manager.add_group(group.id, group.name,
group.description, group.regions)
except error_base.ConflictError:
LOG.exception("Group {} already exists".format(group_id))
LOG.exception("Group {} already exists".format(group.id))
raise error_base.ConflictError(
message="Group {} already exists".format(group_id))
except error_base.InputValueError:
LOG.exception("Some of the regions not found")
raise error_base.NotFoundError(
message="Some of the regions not found")
message="Group {} already exists".format(group.id))
except error_base.InputValueError as e:
LOG.exception(e.message)
raise
def update_group(group, group_id):

View File

@ -1,3 +1,4 @@
import datetime
import logging
from orm.services.region_manager.rms.model import model as PythonModels
@ -68,7 +69,8 @@ class DataManager(BaseDataManager):
location_type=location_type,
vlcp_name=vlcp_name,
clli=clli,
description=description)
description=description,
created=datetime.datetime.now())
if end_point_list is not None:
for end_point in end_point_list:
@ -174,6 +176,8 @@ class DataManager(BaseDataManager):
def delete_region(self, region_id):
# delete a region from `region` table and also the region's
# entries from `region_meta_data` and `region_end_points` tables
# as well as the "group_region" table
session = self._engine_facade.get_session()
with session.begin():
session.query(Region).filter_by(region_id=region_id).delete()
@ -396,7 +400,8 @@ class DataManager(BaseDataManager):
with session.begin():
session.add(Group(group_id=group_id,
name=group_name,
description=group_description))
description=group_description,
created=datetime.datetime.now()))
session.flush() # add the groupe if not rollback
@ -408,7 +413,8 @@ class DataManager(BaseDataManager):
session.add_all(group_regions)
except oslo_db.exception.DBReferenceError as e:
logger.error("Reference error: {}".format(str(e)))
raise error_base.InputValueError("Reference error")
raise error_base.InputValueError(
message="One or more regions not found")
except oslo_db.exception.DBDuplicateEntry as e:
logger.error("Duplicate entry: {}".format(str(e)))
raise error_base.ConflictError("Duplicate entry error")
@ -429,6 +435,8 @@ class DataManager(BaseDataManager):
group_model.id = a_group.group_id
group_model.name = a_group.name
group_model.description = a_group.description
group_model.created = a_group.created
group_model.modified = a_group.modified
regions = []
group_regions = session.query(GroupRegion).\
filter_by(group_id=a_group.group_id)
@ -484,7 +492,9 @@ class DataManager(BaseDataManager):
if a_group is not None:
group_model = {"id": a_group.group_id,
"name": a_group.name,
"description": a_group.description}
"description": a_group.description,
"created": a_group.created,
"modified": a_group.modified}
regions = []
group_regions = session.query(GroupRegion). \
filter_by(group_id=a_group.group_id)

View File

@ -1,4 +1,7 @@
# coding: utf-8
import datetime
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String
from orm.services.region_manager.rms.model.model import Address, EndPoint, RegionData
from sqlalchemy import Column, ForeignKey, Integer, String
@ -28,7 +31,9 @@ class Region(Base):
vlcp_name = Column(String(64), nullable=False)
clli = Column(String(64), nullable=False)
description = Column(String(255), nullable=False)
created = Column(DateTime(timezone=False),
default=datetime.datetime.now())
modified = Column(DateTime(timezone=False))
end_points = relationship(u'RegionEndPoint')
meta_data = relationship(u'RegionMetaData')
@ -56,6 +61,7 @@ class Region(Base):
id = self.region_id
name = self.name
description = self.description
status = self.region_status
clli = self.clli
ranger_agent_version = self.ranger_agent_version
@ -63,13 +69,17 @@ class Region(Base):
location_type = self.location_type
vlcp_name = self.vlcp_name
open_stack_version = self.open_stack_version
created = self.created
modified = self.modified
address = self.address_to_wsme()
return RegionData(status, id, name, clli, ranger_agent_version,
return RegionData(status, id, name, description, clli, ranger_agent_version,
design_type, location_type, vlcp_name,
open_stack_version, address,
metadata=wsme_meta_data,
endpoints=wsme_end_points)
endpoints=wsme_end_points,
created=created,
modified=modified)
class Group(Base):
@ -79,12 +89,17 @@ class Group(Base):
group_id = Column(String(64), nullable=False, unique=True)
name = Column(String(64), nullable=False, unique=True)
description = Column(String(255), nullable=False)
created = Column(DateTime(timezone=False),
default=datetime.datetime.now())
modified = Column(DateTime(timezone=False))
def __json__(self):
return dict(
group_id=self.group_id,
name=self.name,
description=self.description
description=self.description,
created=self.created,
modified=self.modified
)
def to_wsme(self):

View File

@ -9,7 +9,7 @@ from pecan import conf
logger = logging.getLogger(__name__)
def _get_keystone_ep(auth_region):
def get_keystone_ep(auth_region):
result = RegionService.get_region_by_id_or_name(auth_region)
for ep in result.endpoints:
if ep.type == 'identity':
@ -25,7 +25,7 @@ def authorize(request, action):
auth_region = request.headers.get('X-Auth-Region')
try:
keystone_ep = _get_keystone_ep(auth_region)
keystone_ep = get_keystone_ep(auth_region)
except Exception:
# Failed to find Keystone EP - we'll set it to None instead of failing
# because the rule might be to let everyone pass

View File

@ -1,5 +1,4 @@
import logging
import os
from orm.common.client.audit.audit_client.api import audit
from pecan import conf, make_app
@ -63,11 +62,8 @@ def validate_sot():
def main():
dir_name = os.path.dirname(__file__)
drive, path_and_file = os.path.splitdrive(dir_name)
path, filename = os.path.split(path_and_file)
runner = CommandRunner()
runner.run(['serve', path + '/config.py'])
runner.run(['serve', '../config.py'])
if __name__ == "__main__":
main()

View File

@ -4,11 +4,12 @@ import time
from orm.services.resource_distributor.rds.controllers.v1.base import InputValueError
from orm.services.resource_distributor.rds.controllers.v1.status import get_resource
from orm.services.resource_distributor.rds.services.base import ErrorMesage, InputError
from orm.services.resource_distributor.rds.services.base import ErrorMessage, InputError
from orm.services.resource_distributor.rds.services import region_resource_id_status as regionResourceIdStatus
from orm.services.resource_distributor.rds.utils import utils
from pecan import rest
import wsme
from wsme import types as wtypes
from wsmeext.pecan import wsexpose
@ -144,9 +145,11 @@ class Status(rest.RestController):
logger.debug("save data to database.. data :- %s" % data_to_save)
try:
regionResourceIdStatus.add_status(data_to_save)
# invoke regin data to delete on sucess
utils.invoke_delete_region(data_to_save)
# send data to ims
utils.post_data_to_image(data_to_save)
except ErrorMesage as exp:
except ErrorMessage as exp:
logger.error(exp.message)
# raise ClientSideError(status_code=400, error=exp.message)
except InputError as e:

View File

@ -2,7 +2,7 @@ import json
import logging
import requests
from orm.services.resource_distributor.rds.services.base import ErrorMesage
from orm.services.resource_distributor.rds.services.base import ErrorMessage
from orm.services.resource_distributor.rds.utils import authentication as AuthService
from pecan import conf
@ -51,10 +51,10 @@ def send_image_metadata(meta_data, region, resource_id, action='post'):
except requests.ConnectionError as exp:
logger.error(exp)
logger.exception(exp)
raise ErrorMesage("fail to connect to server {}".format(exp.message))
raise ErrorMessage("fail to connect to server {}".format(exp.message))
if response.status_code != 200:
raise ErrorMesage(
raise ErrorMessage(
"Got error from orm.services.resource_distributor.rds server, code: {0} message: {1}".format(
response.status_code, response.content))
return

View File

@ -0,0 +1,100 @@
import json
import logging
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
logger = logging.getLogger(__name__)
headers = {'content-type': 'application/json'}
def _set_headers(region):
try:
token_id = AuthService.get_token(region)
if token_id:
headers['X-Auth-Token'] = token_id
headers['X-Auth-Region'] = region
except Exception:
logger.error("no token")
headers['X-RANGER-Requester'] = 'rds_resource_service_proxy'
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))
_set_headers(region)
try:
if resource_type == "customer":
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),
headers=headers, verify=conf.verify)
elif resource_type == "flavor":
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),
headers=headers, verify=conf.verify)
elif resource_type == "image":
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),
headers=headers, verify=conf.verify)
else:
response = None
logger.debug("got response {} from send delete status to {} service.".
format(response, resource_type))
except requests.ConnectionError as exp:
logger.error(exp)
logger.exception(exp)
raise ErrorMessage("fail to connect to server {}".format(exp.message))
if response.status_code != 200:
raise ErrorMessage(
"Got error from rds server, code: {0} message: {1}".format(
response.status_code, response.content))
return
def send_image_metadata(meta_data, region, resource_id, action='post'):
logger.debug(
"IMS PROXY - send metadata to ims {} for region {}".format(meta_data,
region))
data_to_send = {
"metadata": {
"checksum": meta_data['checksum'],
"virtual_size": meta_data['virtual_size'],
"size": meta_data['size']
}
}
_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))
if action == 'post':
try:
response = requests.post(
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))
if response.status_code != 200:
raise ErrorMessage(
"Got error from rds server, code: {0} message: {1}".format(
response.status_code, response.content))
return

View File

@ -1,29 +1,25 @@
"""python module."""
import logging
import requests
from pecan import conf
import requests
logger = logging.getLogger(__name__)
headers = {'content-type': 'application/json'}
def get_regions():
logger.debug("get list of regions from rms")
logger.debug("rms server {0} path = {1}".format(conf.rms.base_url,
conf.rms.all_regions_path))
response = requests.get(conf.rms.base_url + conf.rms.all_regions_path,
headers=headers, verify=conf.verify)
if response.status_code != 200:
log_message = "not able to get regions {}".format(response)
log_message = log_message.replace('\n', '_').replace('\r', '_')
logger.error(log_message)
return
return response.json()
def get_rms_region(region_name):
""" function to call rms api for region info
returns 200 for ok and None for error
"""
try:
headers = {
'content-type': 'application/json',
}
rms_server_url = '%s%s/%s' % (
conf.rms.base_url, conf.rms.all_regions_path, region_name)
resp = requests.get(rms_server_url, headers=headers,
verify=conf.verify).json()
return resp
except Exception as e:
logger.log_exception('Failed in get_rms_region', e)
return None

View File

@ -9,7 +9,7 @@ class InputError(Error):
self.value = value
class ErrorMesage(Error):
class ErrorMessage(Error):
def __init__(self, message=None):
self.message = message

View File

@ -5,11 +5,12 @@ 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)
from orm.services.resource_distributor.rds.services.base import ConflictValue, ErrorMesage
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
from orm.services.resource_distributor.rds.utils import utils, uuid_utils
from pecan import conf, request
my_logger = logging.getLogger(__name__)
@ -34,13 +35,13 @@ def _get_inputs_from_resource_type(jsondata,
model=jsondata,
external_transaction_id=external_transaction_id)
else:
raise ErrorMesage("no support for resource %s" % resource_type)
raise ErrorMessage("no support for resource %s" % resource_type)
return input_data
def _region_valid(region):
if ('rms_status' in region
and region['rms_status'] not in conf.allow_region_statuses):
if 'rms_status' in region and region[
'rms_status'] not in conf.allow_region_statuses:
return False
return True
@ -51,6 +52,8 @@ def _create_or_update_resource_status(input_data, target, error_msg='',
if not _region_valid(target):
status = 'Error'
error_msg = "Not sent to ord as status equal to " + target['rms_status']
raise ErrorMessage("Not sent to ord as status equal to %s"
% target['rms_status'])
my_logger.debug("save status as %s" % status)
data_to_save = dict(
@ -137,9 +140,8 @@ def _check_resource_status(input_data):
def update_sot(input_data):
"""create resource."""
my_logger.debug(
"build yaml file for %s id: %s" % (input_data.resource_type,
input_data.resource_id))
my_logger.debug("build yaml file for %s id: %s" % (input_data.resource_type,
input_data.resource_id))
targetslist = _create_data_to_sot(input_data)
my_logger.debug("upload yaml to SoT")
_upload_to_sot(input_data.resource_id,
@ -168,7 +170,7 @@ def main(jsondata, external_transaction_id, resource_type, operation):
update_sot(input_data)
except ConflictValue:
raise
except ErrorMesage as exp:
except ErrorMessage as exp:
my_logger.error(exp.message)
my_logger.exception(exp)
raise
@ -176,5 +178,5 @@ def main(jsondata, external_transaction_id, resource_type, operation):
my_logger.exception(e)
_set_all_statuses_to_error(input_data)
my_logger.error("deleting fails ,Error : {}".format(str(e.message)))
raise ErrorMesage(str(e.message))
raise ErrorMessage(str(e.message))
return input_data.resource_id

Some files were not shown because too many files have changed in this diff Show More