def test_image_reserve_options(self): mock_exception = { 'find.side_effect': exceptions.CommandError('x'), 'get.side_effect': exceptions.CommandError('x'), } self.images_mock.configure_mock(**mock_exception) arglist = [ '--container-format', 'ovf', '--disk-format', 'fs', '--min-disk', '10', '--min-ram', '4', '--protected', '--private', image_fakes.image_name, ] verifylist = [ ('container_format', 'ovf'), ('disk_format', 'fs'), ('min_disk', 10), ('min_ram', 4), ('protected', True), ('unprotected', False), ('public', False), ('private', True), ('name', image_fakes.image_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # DisplayCommandBase.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # ImageManager.create(name=, **) self.images_mock.create.assert_called_with( name=image_fakes.image_name, container_format='ovf', disk_format='fs', min_disk=10, min_ram=4, protected=True, is_public=False, data=mock.ANY, ) # Verify update() was not called, if it was show the args self.assertEqual(self.images_mock.update.call_args_list, []) self.assertEqual(image_fakes.IMAGE_columns, columns) self.assertEqual(image_fakes.IMAGE_data, data)
def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.data_processing if parsed_args.json: blob = osc_utils.read_blob_file_contents(parsed_args.json) try: template = jsonutils.loads(blob) except ValueError as e: raise exceptions.CommandError('An error occurred when reading ' 'template from file %s: %s' % (parsed_args.json, e)) data = client.job_binaries.create(**template).to_dict() else: if parsed_args.data: data = open(parsed_args.data).read() jbi_id = client.job_binary_internals.create( parsed_args.name, data).id parsed_args.url = 'internal-db://' + jbi_id if parsed_args.password_prompt: parsed_args.password = osc_utils.get_password(self.app.stdin, confirm=False) if parsed_args.password and not parsed_args.username: raise exceptions.CommandError( 'Username via --username should be provided with password') if parsed_args.username and not parsed_args.password: raise exceptions.CommandError( 'Password should be provided via --password or entered ' 'interactively with --password-prompt') if parsed_args.password and parsed_args.username: extra = { 'user': parsed_args.username, 'password': parsed_args.password } else: extra = None data = client.job_binaries.create( name=parsed_args.name, url=parsed_args.url, description=parsed_args.description, extra=extra, is_public=parsed_args.public, is_protected=parsed_args.protected).to_dict() data = utils.prepare_data(data, JOB_BINARY_FIELDS) return self.dict2columns(data)
def get_password(stdin): if hasattr(stdin, 'isatty') and stdin.isatty(): try: while True: first_pass = getpass.getpass("User password: "******"Repeat user password: "******"The passwords entered were not the same") except EOFError: # Ctl-D raise exceptions.CommandError("Error reading password.") raise exceptions.CommandError("There was a request to be prompted for a" " password and a terminal was not detected.")
def take_action(self, parsed_args): self.log.debug('take_action(%s)' % parsed_args) identity_client = self.app.client_manager.identity if not parsed_args.all: # Find endpoint filtered by a specific attribute or service type kwargs = { 'service_type': parsed_args.service, 'endpoint_type': parsed_args.type, } if parsed_args.attr and parsed_args.value: kwargs.update({ 'attr': parsed_args.attr, 'filter_value': parsed_args.value, }) elif parsed_args.attr or parsed_args.value: msg = 'Both --attr and --value required' raise exceptions.CommandError(msg) url = identity_client.service_catalog.url_for(**kwargs) info = {'%s.%s' % (parsed_args.service, parsed_args.type): url} return zip(*sorted(six.iteritems(info))) else: # The Identity 2.0 API doesn't support retrieving a single # endpoint so we have to do this ourselves try: service = utils.find_resource(identity_client.services, parsed_args.service) except exceptions.CommandError: try: # search for service type service = identity_client.services.find( type=parsed_args.service) # FIXME(dtroyer): This exception should eventually come from # common client exceptions except identity_exc.NotFound: msg = "No service with a type, name or ID of '%s' exists" \ % parsed_args.service raise exceptions.CommandError(msg) data = identity_client.endpoints.list() for ep in data: if ep.service_id == service.id: info = {} info.update(ep._info) service = utils.find_resource(identity_client.services, ep.service_id) info['service_name'] = service.name info['service_type'] = service.type return zip(*sorted(six.iteritems(info)))
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) client = self.app.client_manager.orchestration if not parsed_args.all and parsed_args.output is None: msg = _('Either <OUTPUT NAME> or --all must be specified.') raise exc.CommandError(msg) if parsed_args.all and parsed_args.output is not None: msg = _('Cannot specify both <OUTPUT NAME> and --all.') raise exc.CommandError(msg) if parsed_args.all: try: stack = client.stacks.get(parsed_args.stack) except heat_exc.HTTPNotFound: msg = _('Stack not found: %s') % parsed_args.stack raise exc.CommandError(msg) outputs = stack.to_dict().get('outputs', []) columns = [] values = [] for output in outputs: columns.append(output['output_key']) values.append(heat_utils.json_formatter(output)) return columns, values try: output = client.stacks.output_show(parsed_args.stack, parsed_args.output)['output'] except heat_exc.HTTPNotFound: msg = _('Stack %(id)s or output %(out)s not found.') % { 'id': parsed_args.stack, 'out': parsed_args.output } raise exc.CommandError(msg) if 'output_error' in output: msg = _('Output error: %s') % output['output_error'] raise exc.CommandError(msg) if (isinstance(output['output_value'], list) or isinstance(output['output_value'], dict)): output['output_value'] = heat_utils.json_formatter( output['output_value']) return self.dict2columns(output)
def get_resource(manager, name_or_id): resource = utils.find_resource(manager, name_or_id) if isinstance(resource, list): if not resource: msg = "No %s with a name or ID of '%s' exists." % \ (manager.resource_class.__name__.lower(), name_or_id) raise exceptions.CommandError(msg) if len(resource) > 1: msg = "More than one %s exists with the name '%s'." % \ (manager.resource_class.__name__.lower(), name_or_id) raise exceptions.CommandError(msg) return resource[0] else: return resource
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) client = self.app.client_manager.orchestration config = {} if parsed_args.config: try: config = client.software_configs.get(parsed_args.config) except heat_exc.HTTPNotFound: msg = (_('Software configuration not found: %s') % parsed_args.config) raise exc.CommandError(msg) derived_params = deployment_utils.build_derived_config_params( parsed_args.action, config, parsed_args.name, heat_utils.format_parameters(parsed_args.input_value, False), parsed_args.server, parsed_args.signal_transport, signal_id=deployment_utils.build_signal_id(client, parsed_args)) derived_config = client.software_configs.create(**derived_params) sd = client.software_deployments.create(config_id=derived_config.id, server_id=parsed_args.server, action=parsed_args.action, status='IN_PROGRESS') return zip(*sorted(sd.to_dict().items()))
def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.data_processing cluster_id = utils.get_resource_id(client.clusters, parsed_args.cluster) shares = None if parsed_args.shares: blob = osc_utils.read_blob_file_contents(parsed_args.shares) try: shares = json.loads(blob) except ValueError as e: raise exceptions.CommandError('An error occurred when reading ' 'shares from file %s: %s' % (parsed_args.shares, e)) update_dict = utils.create_dict_from_kwargs( name=parsed_args.name, description=parsed_args.description, is_public=parsed_args.is_public, is_protected=parsed_args.is_protected, shares=shares) data = client.clusters.update(cluster_id, **update_dict).cluster _format_cluster_output(data) data = utils.prepare_data(data, CLUSTER_FIELDS) return self.dict2columns(data)
def select_auth_plugin(options): """If no auth plugin was specified, pick one based on other options""" auth_plugin = None if options.os_url and options.os_token: # service token authentication auth_plugin = 'token_endpoint' elif options.os_password: if options.os_identity_api_version == '3': auth_plugin = 'v3password' elif options.os_identity_api_version == '2.0': auth_plugin = 'v2password' else: # let keystoneclient figure it out itself auth_plugin = 'password' elif options.os_token: if options.os_identity_api_version == '3': auth_plugin = 'v3token' elif options.os_identity_api_version == '2.0': auth_plugin = 'v2token' else: # let keystoneclient figure it out itself auth_plugin = 'token' else: raise exc.CommandError( "Could not figure out which authentication method " "to use, please set --os-auth-plugin" ) LOG.debug("No auth plugin selected, picking %s from other " "options" % auth_plugin) return auth_plugin
def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering try: if not parsed_args.force and sys.stdin.isatty(): sys.stdout.write( _("Are you sure you want to delete this profile(s)" " [y/N]?")) prompt_response = sys.stdin.readline().lower() if not prompt_response.startswith('y'): return except KeyboardInterrupt: # Ctrl-c self.log.info(_LI('Ctrl-c detected.')) return except EOFError: # Ctrl-d self.log.info(_LI('Ctrl-d detected')) return failure_count = 0 for pid in parsed_args.profile: try: senlin_client.delete_profile(pid, False) except Exception as ex: failure_count += 1 print(ex) if failure_count: raise exc.CommandError( _('Failed to delete %(count)s of the ' '%(total)s specified profile(s).') % { 'count': failure_count, 'total': len(parsed_args.profile) }) print('Profile deleted: %s' % parsed_args.profile)
def test_image_reserve_no_options(self): mock_exception = { 'find.side_effect': exceptions.CommandError('x'), } self.images_mock.configure_mock(**mock_exception) arglist = [ image_fakes.image_name, ] verifylist = [ ('container_format', image.DEFAULT_CONTAINER_FORMAT), ('disk_format', image.DEFAULT_DISK_FORMAT), ('name', image_fakes.image_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) # DisplayCommandBase.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) # ImageManager.create(name=, **) self.images_mock.create.assert_called_with( name=image_fakes.image_name, container_format=image.DEFAULT_CONTAINER_FORMAT, disk_format=image.DEFAULT_DISK_FORMAT, ) # Verify update() was not called, if it was show the args self.assertEqual(self.images_mock.update.call_args_list, []) self.images_mock.upload.assert_called_with( mock.ANY, mock.ANY, ) self.assertEqual(image_fakes.IMAGE_columns, columns) self.assertEqual(image_fakes.IMAGE_SHOW_data, data)
def select_auth_plugin(options): """Pick an auth plugin based on --os-auth-type or other options""" auth_plugin_name = None if options.os_auth_type in [plugin.name for plugin in PLUGIN_LIST]: # A direct plugin name was given, use it return options.os_auth_type if options.os_url and options.os_token: # service token authentication auth_plugin_name = 'token_endpoint' elif options.os_username: if options.os_identity_api_version == '3': auth_plugin_name = 'v3password' elif options.os_identity_api_version == '2.0': auth_plugin_name = 'v2password' else: # let keystoneclient figure it out itself auth_plugin_name = 'password' elif options.os_token: if options.os_identity_api_version == '3': auth_plugin_name = 'v3token' elif options.os_identity_api_version == '2.0': auth_plugin_name = 'v2token' else: # let keystoneclient figure it out itself auth_plugin_name = 'token' else: raise exc.CommandError( "Authentication type must be selected with --os-auth-type") LOG.debug("Auth plugin %s selected" % auth_plugin_name) return auth_plugin_name
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 exceptions.NotFound: pass # now try to get entity as uuid try: uuid.UUID(str(name_or_id)) return manager.get(name_or_id) except (ValueError, exceptions.NotFound): pass # finally try to find entity by name try: return manager.find(name=name_or_id) # FIXME(dtroyer): The exception to catch here is dependent on which # client library the manager passed in belongs to. # Eventually this should be pulled from a common set # of client exceptions. except Exception as ex: if type(ex).__name__ == 'NotFound': msg = "No %s with a name or ID of '%s' exists." % \ (manager.resource_class.__name__.lower(), name_or_id) raise exceptions.CommandError(msg) else: raise
def take_action(self, parsed_args): compute_client = self.app.client_manager.compute cs = compute_client.services if (parsed_args.enable or not parsed_args.disable) and \ parsed_args.disable_reason: msg = _("Cannot specify option --disable-reason without " "--disable specified.") raise exceptions.CommandError(msg) enabled = None if parsed_args.enable: enabled = True if parsed_args.disable: enabled = False if enabled is None: return elif enabled: cs.enable(parsed_args.host, parsed_args.service) else: if parsed_args.disable_reason: cs.disable_log_reason(parsed_args.host, parsed_args.service, parsed_args.disable_reason) else: cs.disable(parsed_args.host, parsed_args.service)
def find_attr( self, path, value=None, attr=None, resource=None, ): """Find a resource via attribute or ID Most APIs return a list wrapped by a dict with the resource name as key. Some APIs (Identity) return a dict when a query string is present and there is one return value. Take steps to unwrap these bodies and return a single dict without any resource wrappers. :param string path: The API-specific portion of the URL path :param string value: value to search for :param string attr: attribute to use for resource search :param string resource: plural of the object resource name; defaults to path For example: n = find(netclient, 'network', 'networks', 'matrix') """ # Default attr is 'name' if attr is None: attr = 'name' # Default resource is path - in many APIs they are the same if resource is None: resource = path def getlist(kw): """Do list call, unwrap resource dict if present""" ret = self.list(path, **kw) if type(ret) == dict and resource in ret: ret = ret[resource] return ret # Search by attribute kwargs = {attr: value} data = getlist(kwargs) if type(data) == dict: return data if len(data) == 1: return data[0] if len(data) > 1: msg = "Multiple %s exist with %s='%s'" raise ksc_exceptions.CommandError(msg % (resource, attr, value), ) # Search by id kwargs = {'id': value} data = getlist(kwargs) if len(data) == 1: return data[0] msg = "No %s with a %s or ID of '%s' found" raise exceptions.CommandError(msg % (resource, attr, value))
def take_action(self, parsed_args): client = self.app.client_manager.network obj = client.find_router(parsed_args.router, ignore_missing=False) # Get the common attributes. attrs = _get_attrs(self.app.client_manager, parsed_args) # Get the route attributes. if parsed_args.no_route: attrs['routes'] = [] elif parsed_args.clear_routes: attrs['routes'] = [] LOG.warning( _('The --clear-routes option is deprecated, ' 'please use --no-route instead.')) elif parsed_args.routes is not None: # Map the route keys and append to the current routes. # The REST API will handle route validation and duplicates. for route in parsed_args.routes: route['nexthop'] = route.pop('gateway') attrs['routes'] = obj.routes + parsed_args.routes if attrs == {}: msg = _("Nothing specified to be set") raise exceptions.CommandError(msg) client.update_router(obj, **attrs)
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) client = self.app.client_manager.orchestration env_files, env = ( template_utils.process_multiple_environments_and_files( env_paths=parsed_args.environment)) adopt_url = heat_utils.normalise_file_path_to_url( parsed_args.adopt_file) adopt_data = request.urlopen(adopt_url).read().decode('utf-8') fields = { 'stack_name': parsed_args.name, 'disable_rollback': not parsed_args.enable_rollback, 'adopt_stack_data': adopt_data, 'parameters': heat_utils.format_parameters(parsed_args.parameter), 'files': dict(list(env_files.items())), 'environment': env, 'timeout': parsed_args.timeout } stack = client.stacks.create(**fields)['stack'] if parsed_args.wait: stack_status, msg = event_utils.poll_for_events(client, parsed_args.name, action='ADOPT') if stack_status == 'ADOPT_FAILED': raise exc.CommandError(msg) return _show_stack(client, stack['id'], format='table', short=True)
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) client = self.app.client_manager.orchestration fields = { 'nested_depth': parsed_args.nested_depth, 'with_detail': parsed_args.long, 'filters': heat_utils.format_parameters(parsed_args.filter), } try: resources = client.resources.list(parsed_args.stack, **fields) except heat_exc.HTTPNotFound: msg = _('Stack not found: %s') % parsed_args.stack raise exc.CommandError(msg) columns = [ 'physical_resource_id', 'resource_type', 'resource_status', 'updated_time' ] if len(resources) >= 1 and not hasattr(resources[0], 'resource_name'): columns.insert(0, 'logical_resource_id') else: columns.insert(0, 'resource_name') if parsed_args.nested_depth or parsed_args.long: columns.append('stack_name') return (columns, (utils.get_item_properties(r, columns) for r in resources))
def _show_config(heat_client, config_id, config_only): try: sc = heat_client.software_configs.get(config_id=config_id) except heat_exc.HTTPNotFound: raise exc.CommandError(_('Configuration not found: %s') % config_id) columns = None rows = None if config_only: print(sc.config) else: columns = ( 'id', 'name', 'group', 'config', 'inputs', 'outputs', 'options', 'creation_time', ) rows = utils.get_dict_properties(sc.to_dict(), columns) return columns, rows
def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) if parsed_args.name: server.update(name=parsed_args.name) if parsed_args.property: compute_client.servers.set_meta( server, parsed_args.property, ) if parsed_args.root_password: p1 = getpass.getpass(_('New password: '******'Retype new password: ')) if p1 == p2: server.change_password(p1) else: msg = _("Passwords do not match, password unchanged") raise exceptions.CommandError(msg)
def take_action(self, parsed_args): ret = 0 resources = getattr(parsed_args, self.resource, []) for r in resources: self.r = r try: if self.app.client_manager.is_network_endpoint_enabled(): self.take_action_network(self.app.client_manager.network, parsed_args) else: self.take_action_compute(self.app.client_manager.compute, parsed_args) except Exception as e: msg = _("Failed to delete %(resource)s with name or ID " "'%(name_or_id)s': %(e)s") % { "resource": self.resource, "name_or_id": r, "e": e, } self.app.log.error(msg) ret += 1 if ret: total = len(resources) msg = _("%(num)s of %(total)s %(resource)s failed to delete.") % { "num": ret, "total": total, "resource": self.resource, } raise exceptions.CommandError(msg)
def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.data_processing search_opts = {} if parsed_args.type: search_opts['type'] = parsed_args.type if parsed_args.plugin: search_opts['plugin'] = parsed_args.plugin if parsed_args.version: search_opts['version'] = parsed_args.version elif parsed_args.version: raise exceptions.CommandError( '--version argument should be specified with --plugin ' 'argument') data = client.job_types.list(search_opts=search_opts) for job in data: plugins = [] for plugin in job.plugins: versions = ", ".join(sorted(plugin["versions"].keys())) if versions: versions = "(" + versions + ")" plugins.append(plugin["name"] + versions) job.plugins = ', '.join(plugins) columns = ('name', 'plugins') column_headers = utils.prepare_column_headers(columns) return (column_headers, (osc_utils.get_item_properties(s, columns) for s in data))
def get_password(stdin, prompt=None, confirm=True): message = prompt or "User Password:"******"Repeat " + message) if first_pass == second_pass: return first_pass print("The passwords entered were not the same") except EOFError: # Ctl-D raise exceptions.CommandError("Error reading password.") raise exceptions.CommandError("There was a request to be prompted for a" " password and a terminal was not detected.")
def check_valid_auth_options(options, auth_plugin_name): """Perform basic option checking, provide helpful error messages""" msg = '' if auth_plugin_name.endswith('password'): if not options.auth.get('username', None): msg += _('Set a username with --os-username, OS_USERNAME,' ' or auth.username\n') if not options.auth.get('auth_url', None): msg += _('Set an authentication URL, with --os-auth-url,' ' OS_AUTH_URL or auth.auth_url\n') if (not options.auth.get('project_id', None) and not options.auth.get('domain_id', None) and not options.auth.get('domain_name', None) and not options.auth.get('project_name', None) and not options.auth.get('tenant_id', None) and not options.auth.get('tenant_name', None)): msg += _('Set a scope, such as a project or domain, set a ' 'project scope with --os-project-name, OS_PROJECT_NAME ' 'or auth.project_name, set a domain scope with ' '--os-domain-name, OS_DOMAIN_NAME or auth.domain_name') elif auth_plugin_name.endswith('token'): if not options.auth.get('token', None): msg += _('Set a token with --os-token, OS_TOKEN or auth.token\n') if not options.auth.get('auth_url', None): msg += _('Set a service AUTH_URL, with --os-auth-url, ' 'OS_AUTH_URL or auth.auth_url\n') elif auth_plugin_name == 'token_endpoint': if not options.auth.get('token', None): msg += _('Set a token with --os-token, OS_TOKEN or auth.token\n') if not options.auth.get('url', None): msg += _('Set a service URL, with --os-url, OS_URL or auth.url\n') if msg: raise exc.CommandError('Missing parameter(s): \n%s' % msg)
def take_action(self, parsed_args): compute_client = self.app.client_manager.compute public_key = parsed_args.public_key if public_key: try: with open(os.path.expanduser(parsed_args.public_key)) as p: public_key = p.read() except IOError as e: msg = "Key file %s not found: %s" raise exceptions.CommandError(msg % (parsed_args.public_key, e)) keypair = compute_client.keypairs.create( parsed_args.name, public_key=public_key, ) # NOTE(dtroyer): how do we want to handle the display of the private # key when it needs to be communicated back to the user # For now, duplicate nova keypair-add command output info = {} if public_key: info.update(keypair._info) del info['public_key'] return zip(*sorted(six.iteritems(info))) else: sys.stdout.write(keypair.private_key) return ({}, {})
def take_action(self, parsed_args): self.log.debug("take_action(%s)" % parsed_args) client = self.app.client_manager.data_processing if parsed_args.json: blob = osc_utils.read_blob_file_contents(parsed_args.json) try: template = jsonutils.loads(blob) except ValueError as e: raise exceptions.CommandError('An error occurred when reading ' 'template from file %s: %s' % (parsed_args.json, e)) data = client.jobs.create(**template).to_dict() else: if parsed_args.interface: blob = osc_utils.read_blob_file_contents(parsed_args.json) try: parsed_args.interface = jsonutils.loads(blob) except ValueError as e: raise exceptions.CommandError( 'An error occurred when reading ' 'interface from file %s: %s' % (parsed_args.json, e)) mains_ids = [ utils.get_resource_id(client.job_binaries, m) for m in parsed_args.mains ] if parsed_args.mains else None libs_ids = [ utils.get_resource_id(client.job_binaries, m) for m in parsed_args.libs ] if parsed_args.libs else None data = client.jobs.create( name=parsed_args.name, type=parsed_args.type, mains=mains_ids, libs=libs_ids, description=parsed_args.description, interface=parsed_args.interface, is_public=parsed_args.public, is_protected=parsed_args.protected).to_dict() _format_job_template_output(data) data = utils.prepare_data(data, JOB_TEMPLATE_FIELDS) return self.dict2columns(data)
def read_blob_file_contents(blob_file): try: with open(blob_file) as file: blob = file.read().strip() return blob except IOError: msg = "Error occurred trying to read from file %s" raise exceptions.CommandError(msg % blob_file)
def take_action(self, parsed_args): self.log.debug('take_action(%s)' % parsed_args) identity_client = self.app.client_manager.identity auth_ref = self.app.client_manager.auth_ref # Project and user are required, if not included in command args # default to the values used for authentication. For token-flow # authentication they must be included on the command line. if not parsed_args.project: if self.app.client_manager.auth_ref: parsed_args.project = auth_ref.project_id else: msg = "Project must be specified" raise exceptions.CommandError(msg) if not parsed_args.user: if self.app.client_manager.auth_ref: parsed_args.user = auth_ref.user_id else: msg = "User must be specified" raise exceptions.CommandError(msg) project = utils.find_resource( identity_client.tenants, parsed_args.project, ) user = utils.find_resource(identity_client.users, parsed_args.user) data = identity_client.roles.roles_for_user(user.id, project.id) columns = ( 'ID', 'Name', 'Project', 'User', ) # Add the names to the output even though they will be constant for role in data: role.user = user.name role.project = project.name return (columns, (utils.get_item_properties( s, columns, formatters={}, ) for s in data))
def get_field(item, field): try: if isinstance(item, dict): return item[field] else: return getattr(item, field) except Exception: msg = "Resource doesn't have field %s" % field raise exceptions.CommandError(msg)
def take_action(self, parsed_args): compute_client = self.app.client_manager.compute server = utils.find_resource( compute_client.servers, parsed_args.server, ) # Set sane defaults as this API wants all mouths to be fed if parsed_args.name is None: backup_name = server.name else: backup_name = parsed_args.name if parsed_args.type is None: backup_type = "" else: backup_type = parsed_args.type if parsed_args.rotate is None: backup_rotation = 1 else: backup_rotation = parsed_args.rotate compute_client.servers.backup( server.id, backup_name, backup_type, backup_rotation, ) image_client = self.app.client_manager.image image = utils.find_resource( image_client.images, backup_name, ) if parsed_args.wait: if utils.wait_for_status( image_client.images.get, image.id, callback=_show_progress, ): sys.stdout.write('\n') else: msg = _('Error creating server backup: %s') % parsed_args.name raise exceptions.CommandError(msg) if self.app.client_manager._api_version['image'] == '1': info = {} info.update(image._info) info['properties'] = utils.format_dict(info.get('properties', {})) else: # Get the right image module to format the output image_module = importutils.import_module(self.IMAGE_API_VERSIONS[ self.app.client_manager._api_version['image']]) info = image_module._format_image(image) return zip(*sorted(six.iteritems(info)))