import argparse import orm.base_config as base_config import os import requests from . import cli_common from . import config class ResponseError(Exception): pass class ConnectionError(Exception): pass def add_to_parser(service_sub): parser = \ service_sub.add_parser('fms', help='Flavor Management Service', formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=30, width=120)) parser.add_argument('--version', action='version', version='%(prog)s 1.0') parser.add_argument('--auth-region', type=str, help='Region used for authentication', default=get_environment_variable('auth-region')) parser.add_argument('--keystone-auth-url', type=str, help='keystone-auth-url used for authentication', default=get_environment_variable('keystone-auth-url')) parser.add_argument('--tenant-name', type=str, help='Keystone user tenant name', default=get_environment_variable('tenant-name')) parser.add_argument('--username', type=str, help='Keystone user name', default=get_environment_variable('username')) parser.add_argument('--user-domain', type=str, help='Keystone user domain', default=get_environment_variable('user-domain')) parser.add_argument('--password', type=str, help='Keystone user password', default=get_environment_variable('password')) parser.add_argument('--project-domain', type=str, help='Keystone project domain', default=get_environment_variable('project-domain')) parser.add_argument('--rms-base-url', type=str, help='RMS base URL', default=get_environment_variable('rms-base-url')) parser.add_argument('--fms-base-url', type=str, help='FMS base URL', default=get_environment_variable('fms-base-url')) parser.add_argument('--tracking_id', type=str, help='tracking id') parser.add_argument('--port', type=int, help='port number of FMS 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=argparse.SUPPRESS, default=False, action="store_true") subparsers = parser.add_subparsers(dest='subcmd', metavar=' [-h] ') # flavor h1, h2 = ('[<"X-RANGER-Client" header>]', '') parser_create_flavor = subparsers.add_parser('create_flavor', help='%s %s' % (h1, h2)) parser_create_flavor.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_create_flavor.add_argument('datafile', type=argparse.FileType('r'), help=h2) h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '', '',) parser_add_tags = subparsers.add_parser('add_tags', help='%s %s %s' % (h1, h2, h3)) parser_add_tags.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_add_tags.add_argument('flavorid', type=str, help=h2) parser_add_tags.add_argument('datafile', type=argparse.FileType('r'), help=h3) h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '', '',) parser_replace_tags = subparsers.add_parser('replace_tags', help='%s %s %s' % (h1, h2, h3)) parser_replace_tags.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_replace_tags.add_argument('flavorid', type=str, help=h2) parser_replace_tags.add_argument('datafile', type=argparse.FileType('r'), help=h3) h1, h2, h3 = '[<"X-RANGER-Client" header>]', '', '' parser_delete_tag = subparsers.add_parser('delete_tag', help='%s %s %s' % (h1, h2, h3)) parser_delete_tag.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_delete_tag.add_argument('flavorid', type=str, help=h2) parser_delete_tag.add_argument('tagname', type=str, help=h3) h1, h2 = '[<"X-RANGER-Client" header>]', '' parser_delete_all_tags = subparsers.add_parser('delete_all_tags', help='%s %s' % (h1, h2)) parser_delete_all_tags.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_delete_all_tags.add_argument('flavorid', type=str, help=h2) h1, h2 = '[<"X-RANGER-Client" header>]', '' parser_get_tags = subparsers.add_parser('get_tags', help='%s %s' % (h1, h2)) parser_get_tags.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_get_tags.add_argument('flavorid', type=str, help=h2) # extra specs h1, h2 = '[<"X-RANGER-Client" header>]', '' parser_get_extra_specs = subparsers.add_parser('get_extra_specs', help='%s %s' % (h1, h2)) parser_get_extra_specs.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_get_extra_specs.add_argument('flavorid', type=str, help=h2) h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '', '',) parser_replace_extra_specs = subparsers.add_parser('replace_extra_specs', help='%s %s %s' % (h1, h2, h3)) parser_replace_extra_specs.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_replace_extra_specs.add_argument('flavorid', type=str, help=h2) parser_replace_extra_specs.add_argument('datafile', type=argparse.FileType('r'), help=h3) h1, h2 = '[<"X-RANGER-Client" header>]', '' parser_delete_all_extra_specs = subparsers.add_parser( 'delete_all_extra_specs', help='%s %s' % (h1, h2)) parser_delete_all_extra_specs.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_delete_all_extra_specs.add_argument('flavorid', type=str, help=h2) h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '', '',) parser_delete_extra_spec = subparsers.add_parser('delete_extra_spec', help='%s %s %s' % ( h1, h2, h3)) parser_delete_extra_spec.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_delete_extra_spec.add_argument('flavorid', type=str, help=h2) parser_delete_extra_spec.add_argument('eskeyname', type=str, help=h3) h1, h2, h3 = ('[<"X-RANGER-Client" header>]', '', '',) parser_add_extra_specs = subparsers.add_parser('add_extra_specs', help='%s %s %s' % ( h1, h2, h3)) parser_add_extra_specs.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_add_extra_specs.add_argument('flavorid', type=str, help=h2) parser_add_extra_specs.add_argument('datafile', type=argparse.FileType('r'), help=h3) h1, h2 = '[<"X-RANGER-Client" header>]', '' parser_delete_flavor = subparsers.add_parser('delete_flavor', help='%s %s' % (h1, h2)) 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>]', '' parser_get_flavor = subparsers.add_parser('get_flavor', help='%s %s' % (h1, h2)) parser_get_flavor.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_get_flavor.add_argument('flavorid', type=str, help=h2) h1, h2 = ('[<"X-RANGER-Client" header>]', '[--visibility ] [--region ] [--tenant ' '] [--series ] [--alias ] ' '[--starts_with ] [--contains ] ' '[--vm_type ] [--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) parser_list_flavor.add_argument('--visibility', type=str, choices=['public', 'private']) parser_list_flavor.add_argument('--region', type=str, help='region name') parser_list_flavor.add_argument('--tenant', type=str, help='tenant id') parser_list_flavor.add_argument('--starts_with', type=str, help='flavor name starts with *') parser_list_flavor.add_argument('--contains', type=str, help='* contains in flavor name') parser_list_flavor.add_argument('--series', type=str, help='series name') 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>]', '', '',) parser_add_region = subparsers.add_parser('add_region', help='%s %s %s' % (h1, h2, h3)) parser_add_region.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_add_region.add_argument('flavorid', type=str, help=h2) parser_add_region.add_argument('datafile', type=argparse.FileType('r'), help=h3) h1, h2, h3 = '[<"X-RANGER-Client" header>] [--force_delete]', \ '', '' 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>]', '', '',) parser_add_tenant = subparsers.add_parser('add_tenant', help='%s %s %s' % (h1, h2, h3)) parser_add_tenant.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_add_tenant.add_argument('flavorid', type=str, help=h2) parser_add_tenant.add_argument('datafile', type=argparse.FileType('r'), help=h3) h1, h2, h3 = '[<"X-RANGER-Client" header>]', '', '' parser_delete_tenant = subparsers.add_parser('delete_tenant', help='%s %s %s' % ( h1, h2, h3)) parser_delete_tenant.add_argument('client', **cli_common.ORM_CLIENT_KWARGS) parser_delete_tenant.add_argument('flavorid', type=str, help=h2) parser_delete_tenant.add_argument('tenantid', type=str, help=h3) def preparm(p): return ('' if len(p) else '?') + ('&' if len(p) else '') def cmd_details(args): if args.subcmd == 'create_flavor': return requests.post, '' elif args.subcmd == 'update_flavor': return requests.put, '/%s' % args.flavorid elif args.subcmd == 'delete_flavor': return requests.delete, '/%s' % args.flavorid elif args.subcmd == 'add_region': return requests.post, '/%s/regions' % args.flavorid elif args.subcmd == 'add_tags': return requests.post, '/%s/tags' % args.flavorid elif args.subcmd == 'replace_tags': return requests.put, '/%s/tags' % args.flavorid elif args.subcmd == 'delete_tag': return requests.delete, '/%s/tags/%s' % (args.flavorid, args.tagname) elif args.subcmd == 'delete_all_tags': return requests.delete, '/%s/tags' % args.flavorid elif args.subcmd == 'get_tags': return requests.get, '/%s/tags' % args.flavorid elif args.subcmd == 'delete_region': 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': return requests.delete, '/%s/tenants/%s' % ( args.flavorid, args.tenantid) elif args.subcmd == 'get_flavor': return requests.get, '/%s' % args.flavorid elif args.subcmd == 'get_extra_specs': return requests.get, '/%s/os_extra_specs' % args.flavorid elif args.subcmd == 'delete_all_extra_specs': return requests.delete, '/%s/os_extra_specs' % args.flavorid elif args.subcmd == 'delete_extra_spec': return requests.delete, '/%s/os_extra_specs/%s' % ( args.flavorid, args.eskeyname) elif args.subcmd == 'add_extra_specs': return requests.post, '/%s/os_extra_specs' % args.flavorid elif args.subcmd == 'replace_extra_specs': return requests.put, '/%s/os_extra_specs' % args.flavorid elif args.subcmd == 'list_flavors': param = '' if args.visibility: param += '%svisibility=%s' % (preparm(param), args.visibility) if args.region: param += '%sregion=%s' % (preparm(param), args.region) if args.tenant: 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: param += '%scontains=%s' % (preparm(param), args.contains) if args.alias: param += '%salias=%s' % (preparm(param), args.alias) return requests.get, '/%s' % param def validate_args(args): for argument in ('tenant_name', 'username', 'password', 'auth_region', 'keystone_auth_url'): argument_value = getattr(args, argument, None) if argument_value is not None: globals()[argument] = argument_value else: configuration_value = getattr(config, argument) if configuration_value: globals()[argument] = configuration_value else: message = ('ERROR: {} for token generation was not supplied. ' 'Please use its command-line argument or ' 'environment variable.'.format(argument)) print(message) raise cli_common.MissingArgumentError(message) def get_environment_variable(argument): # The rules are: all caps, underscores instead of dashes and prefixed environment_variable = 'RANGER_{}'.format( argument.replace('-', '_').upper()) return os.environ.get(environment_variable) def run(args): host = args.fms_base_url if args.fms_base_url else \ base_config.fms['base_url'] port = args.port if args.port else base_config.fms['port'] data = args.datafile.read() if 'datafile' in args else '{}' timeout = args.timeout if args.timeout else 10 rest_cmd, cmd_url = cmd_details(args) url = '%s/v1/orm/flavors' % (host) + cmd_url if args.faceless: auth_key = auth_region = requester = client = '' else: try: validate_args(args) auth_key = cli_common.get_token(timeout, args) except Exception: exit(1) auth_region = globals()['auth_region'] requester = globals()['username'] client = requester tracking_id = args.tracking_id if args.tracking_id else None headers = { 'content-type': 'application/json', 'X-Auth-Token': auth_key, 'X-Auth-Region': auth_region, 'X-RANGER-Requester': requester, 'X-RANGER-Client': client, 'X-RANGER-Tracking-Id': tracking_id } if args.verbose: print(( "Sending API:\ntimeout: %d\ndata: %s\nheaders: %s\ncmd: %s\nurl:" " %s\n" % ( timeout, data, headers, rest_cmd.__name__, url))) try: resp = rest_cmd(url, timeout=timeout, data=data, headers=headers, verify=config.verify) except Exception as e: print(e) exit(1) if not 200 <= resp.status_code < 300: content = resp.content print('API error: %s %s (Reason: %d)\n%s' % ( rest_cmd.__name__.upper(), url, resp.status_code, content)) exit(1) if resp.status_code == 204: # no content exit(0) rj = resp.json() if rj == 'Not found': print('No output was found') else: cli_common.pretty_print_json(rj)