230 lines
6.4 KiB
Python
230 lines
6.4 KiB
Python
# Copyright 2015 - Mirantis, Inc.
|
|
#
|
|
# 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.
|
|
|
|
import argparse
|
|
import collections
|
|
import inspect
|
|
import json
|
|
import os
|
|
|
|
from cinderclient import utils as cinder_base
|
|
from cinderclient.v2 import client as cinderclient
|
|
from glanceclient.v2 import client as glanceclient
|
|
from heatclient.openstack.common.apiclient import base as heat_base
|
|
from heatclient.v1 import client as heatclient
|
|
from keystoneclient import base as keystone_base
|
|
from keystoneclient.v3 import client as keystoneclient
|
|
from novaclient.openstack.common.apiclient import base as nova_base
|
|
from novaclient import client as novaclient
|
|
|
|
|
|
# TODO(nmakhotkin): Find a rational way to do it for neutron.
|
|
# TODO(nmakhotkin): Implement recursive way of searching for managers
|
|
# TODO(nmakhotkin): (e.g. keystone).
|
|
|
|
"""It is simple CLI tool which allows to see and update mapping.json file
|
|
if needed. mapping.json contains all allowing OpenStack actions sorted by
|
|
service name. Usage example:
|
|
|
|
python tools/get_action_list.py nova
|
|
|
|
The result will be simple JSON containing action name as a key and method
|
|
path as a value. For updating mapping.json it is need to copy all keys and
|
|
values of the result to corresponding section of mapping.json:
|
|
|
|
...mapping.json...
|
|
"nova": {
|
|
<put it here>
|
|
},
|
|
...mapping.json...
|
|
|
|
|
|
Note: in case of Keystone service, correct OS_AUTH_URL v3 and the rest auth
|
|
info must be provided. It can be provided either via environment variables
|
|
or CLI arguments. See --help for details.
|
|
"""
|
|
|
|
BASE_HEAT_MANAGER = heat_base.HookableMixin
|
|
BASE_NOVA_MANAGER = nova_base.HookableMixin
|
|
BASE_KEYSTONE_MANAGER = keystone_base.Manager
|
|
BASE_CINDER_MANAGER = cinder_base.HookableMixin
|
|
|
|
|
|
def get_parser():
|
|
parser = argparse.ArgumentParser(
|
|
description='Gets All needed methods of OpenStack clients.',
|
|
usage="python get_action_list.py <service_name>"
|
|
)
|
|
parser.add_argument(
|
|
'service',
|
|
choices=['nova', 'glance', 'heat', 'cinder', 'keystone'],
|
|
help='Service name which methods need to be found.'
|
|
)
|
|
parser.add_argument(
|
|
'--os-username',
|
|
dest='username',
|
|
default=os.environ.get('OS_USERNAME', 'admin'),
|
|
help='Authentication username (Env: OS_USERNAME)'
|
|
)
|
|
parser.add_argument(
|
|
'--os-password',
|
|
dest='password',
|
|
default=os.environ.get('OS_PASSWORD', 'openstack'),
|
|
help='Authentication password (Env: OS_PASSWORD)'
|
|
)
|
|
parser.add_argument(
|
|
'--os-tenant-name',
|
|
dest='tenant_name',
|
|
default=os.environ.get('OS_TENANT_NAME', 'Default'),
|
|
help='Authentication tenant name (Env: OS_TENANT_NAME)'
|
|
)
|
|
parser.add_argument(
|
|
'--os-auth-url',
|
|
dest='auth_url',
|
|
default=os.environ.get('OS_AUTH_URL'),
|
|
help='Authentication URL (Env: OS_AUTH_URL)'
|
|
)
|
|
|
|
return parser
|
|
|
|
|
|
GLANCE_NAMESPACE_LIST = [
|
|
'image_members', 'image_tags', 'images', 'schemas', 'tasks'
|
|
]
|
|
|
|
|
|
def get_nova_client(**kwargs):
|
|
return novaclient.Client(2)
|
|
|
|
|
|
def get_keystone_client(**kwargs):
|
|
return keystoneclient.Client(**kwargs)
|
|
|
|
|
|
def get_glance_client(**kwargs):
|
|
return glanceclient.Client(kwargs.get('auth_url'))
|
|
|
|
|
|
def get_heat_client(**kwargs):
|
|
return heatclient.Client('')
|
|
|
|
|
|
def get_cinder_client(**kwargs):
|
|
return cinderclient.Client()
|
|
|
|
|
|
CLIENTS = {
|
|
'nova': get_nova_client,
|
|
'heat': get_heat_client,
|
|
'cinder': get_cinder_client,
|
|
'keystone': get_keystone_client,
|
|
'glance': get_glance_client,
|
|
# 'neutron': get_nova_client
|
|
}
|
|
BASE_MANAGERS = {
|
|
'nova': BASE_NOVA_MANAGER,
|
|
'heat': BASE_HEAT_MANAGER,
|
|
'cinder': BASE_CINDER_MANAGER,
|
|
'keystone': BASE_KEYSTONE_MANAGER,
|
|
'glance': None,
|
|
# 'neutron': BASE_NOVA_MANAGER
|
|
}
|
|
NAMESPACES = {
|
|
'glance': GLANCE_NAMESPACE_LIST
|
|
}
|
|
ALLOWED_ATTRS = ['service_catalog', 'catalog']
|
|
FORBIDDEN_METHODS = [
|
|
'add_hook', 'alternate_service_type', 'completion_cache', 'run_hooks',
|
|
'write_to_completion_cache', 'model', 'build_key_only_query', 'build_url',
|
|
'head', 'put'
|
|
]
|
|
|
|
|
|
def get_public_attrs(obj):
|
|
all_attrs = dir(obj)
|
|
|
|
return [a for a in all_attrs if not a.startswith('_')]
|
|
|
|
|
|
def get_public_methods(attr, client):
|
|
hierarchy_list = attr.split('.')
|
|
attribute = client
|
|
|
|
for attr in hierarchy_list:
|
|
attribute = getattr(attribute, attr)
|
|
all_attributes_list = get_public_attrs(attribute)
|
|
|
|
methods = []
|
|
for a in all_attributes_list:
|
|
allowed = a in ALLOWED_ATTRS
|
|
forbidden = a in FORBIDDEN_METHODS
|
|
|
|
if (not forbidden and
|
|
(allowed or inspect.ismethod(getattr(attribute, a)))):
|
|
methods.append(a)
|
|
|
|
return methods
|
|
|
|
|
|
def get_manager_list(service_name, client):
|
|
base_manager = BASE_MANAGERS[service_name]
|
|
|
|
if not base_manager:
|
|
return NAMESPACES[service_name]
|
|
|
|
public_attrs = get_public_attrs(client)
|
|
|
|
manager_list = []
|
|
|
|
for attr in public_attrs:
|
|
if (isinstance(getattr(client, attr), base_manager)
|
|
or attr in ALLOWED_ATTRS):
|
|
manager_list.append(attr)
|
|
|
|
return manager_list
|
|
|
|
|
|
def get_mapping_for_service(service, client):
|
|
mapping = collections.OrderedDict()
|
|
for man in get_manager_list(service, client):
|
|
public_methods = get_public_methods(man, client)
|
|
for method in public_methods:
|
|
key = "%s_%s" % (man, method)
|
|
value = "%s.%s" % (man, method)
|
|
mapping[key] = value
|
|
|
|
return mapping
|
|
|
|
|
|
def print_mapping(mapping):
|
|
print(json.dumps(mapping, indent=8, separators=(',', ': ')))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
args = get_parser().parse_args()
|
|
|
|
auth_info = {
|
|
'username': args.username,
|
|
'tenant_name': args.tenant_name,
|
|
'password': args.password,
|
|
'auth_url': args.auth_url
|
|
}
|
|
|
|
service = args.service
|
|
client = CLIENTS.get(service)(**auth_info)
|
|
|
|
print("Find methods for service: %s..." % service)
|
|
|
|
print_mapping(get_mapping_for_service(service, client))
|