903cba8c1a
When an exception was caught and rethrown, it should call 'raise' without any arguments because it shows the place where an exception occured initially instead of place where the exception re-raised Change-Id: I5bb1cb87dc2c0c8d502a5bbb75e70369cb8254ca
297 lines
9.7 KiB
Python
297 lines
9.7 KiB
Python
# Copyright 2014 VMware.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from oslo_log import log as logging
|
|
|
|
from congressclient.v1 import client as congress_client
|
|
from django.conf import settings
|
|
import keystoneclient
|
|
from openstack_dashboard.api import base
|
|
|
|
|
|
LITERALS_SEPARATOR = '),'
|
|
RULE_SEPARATOR = ':-'
|
|
TABLE_SEPARATOR = ':'
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def _set_id_as_name_if_empty(apidict, length=0):
|
|
try:
|
|
if not apidict._apidict.get('name'):
|
|
id = apidict._apidict['id']
|
|
if length:
|
|
id = id[:length]
|
|
apidict._apidict['name'] = '(%s)' % id
|
|
else:
|
|
apidict._apidict['name'] = id
|
|
except KeyError:
|
|
pass
|
|
|
|
|
|
class PolicyAPIDictWrapper(base.APIDictWrapper):
|
|
def set_id_as_name_if_empty(self):
|
|
_set_id_as_name_if_empty(self)
|
|
|
|
def set_id_if_empty(self, id):
|
|
apidict_id = self._apidict.get('id')
|
|
if not apidict_id or apidict_id == "None":
|
|
self._apidict['id'] = id
|
|
|
|
def set_value(self, key, value):
|
|
self._apidict[key] = value
|
|
|
|
def delete_by_key(self, key):
|
|
del self._apidict[key]
|
|
|
|
|
|
class PolicyRule(PolicyAPIDictWrapper):
|
|
"""Wrapper for a Congress policy's rule."""
|
|
def set_id_as_name_if_empty(self):
|
|
# Shorten UUID.
|
|
_set_id_as_name_if_empty(self, length=8)
|
|
|
|
|
|
class PolicyTable(PolicyAPIDictWrapper):
|
|
"""Wrapper for a Congress policy's data table."""
|
|
def set_policy_details(self, policy):
|
|
self._apidict['policy_name'] = policy['name']
|
|
self._apidict['policy_owner_id'] = policy['owner_id']
|
|
|
|
|
|
def congressclient(request):
|
|
"""Instantiate Congress client."""
|
|
auth_url = getattr(settings, 'OPENSTACK_KEYSTONE_URL')
|
|
user = request.user
|
|
auth = keystoneclient.auth.identity.v2.Token(auth_url, user.token.id,
|
|
tenant_id=user.tenant_id,
|
|
tenant_name=user.tenant_name)
|
|
session = keystoneclient.session.Session(auth=auth)
|
|
region_name = user.services_region
|
|
|
|
kwargs = {
|
|
'session': session,
|
|
'auth': None,
|
|
'interface': 'publicURL',
|
|
'service_type': 'policy',
|
|
'region_name': region_name
|
|
}
|
|
return congress_client.Client(**kwargs)
|
|
|
|
|
|
def policies_list(request):
|
|
"""List all policies."""
|
|
client = congressclient(request)
|
|
policies_list = client.list_policy()
|
|
results = policies_list['results']
|
|
policies = []
|
|
for p in results:
|
|
policy = PolicyAPIDictWrapper(p)
|
|
# Policies currently have a name but not necessarily a non-"None" id.
|
|
# Use the name to identify the policy, needed to differentiate them in
|
|
# DataTables.
|
|
policy.set_id_if_empty(policy.get('name'))
|
|
policies.append(policy)
|
|
return policies
|
|
|
|
|
|
def policy_create(request, args):
|
|
"""Create a policy with the given properties."""
|
|
client = congressclient(request)
|
|
policy = client.create_policy(args)
|
|
return policy
|
|
|
|
|
|
def policy_delete(request, policy_id):
|
|
"""Delete a policy by id."""
|
|
client = congressclient(request)
|
|
policy = client.delete_policy(policy_id)
|
|
return policy
|
|
|
|
|
|
def policy_get(request, policy_name):
|
|
"""Get a policy by name."""
|
|
# TODO(jwy): Use congress.show_policy() once system policies have unique
|
|
# IDs.
|
|
policies = policies_list(request)
|
|
for p in policies:
|
|
if p['name'] == policy_name:
|
|
return p
|
|
|
|
|
|
def policy_rule_create(request, policy_name, body=None):
|
|
"""Create a rule in the given policy, with the given properties."""
|
|
client = congressclient(request)
|
|
rule = client.create_policy_rule(policy_name, body=body)
|
|
return rule
|
|
|
|
|
|
def policy_rule_delete(request, policy_name, rule_id):
|
|
"""Delete a rule by id, from the given policy."""
|
|
client = congressclient(request)
|
|
rule = client.delete_policy_rule(policy_name, rule_id)
|
|
return rule
|
|
|
|
|
|
def policy_rules_list(request, policy_name):
|
|
"""List all rules in a policy, given by name."""
|
|
client = congressclient(request)
|
|
policy_rules_list = client.list_policy_rules(policy_name)
|
|
results = policy_rules_list['results']
|
|
return [PolicyRule(r) for r in results]
|
|
|
|
|
|
def policy_tables_list(request, policy_name):
|
|
"""List all data tables in a policy, given by name."""
|
|
client = congressclient(request)
|
|
policy_tables_list = client.list_policy_tables(policy_name)
|
|
results = policy_tables_list['results']
|
|
return [PolicyTable(t) for t in results]
|
|
|
|
|
|
def policy_table_get(request, policy_name, table_name):
|
|
"""Get a policy table in a policy, given by name."""
|
|
client = congressclient(request)
|
|
return client.show_policy_table(policy_name, table_name)
|
|
|
|
|
|
def policy_rows_list(request, policy_name, table_name):
|
|
"""List all rows in a policy's data table, given by name."""
|
|
client = congressclient(request)
|
|
policy_rows_list = client.list_policy_rows(policy_name, table_name)
|
|
results = policy_rows_list['results']
|
|
|
|
policy_rows = []
|
|
# Policy table rows currently don't have ids. However, the DataTable object
|
|
# requires an id for the table to get rendered properly. Otherwise, the
|
|
# same contents are displayed for every row in the table. Assign the rows
|
|
# ids here.
|
|
id = 0
|
|
for row in results:
|
|
new_row = PolicyAPIDictWrapper(row)
|
|
new_row.set_id_if_empty(id)
|
|
id += 1
|
|
policy_rows.append(new_row)
|
|
return policy_rows
|
|
|
|
|
|
def policy_table_schema_get(request, policy_name, table_name):
|
|
"""Get the schema for a policy table, based on the first matching rule."""
|
|
column_names = []
|
|
rules = policy_rules_list(request, policy_name)
|
|
# There might be multiple rules that use the same name in the head. Pick
|
|
# the first matching one, which is what the policy engine currently does.
|
|
for rule in rules:
|
|
rule_def = rule['rule']
|
|
head, _ = rule_def.split(RULE_SEPARATOR)
|
|
if head.strip().startswith('%s(' % table_name):
|
|
start = head.index('(') + 1
|
|
end = head.index(')')
|
|
column_names = head[start:end].split(',')
|
|
break
|
|
|
|
schema = {'table_id': table_name}
|
|
schema['columns'] = [{'name': name.strip(), 'description': None}
|
|
for name in column_names]
|
|
return schema
|
|
|
|
|
|
def datasources_list(request):
|
|
"""List all the data sources."""
|
|
client = congressclient(request)
|
|
datasources_list = client.list_datasources()
|
|
datasources = datasources_list['results']
|
|
return [PolicyAPIDictWrapper(d) for d in datasources]
|
|
|
|
|
|
def datasource_get(request, datasource_id):
|
|
"""Get a data source by id."""
|
|
# TODO(jwy): Need API in congress_client to retrieve data source by id.
|
|
datasources = datasources_list(request)
|
|
for d in datasources:
|
|
if d['id'] == datasource_id:
|
|
return d
|
|
|
|
|
|
def datasource_get_by_name(request, datasource_name):
|
|
"""Get a data source by name."""
|
|
datasources = datasources_list(request)
|
|
for d in datasources:
|
|
if d['name'] == datasource_name:
|
|
return d
|
|
|
|
|
|
def datasource_tables_list(request, datasource_id):
|
|
"""List all data tables in a data source, given by id."""
|
|
client = congressclient(request)
|
|
datasource_tables_list = client.list_datasource_tables(datasource_id)
|
|
results = datasource_tables_list['results']
|
|
return [PolicyAPIDictWrapper(t) for t in results]
|
|
|
|
|
|
def datasource_rows_list(request, datasource_id, table_name):
|
|
"""List all rows in a data source's data table, given by id."""
|
|
client = congressclient(request)
|
|
datasource_rows_list = client.list_datasource_rows(datasource_id,
|
|
table_name)
|
|
results = datasource_rows_list['results']
|
|
datasource_rows = []
|
|
id = 0
|
|
for row in results:
|
|
new_row = PolicyAPIDictWrapper(row)
|
|
new_row.set_id_if_empty(id)
|
|
id += 1
|
|
datasource_rows.append(new_row)
|
|
return datasource_rows
|
|
|
|
|
|
def datasource_schema_get(request, datasource_id):
|
|
"""Get the schema for all tables in the given data source."""
|
|
client = congressclient(request)
|
|
return client.show_datasource_schema(datasource_id)
|
|
|
|
|
|
def datasource_table_schema_get(request, datasource_id, table_name):
|
|
"""Get the schema for a data source table."""
|
|
client = congressclient(request)
|
|
return client.show_datasource_table_schema(datasource_id, table_name)
|
|
|
|
|
|
def datasource_table_schema_get_by_name(request, datasource_name, table_name):
|
|
"""Get the schema for a data source table."""
|
|
datasource = datasource_get_by_name(request, datasource_name)
|
|
client = congressclient(request)
|
|
return client.show_datasource_table_schema(datasource['id'], table_name)
|
|
|
|
|
|
def datasource_statuses_list(request):
|
|
client = congressclient(request)
|
|
datasources_list = client.list_datasources()
|
|
datasources = datasources_list['results']
|
|
ds_status = []
|
|
|
|
for ds in datasources:
|
|
try:
|
|
status = client.list_datasource_status(ds['id'])
|
|
except Exception:
|
|
LOG.exception("Exception while getting the status")
|
|
raise
|
|
wrapper = PolicyAPIDictWrapper(ds)
|
|
wrapper.set_value('service', ds['name'])
|
|
for key in status:
|
|
value = status[key]
|
|
wrapper.set_value(key, value)
|
|
ds_status.append(wrapper)
|
|
return ds_status
|