def find_resource(manager, name_or_id): """Helper for the _find_* methods.""" # first try to get entity as integer id try: if isinstance(name_or_id, int) or name_or_id.isdigit(): return manager.get(int(name_or_id)) except exc.NotFound: pass # now try to get entity as uuid try: # This must be unicode for Python 3 compatibility. # If you pass a bytestring to uuid.UUID, you will get a TypeError uuid.UUID(encodeutils.safe_decode(name_or_id)) return manager.get(name_or_id) except (ValueError, exc.NotFound): pass # finally try to find entity by name matches = list(manager.list(filters={'name': name_or_id})) num_matches = len(matches) if num_matches == 0: msg = "No %s with a name or ID of '%s' exists." % \ (manager.resource_class.__name__.lower(), name_or_id) raise exc.CommandError(msg) elif num_matches > 1: msg = ("Multiple %s matches found for '%s', use an ID to be more" " specific." % (manager.resource_class.__name__.lower(), name_or_id)) raise exc.CommandError(msg) else: return matches[0]
def find_resource(manager, name_or_id): """Helper for the _find_* methods.""" # first try to get entity as integer id try: if isinstance(name_or_id, int) or name_or_id.isdigit(): return manager.get(int(name_or_id)) except exc.NotFound: pass # now try to get entity as uuid try: uuid.UUID(ensure_str(name_or_id)) return manager.get(name_or_id) except (ValueError, exc.NotFound): pass # finally try to find entity by name matches = list(manager.list(filters={'name': name_or_id})) num_matches = len(matches) if num_matches == 0: msg = "No %s with a name or ID of '%s' exists." % \ (manager.resource_class.__name__.lower(), name_or_id) raise exc.CommandError(msg) elif num_matches > 1: msg = ("Multiple %s matches found for '%s', use an ID to be more" " specific." % (manager.resource_class.__name__.lower(), name_or_id)) raise exc.CommandError(msg) else: return matches[0]
def _get_endpoint_and_token(self, args, force_auth=False): image_url = self._get_image_url(args) auth_token = args.os_auth_token auth_reqd = force_auth or (utils.is_authentication_required(args.func) and not (auth_token and image_url)) if not auth_reqd: endpoint = image_url token = args.os_auth_token else: if not args.os_username: raise exc.CommandError("You must provide a username via" " either --os-username or " "env[OS_USERNAME]") if not args.os_password: raise exc.CommandError("You must provide a password via" " either --os-password or " "env[OS_PASSWORD]") if not (args.os_tenant_id or args.os_tenant_name): raise exc.CommandError("You must provide a tenant_id via" " either --os-tenant-id or " "via env[OS_TENANT_ID]") if not args.os_auth_url: raise exc.CommandError("You must provide an auth url via" " either --os-auth-url or " "via env[OS_AUTH_URL]") kwargs = { 'username': args.os_username, 'password': args.os_password, 'tenant_id': args.os_tenant_id, 'tenant_name': args.os_tenant_name, 'auth_url': args.os_auth_url, 'service_type': args.os_service_type, 'endpoint_type': args.os_endpoint_type, 'cacert': args.os_cacert, 'insecure': args.insecure, 'region_name': args.os_region_name, } _ksclient = self._get_ksclient(**kwargs) token = args.os_auth_token or _ksclient.auth_token endpoint = args.os_image_url or self._get_endpoint( _ksclient, **kwargs) return endpoint, token
def main(self, argv): # Parse args once to find version #NOTE(flepied) Under Python3, parsed arguments are removed # from the list so make a copy for the first parsing base_argv = copy.deepcopy(argv) parser = self.get_base_parser() (options, args) = parser.parse_known_args(base_argv) # build available subcommands based on version api_version = options.os_image_api_version if api_version == '2': self._cache_schemas(options) subcommand_parser = self.get_subcommand_parser(api_version) self.parser = subcommand_parser # Handle top-level --help/-h before attempting to parse # a command off the command line if options.help or not argv: self.do_help(options) return 0 # Parse args again and call whatever callback was selected args = subcommand_parser.parse_args(argv) # Short-circuit and deal with help command right away. if args.func == self.do_help: self.do_help(args) return 0 LOG = logging.getLogger('glanceclient') LOG.addHandler(logging.StreamHandler()) LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) profile = osprofiler_profiler and options.profile if profile: osprofiler_profiler.init(options.profile) client = self._get_versioned_client(api_version, args, force_auth=False) try: args.func(client, args) except exc.Unauthorized: raise exc.CommandError("Invalid OpenStack Identity credentials.") except Exception: #NOTE(kragniz) Print any exceptions raised to stderr if the --debug # flag is set if args.debug: traceback.print_exc() raise finally: if profile: trace_id = osprofiler_profiler.get().get_base_id() print("Profiling trace ID: %s" % trace_id) print("To display trace use next command:\n" "osprofiler trace show --html %s " % trace_id)
def do_help(self, args, parser): """Display help about this program or one of its subcommands.""" command = getattr(args, 'command', '') if command: if args.command in self.subcommands: self.subcommands[args.command].print_help() else: raise exc.CommandError("'%s' is not a valid subcommand" % args.command) else: parser.print_help() if not args.os_image_api_version or args.os_image_api_version == '2': # NOTE(NiallBunting) This currently assumes that the only versions # are one and two. try: if command is None: print("\nRun `glance --os-image-api-version 1 help`" " for v1 help") else: self.get_subcommand_parser(1) if command in self.subcommands: command = ' ' + command print(("\nRun `glance --os-image-api-version 1 help%s`" " for v1 help") % (command or '')) except ImportError: pass
def _discover_auth_versions(self, session, auth_url): # discover the API versions the server is supporting base on the # given URL v2_auth_url = None v3_auth_url = None try: ks_discover = discover.Discover(session=session, url=auth_url) v2_auth_url = ks_discover.url_for('2.0') v3_auth_url = ks_discover.url_for('3.0') except ks_exc.ClientException as e: # Identity service may not support discover API version. # Lets trying to figure out the API version from the original URL. url_parts = urlparse.urlparse(auth_url) (scheme, netloc, path, params, query, fragment) = url_parts path = path.lower() if path.startswith('/v3'): v3_auth_url = auth_url elif path.startswith('/v2'): v2_auth_url = auth_url else: # not enough information to determine the auth version msg = ('Unable to determine the Keystone version ' 'to authenticate with using the given ' 'auth_url. Identity service may not support API ' 'version discovery. Please provide a versioned ' 'auth_url instead. error=%s') % (e) raise exc.CommandError(msg) return (v2_auth_url, v3_auth_url)
def _get_keystone_session(self, **kwargs): ks_session = session.Session.construct(kwargs) # discover the supported keystone versions using the given auth url auth_url = kwargs.pop('auth_url', None) (v2_auth_url, v3_auth_url) = self._discover_auth_versions(session=ks_session, auth_url=auth_url) # Determine which authentication plugin to use. First inspect the # auth_url to see the supported version. If both v3 and v2 are # supported, then use the highest version if possible. user_id = kwargs.pop('user_id', None) username = kwargs.pop('username', None) password = kwargs.pop('password', None) user_domain_name = kwargs.pop('user_domain_name', None) user_domain_id = kwargs.pop('user_domain_id', None) # project and tenant can be used interchangeably project_id = (kwargs.pop('project_id', None) or kwargs.pop('tenant_id', None)) project_name = (kwargs.pop('project_name', None) or kwargs.pop('tenant_name', None)) project_domain_id = kwargs.pop('project_domain_id', None) project_domain_name = kwargs.pop('project_domain_name', None) auth = None use_domain = (user_domain_id or user_domain_name or project_domain_id or project_domain_name) use_v3 = v3_auth_url and (use_domain or (not v2_auth_url)) use_v2 = v2_auth_url and not use_domain if use_v3: auth = v3_auth.Password(v3_auth_url, user_id=user_id, username=username, password=password, user_domain_id=user_domain_id, user_domain_name=user_domain_name, project_id=project_id, project_name=project_name, project_domain_id=project_domain_id, project_domain_name=project_domain_name) elif use_v2: auth = v2_auth.Password(v2_auth_url, username, password, tenant_id=project_id, tenant_name=project_name) else: # if we get here it means domain information is provided # (caller meant to use Keystone V3) but the auth url is # actually Keystone V2. Obviously we can't authenticate a V3 # user using V2. exc.CommandError("Credential and auth_url mismatch. The given " "auth_url is using Keystone V2 endpoint, which " "may not able to handle Keystone V3 credentials. " "Please provide a correct Keystone V3 auth_url.") ks_session.auth = auth return ks_session
def do_help(self, args): """Display help about this program or one of its subcommands.""" if getattr(args, 'command', None): if args.command in self.subcommands: self.subcommands[args.command].print_help() else: raise exc.CommandError("'%s' is not a valid subcommand" % args.command) else: self.parser.print_help()
def _get_kwargs_for_create_session(args): if not args.os_username: raise exc.CommandError( _("You must provide a username for %s" % args.name)) if not args.os_password: # No password, If we've got a tty, try prompting for it if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): # Check for Ctl-D try: args.os_password = getpass.getpass('OS Password for %s: ' % args.name) except EOFError: pass # No password because we didn't have a tty or the # user Ctl-D when prompted. if not args.os_password: raise exc.CommandError( _("You must provide a password for %s" % args.name)) if not args.os_auth_url: raise exc.CommandError( _("You must provide an auth url for %s" % args.name)) kwargs = { 'auth_url': args.os_auth_url, 'username': args.os_username, 'user_id': args.os_user_id, 'user_domain_id': args.os_user_domain_id, 'user_domain_name': args.os_user_domain_name, 'password': args.os_password, 'project_name': args.os_project_name, 'project_id': args.os_project_id, 'project_domain_name': args.os_project_domain_name, 'project_domain_id': args.os_project_domain_id, 'insecure': args.insecure, 'cacert': args.os_cacert, 'cert': args.os_cert, 'key': args.os_key } return kwargs
def func_wrapper(gc, args): # Set of arguments with data fields = set(a[0] for a in vars(args).items() if a[1]) # Fields the conditional requirements depend on present = fields.intersection(data_fields) # How many conditional requirements are missing missing = set(required) - fields # We use get_data_file to check if data is provided in stdin if (present or get_data_file(args)) and missing: msg = (_("error: Must provide %(req)s when using %(opt)s.") % {'req': prepare_fields(missing), 'opt': prepare_fields(present) or 'stdin'}) raise exc.CommandError(msg) return func(gc, args)
def do_help(self, args, parser): """Display help about this program or one of its subcommands.""" command = getattr(args, 'command', '') if command: if args.command in self.subcommands: self.subcommands[args.command].print_help() else: raise exc.CommandError("'%s' is not a valid subcommand" % args.command) command = ' ' + command else: parser.print_help() if not args.os_image_api_version or args.os_image_api_version == '2': print(("\nRun `glance --os-image-api-version 1 help%s`" " for v1 help") % (command or ''))
def main(self, argv): # Parse args once to find version #NOTE(flepied) Under Python3, parsed arguments are removed # from the list so make a copy for the first parsing base_argv = copy.deepcopy(argv) parser = self.get_base_parser() (options, args) = parser.parse_known_args(base_argv) # build available subcommands based on version api_version = options.os_image_api_version if api_version == '2': self._cache_schema(options) subcommand_parser = self.get_subcommand_parser(api_version) self.parser = subcommand_parser # Handle top-level --help/-h before attempting to parse # a command off the command line if options.help or not argv: self.do_help(options) return 0 # Parse args again and call whatever callback was selected args = subcommand_parser.parse_args(argv) # Short-circuit and deal with help command right away. if args.func == self.do_help: self.do_help(args) return 0 LOG = logging.getLogger('glanceclient') LOG.addHandler(logging.StreamHandler()) LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) client = self._get_versioned_client(api_version, args, force_auth=False) try: args.func(client, args) except exc.Unauthorized: raise exc.CommandError("Invalid OpenStack Identity credentials.")
def do_image_delete(gc, args): """Delete specified image(s).""" for args_image in args.images: image = utils.find_resource(gc.images, args_image) if image and image.status == "deleted": msg = "No image with an ID of '%s' exists." % image.id raise exc.CommandError(msg) try: if args.verbose: print('Requesting image delete for %s ...' % encodeutils.safe_decode(args_image), end=' ') gc.images.delete(image) if args.verbose: print('[Done]') except exc.HTTPException as e: if args.verbose: print('[Fail]') print('%s: Unable to delete image %s' % (e, args_image))
def _cache_schemas(self, options, client, home_dir='~/.glanceclient'): homedir = os.path.expanduser(home_dir) path_prefix = homedir if options.os_auth_url: hash_host = hashlib.sha1(options.os_auth_url.encode('utf-8')) path_prefix = os.path.join(path_prefix, hash_host.hexdigest()) if not os.path.exists(path_prefix): try: os.makedirs(path_prefix) except OSError as e: # This avoids glanceclient to crash if it can't write to # ~/.glanceclient, which may happen on some env (for me, # it happens in Jenkins, as glanceclient can't write to # /var/lib/jenkins). msg = '%s' % e print(encodeutils.safe_decode(msg), file=sys.stderr) resources = ['image', 'metadefs/namespace', 'metadefs/resource_type'] schema_file_paths = [ os.path.join(path_prefix, x + '_schema.json') for x in ['image', 'namespace', 'resource_type'] ] failed_download_schema = 0 for resource, schema_file_path in zip(resources, schema_file_paths): if (not os.path.exists(schema_file_path)) or options.get_schema: try: schema = client.schemas.get(resource) with open(schema_file_path, 'w') as f: f.write(json.dumps(schema.raw())) except exc.Unauthorized: raise exc.CommandError( "Invalid OpenStack Identity credentials.") except Exception: # NOTE(esheffield) do nothing here, we'll get a message # later if the schema is missing failed_download_schema += 1 pass return failed_download_schema >= len(resources)
def find_resource(manager, name_or_id): """Helper for the _find_* methods.""" # first try to get entity as integer id try: if isinstance(name_or_id, int) or name_or_id.isdigit(): return manager.get(int(name_or_id)) except exc.NotFound: pass # now try to get entity as uuid try: uuid.UUID(str(name_or_id)) return manager.get(name_or_id) except (ValueError, exc.NotFound): pass # finally try to find entity by name try: return manager.find(name=name_or_id) except exc.NotFound: msg = "No %s with a name or ID of '%s' exists." % \ (manager.resource_class.__name__.lower(), name_or_id) raise exc.CommandError(msg)
def _get_kwargs_to_create_auth_plugin(self, args): if not args.os_username: raise exc.CommandError( _("You must provide a username via" " either --os-username or " "env[OS_USERNAME]")) if not args.os_password: # No password, If we've got a tty, try prompting for it if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): # Check for Ctl-D try: args.os_password = getpass.getpass('OS Password: '******'t have a tty or the # user Ctl-D when prompted. if not args.os_password: raise exc.CommandError( _("You must provide a password via " "either --os-password, " "env[OS_PASSWORD], " "or prompted response")) # Validate password flow auth os_project_name = getattr( args, 'os_project_name', getattr(args, 'os_tenant_name', None)) os_project_id = getattr( args, 'os_project_id', getattr(args, 'os_tenant_id', None)) if not any([os_project_name, os_project_id]): # tenant is deprecated in Keystone v3. Use the latest # terminology instead. raise exc.CommandError( _("You must provide a project_id or project_name (" "with project_domain_name or project_domain_id) " "via " " --os-project-id (env[OS_PROJECT_ID])" " --os-project-name (env[OS_PROJECT_NAME])," " --os-project-domain-id " "(env[OS_PROJECT_DOMAIN_ID])" " --os-project-domain-name " "(env[OS_PROJECT_DOMAIN_NAME])")) if not args.os_auth_url: raise exc.CommandError( _("You must provide an auth url via" " either --os-auth-url or " "via env[OS_AUTH_URL]")) kwargs = { 'auth_url': args.os_auth_url, 'username': args.os_username, 'user_id': args.os_user_id, 'user_domain_id': args.os_user_domain_id, 'user_domain_name': args.os_user_domain_name, 'password': args.os_password, 'tenant_name': args.os_tenant_name, 'tenant_id': args.os_tenant_id, 'project_name': args.os_project_name, 'project_id': args.os_project_id, 'project_domain_name': args.os_project_domain_name, 'project_domain_id': args.os_project_domain_id, } return kwargs
def main(self, argv): # Parse args once to find version # NOTE(flepied) Under Python3, parsed arguments are removed # from the list so make a copy for the first parsing base_argv = copy.deepcopy(argv) parser = self.get_base_parser() (options, args) = parser.parse_known_args(base_argv) span_host = tomograph.getHost() span_name = ' '.join(sys.argv) tomograph.start("glanceclient-shell", span_name, span_host, 0) try: # NOTE(flaper87): Try to get the version from the # image-url first. If no version was specified, fallback # to the api-image-version arg. If both of these fail then # fallback to the minimum supported one and let keystone # do the magic. endpoint = self._get_image_url(options) endpoint, url_version = utils.strip_version(endpoint) except ValueError: # NOTE(flaper87): ValueError is raised if no endpoint is povided url_version = None # build available subcommands based on version try: api_version = int(options.os_image_api_version or url_version or 2) if api_version not in SUPPORTED_VERSIONS: raise ValueError except ValueError: msg = ("Invalid API version parameter. " "Supported values are %s" % SUPPORTED_VERSIONS) utils.exit(msg=msg) if api_version == 2: switch_version = self._cache_schemas(options) if switch_version: print('WARNING: The client is falling back to v1 because' ' the accessing to v2 failed. This behavior will' ' be removed in future versions') api_version = 1 try: subcommand_parser = self.get_subcommand_parser(api_version) except ImportError as e: if options.debug: traceback.print_exc() if not str(e): # Add a generic import error message if the raised ImportError # has none. raise ImportError('Unable to import module. Re-run ' 'with --debug for more info.') raise except Exception: if options.debug: traceback.print_exc() raise self.parser = subcommand_parser # Handle top-level --help/-h before attempting to parse # a command off the command line if options.help or not argv: self.do_help(options) return 0 # Parse args again and call whatever callback was selected args = subcommand_parser.parse_args(argv) # Short-circuit and deal with help command right away. if args.func == self.do_help: self.do_help(args) return 0 elif args.func == self.do_bash_completion: self.do_bash_completion(args) return 0 LOG = logging.getLogger('glanceclient') LOG.addHandler(logging.StreamHandler()) LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) profile = osprofiler_profiler and options.profile if profile: osprofiler_profiler.init(options.profile) client = self._get_versioned_client(api_version, args, force_auth=False) try: # pdb.set_trace() args.func(client, args) except exc.Unauthorized: raise exc.CommandError("Invalid OpenStack Identity credentials.") except Exception: # NOTE(kragniz) Print any exceptions raised to stderr if the # --debug flag is set if args.debug: traceback.print_exc() raise finally: tomograph.stop(span_name) if profile: trace_id = osprofiler_profiler.get().get_base_id() print("Profiling trace ID: %s" % trace_id) print("To display trace use next command:\n" "osprofiler trace show --html %s " % trace_id)
def _get_endpoint_and_token(self, args, force_auth=False): image_url = self._get_image_url(args) auth_token = args.os_auth_token auth_reqd = force_auth or (utils.is_authentication_required(args.func) and not (auth_token and image_url)) if not auth_reqd: endpoint = image_url token = args.os_auth_token else: if not args.os_username: raise exc.CommandError( _("You must provide a username via" " either --os-username or " "env[OS_USERNAME]")) if not args.os_password: raise exc.CommandError( _("You must provide a password via" " either --os-password or " "env[OS_PASSWORD]")) # Validate password flow auth project_info = ( args.os_tenant_name or args.os_tenant_id or (args.os_project_name and (args.project_domain_name or args.project_domain_id)) or args.os_project_id) if (not project_info): # tenent is deprecated in Keystone v3. Use the latest # terminology instead. raise exc.CommandError( _("You must provide a project_id or project_name (" "with project_domain_name or project_domain_id) " "via " " --os-project-id (env[OS_PROJECT_ID])" " --os-project-name (env[OS_PROJECT_NAME])," " --os-project-domain-id " "(env[OS_PROJECT_DOMAIN_ID])" " --os-project-domain-name " "(env[OS_PROJECT_DOMAIN_NAME])")) if not args.os_auth_url: raise exc.CommandError( _("You must provide an auth url via" " either --os-auth-url or " "via env[OS_AUTH_URL]")) kwargs = { 'auth_url': args.os_auth_url, 'username': args.os_username, 'user_id': args.os_user_id, 'user_domain_id': args.os_user_domain_id, 'user_domain_name': args.os_user_domain_name, 'password': args.os_password, 'tenant_name': args.os_tenant_name, 'tenant_id': args.os_tenant_id, 'project_name': args.os_project_name, 'project_id': args.os_project_id, 'project_domain_name': args.os_project_domain_name, 'project_domain_id': args.os_project_domain_id, 'insecure': args.insecure, 'cacert': args.os_cacert, 'cert': args.os_cert, 'key': args.os_key } ks_session = self._get_keystone_session(**kwargs) token = args.os_auth_token or ks_session.get_token() endpoint_type = args.os_endpoint_type or 'public' service_type = args.os_service_type or 'image' endpoint = args.os_image_url or ks_session.get_endpoint( service_type=service_type, endpoint_type=endpoint_type, region_name=args.os_region_name) return endpoint, token
def main(self, argv): # Parse args once to find version #NOTE(flepied) Under Python3, parsed arguments are removed # from the list so make a copy for the first parsing base_argv = copy.deepcopy(argv) parser = self.get_base_parser() (options, args) = parser.parse_known_args(base_argv) try: # NOTE(flaper87): Try to get the version from the # image-url first. If no version was specified, fallback # to the api-image-version arg. If both of these fail then # fallback to the minimum supported one and let keystone # do the magic. endpoint = self._get_image_url(options) endpoint, url_version = utils.strip_version(endpoint) except ValueError: # NOTE(flaper87): ValueError is raised if no endpoint is povided url_version = None # build available subcommands based on version try: api_version = int(options.os_image_api_version or url_version or 1) except ValueError: print("Invalid API version parameter") utils.exit() if api_version == 2: self._cache_schemas(options) subcommand_parser = self.get_subcommand_parser(api_version) self.parser = subcommand_parser # Handle top-level --help/-h before attempting to parse # a command off the command line if options.help or not argv: self.do_help(options) return 0 # Parse args again and call whatever callback was selected args = subcommand_parser.parse_args(argv) # Short-circuit and deal with help command right away. if args.func == self.do_help: self.do_help(args) return 0 elif args.func == self.do_bash_completion: self.do_bash_completion(args) return 0 LOG = logging.getLogger('glanceclient') LOG.addHandler(logging.StreamHandler()) LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) profile = osprofiler_profiler and options.profile if profile: osprofiler_profiler.init(options.profile) client = self._get_versioned_client(api_version, args, force_auth=False) try: args.func(client, args) except exc.Unauthorized: raise exc.CommandError("Invalid OpenStack Identity credentials.") except Exception: #NOTE(kragniz) Print any exceptions raised to stderr if the --debug # flag is set if args.debug: traceback.print_exc() raise finally: if profile: trace_id = osprofiler_profiler.get().get_base_id() print("Profiling trace ID: %s" % trace_id) print("To display trace use next command:\n" "osprofiler trace show --html %s " % trace_id)
def main(self, argv): def _get_subparser(api_version): try: return self.get_subcommand_parser(api_version, argv) except ImportError as e: if not str(e): # Add a generic import error message if the raised # ImportError has none. raise ImportError('Unable to import module. Re-run ' 'with --debug for more info.') raise # Parse args once to find version # NOTE(flepied) Under Python3, parsed arguments are removed # from the list so make a copy for the first parsing base_argv = copy.deepcopy(argv) parser = self.get_base_parser(argv) (options, args) = parser.parse_known_args(base_argv) try: # NOTE(flaper87): Try to get the version from the # image-url first. If no version was specified, fallback # to the api-image-version arg. If both of these fail then # fallback to the minimum supported one and let keystone # do the magic. endpoint = self._get_image_url(options) endpoint, url_version = utils.strip_version(endpoint) except ValueError: # NOTE(flaper87): ValueError is raised if no endpoint is provided url_version = None # build available subcommands based on version try: api_version = int(options.os_image_api_version or url_version or 2) if api_version not in SUPPORTED_VERSIONS: raise ValueError except ValueError: msg = ("Invalid API version parameter. " "Supported values are %s" % SUPPORTED_VERSIONS) utils.exit(msg=msg) # Handle top-level --help/-h before attempting to parse # a command off the command line if options.help or not argv: parser = _get_subparser(api_version) self.do_help(options, parser=parser) return 0 # NOTE(sigmavirus24): Above, args is defined as the left over # arguments from parser.parse_known_args(). This allows us to # skip any parameters to command-line flags that may have been passed # to glanceclient, e.g., --os-auth-token. self._fixup_subcommand(args, argv) # short-circuit and deal with help command right away. sub_parser = _get_subparser(api_version) args = sub_parser.parse_args(argv) if args.func == self.do_help: self.do_help(args, parser=sub_parser) return 0 elif args.func == self.do_bash_completion: self.do_bash_completion(args) return 0 if not options.os_image_api_version and api_version == 2: switch_version = True client = self._get_versioned_client('2', args) resp, body = client.http_client.get('/versions') for version in body['versions']: if version['id'].startswith('v2'): # NOTE(flaper87): We know v2 is enabled in the server, # which means we should be able to get the schemas and # move on. switch_version = self._cache_schemas(options, client) break if switch_version: print('WARNING: The client is falling back to v1 because' ' the accessing to v2 failed. This behavior will' ' be removed in future versions', file=sys.stderr) api_version = 1 sub_parser = _get_subparser(api_version) # Parse args again and call whatever callback was selected args = sub_parser.parse_args(argv) # NOTE(flaper87): Make sure we re-use the password input if we # have one. This may happen if the schemas were downloaded in # this same command. Password will be asked to download the # schemas and then for the operations below. if not args.os_password and options.os_password: args.os_password = options.os_password if args.debug: # Set up the root logger to debug so that the submodules can # print debug messages logging.basicConfig(level=logging.DEBUG) # for iso8601 < 0.1.11 logging.getLogger('iso8601').setLevel(logging.WARNING) LOG = logging.getLogger('glanceclient') LOG.addHandler(logging.StreamHandler()) LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) profile = osprofiler_profiler and options.profile if profile: osprofiler_profiler.init(options.profile) client = self._get_versioned_client(api_version, args) try: args.func(client, args) except exc.Unauthorized: raise exc.CommandError("Invalid OpenStack Identity credentials.") finally: if profile: trace_id = osprofiler_profiler.get().get_base_id() print("Profiling trace ID: %s" % trace_id) print("To display trace use next command:\n" "osprofiler trace show --html %s " % trace_id)
def _get_endpoint_and_token(self, args): endpoint = self._get_image_url(args) auth_token = args.os_auth_token auth_req = (hasattr(args, 'func') and utils.is_authentication_required(args.func)) if auth_req and not (endpoint and auth_token): if not args.os_username: raise exc.CommandError( _("You must provide a username via" " either --os-username or " "env[OS_USERNAME]")) if not args.os_password: # No password, If we've got a tty, try prompting for it if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): # Check for Ctl-D try: args.os_password = getpass.getpass('OS Password: '******'t have a tty or the # user Ctl-D when prompted. if not args.os_password: raise exc.CommandError( _("You must provide a password via " "either --os-password, " "env[OS_PASSWORD], " "or prompted response")) # Validate password flow auth project_info = ( args.os_tenant_name or args.os_tenant_id or (args.os_project_name and (args.os_project_domain_name or args.os_project_domain_id)) or args.os_project_id) if not project_info: # tenant is deprecated in Keystone v3. Use the latest # terminology instead. raise exc.CommandError( _("You must provide a project_id or project_name (" "with project_domain_name or project_domain_id) " "via " " --os-project-id (env[OS_PROJECT_ID])" " --os-project-name (env[OS_PROJECT_NAME])," " --os-project-domain-id " "(env[OS_PROJECT_DOMAIN_ID])" " --os-project-domain-name " "(env[OS_PROJECT_DOMAIN_NAME])")) if not args.os_auth_url: raise exc.CommandError( _("You must provide an auth url via" " either --os-auth-url or " "via env[OS_AUTH_URL]")) kwargs = { 'auth_url': args.os_auth_url, 'username': args.os_username, 'user_id': args.os_user_id, 'user_domain_id': args.os_user_domain_id, 'user_domain_name': args.os_user_domain_name, 'password': args.os_password, 'tenant_name': args.os_tenant_name, 'tenant_id': args.os_tenant_id, 'project_name': args.os_project_name, 'project_id': args.os_project_id, 'project_domain_name': args.os_project_domain_name, 'project_domain_id': args.os_project_domain_id, 'insecure': args.insecure, 'cacert': args.os_cacert, 'cert': args.os_cert, 'key': args.os_key } ks_session = self._get_keystone_session(**kwargs) auth_token = args.os_auth_token or ks_session.get_token() endpoint_type = args.os_endpoint_type or 'public' service_type = args.os_service_type or 'image' endpoint = args.os_image_url or ks_session.get_endpoint( service_type=service_type, interface=endpoint_type, region_name=args.os_region_name) return endpoint, auth_token
def main(self, argv): # Parse args once to find version parser = self.get_base_parser() (options, args) = parser.parse_known_args(argv) # build available subcommands based on version api_version = options.os_image_api_version subcommand_parser = self.get_subcommand_parser(api_version) self.parser = subcommand_parser # Handle top-level --help/-h before attempting to parse # a command off the command line if options.help or not argv: self.do_help(options) return 0 # Parse args again and call whatever callback was selected args = subcommand_parser.parse_args(argv) # Short-circuit and deal with help command right away. if args.func == self.do_help: self.do_help(args) return 0 LOG = logging.getLogger('glanceclient') LOG.addHandler(logging.StreamHandler()) LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) image_url = self._get_image_url(args) auth_reqd = (utils.is_authentication_required(args.func) and not (args.os_auth_token and image_url)) if not auth_reqd: endpoint = image_url token = args.os_auth_token else: if not args.os_username: raise exc.CommandError("You must provide a username via" " either --os-username or " "env[OS_USERNAME]") if not args.os_password: raise exc.CommandError("You must provide a password via" " either --os-password or " "env[OS_PASSWORD]") if not (args.os_tenant_id or args.os_tenant_name): raise exc.CommandError("You must provide a tenant_id via" " either --os-tenant-id or " "via env[OS_TENANT_ID]") if not args.os_auth_url: raise exc.CommandError("You must provide an auth url via" " either --os-auth-url or " "via env[OS_AUTH_URL]") kwargs = { 'username': args.os_username, 'password': args.os_password, 'tenant_id': args.os_tenant_id, 'tenant_name': args.os_tenant_name, 'auth_url': args.os_auth_url, 'service_type': args.os_service_type, 'endpoint_type': args.os_endpoint_type, 'cacert': args.os_cacert, 'insecure': args.insecure, 'region_name': args.os_region_name, } _ksclient = self._get_ksclient(**kwargs) token = args.os_auth_token or _ksclient.auth_token endpoint = args.os_image_url or \ self._get_endpoint(_ksclient, **kwargs) kwargs = { 'token': token, 'insecure': args.insecure, 'timeout': args.timeout, 'cacert': args.os_cacert, 'cert_file': args.cert_file, 'key_file': args.key_file, 'ssl_compression': args.ssl_compression } client = glanceclient.Client(api_version, endpoint, **kwargs) try: args.func(client, args) except exc.Unauthorized: raise exc.CommandError("Invalid OpenStack Identity credentials.")