diff options
Diffstat (limited to 'openstackclient/compute')
| -rw-r--r-- | openstackclient/compute/v2/console.py | 2 | ||||
| -rw-r--r-- | openstackclient/compute/v2/fixedip.py | 12 | ||||
| -rw-r--r-- | openstackclient/compute/v2/flavor.py | 13 | ||||
| -rw-r--r-- | openstackclient/compute/v2/floatingip.py | 18 | ||||
| -rw-r--r-- | openstackclient/compute/v2/floatingippool.py | 2 | ||||
| -rw-r--r-- | openstackclient/compute/v2/security_group.py | 262 | ||||
| -rw-r--r-- | openstackclient/compute/v2/server.py | 303 | ||||
| -rw-r--r-- | openstackclient/compute/v2/service.py | 22 | ||||
| -rw-r--r-- | openstackclient/compute/v2/usage.py | 33 |
9 files changed, 446 insertions, 221 deletions
diff --git a/openstackclient/compute/v2/console.py b/openstackclient/compute/v2/console.py index bb0747b1..aafa5d44 100644 --- a/openstackclient/compute/v2/console.py +++ b/openstackclient/compute/v2/console.py @@ -22,6 +22,7 @@ import sys from cliff import command from cliff import show +from openstackclient.common import parseractions from openstackclient.common import utils @@ -42,6 +43,7 @@ class ShowConsoleLog(command.Command): metavar='<num-lines>', type=int, default=None, + action=parseractions.NonNegativeAction, help='Number of lines to display from the end of the log ' '(default=all)', ) diff --git a/openstackclient/compute/v2/fixedip.py b/openstackclient/compute/v2/fixedip.py index d105e391..da9d85c3 100644 --- a/openstackclient/compute/v2/fixedip.py +++ b/openstackclient/compute/v2/fixedip.py @@ -23,7 +23,7 @@ from openstackclient.common import utils class AddFixedIP(command.Command): - """Add fixed-ip command""" + """Add fixed IP address to server""" log = logging.getLogger(__name__ + ".AddFixedIP") @@ -32,12 +32,12 @@ class AddFixedIP(command.Command): parser.add_argument( "network", metavar="<network>", - help="Name of the network to fetch an IP address from", + help="Network to fetch an IP address from (name or ID)", ) parser.add_argument( "server", metavar="<server>", - help="Name of the server to receive the IP address", + help="Server to receive the IP address (name or ID)", ) return parser @@ -56,7 +56,7 @@ class AddFixedIP(command.Command): class RemoveFixedIP(command.Command): - """Remove fixed-ip command""" + """Remove fixed IP address from server""" log = logging.getLogger(__name__ + ".RemoveFixedIP") @@ -65,12 +65,12 @@ class RemoveFixedIP(command.Command): parser.add_argument( "ip_address", metavar="<ip-address>", - help="IP address to remove from server", + help="IP address to remove from server (name only)", ) parser.add_argument( "server", metavar="<server>", - help="Name of the server to remove the IP address from", + help="Server to remove the IP address from (name or ID)", ) return parser diff --git a/openstackclient/compute/v2/flavor.py b/openstackclient/compute/v2/flavor.py index 3458cf79..7474580b 100644 --- a/openstackclient/compute/v2/flavor.py +++ b/openstackclient/compute/v2/flavor.py @@ -181,6 +181,15 @@ class ListFlavor(lister.Lister): action='store_true', default=False, help='List additional fields in output') + parser.add_argument( + '--marker', + metavar="<marker>", + help='The last flavor ID of the previous page') + parser.add_argument( + '--limit', + type=int, + metavar="<limit>", + help='Maximum number of flavors to display') return parser def take_action(self, parsed_args): @@ -202,7 +211,9 @@ class ListFlavor(lister.Lister): # and flavors from their own projects only. is_public = None if parsed_args.all else parsed_args.public - data = compute_client.flavors.list(is_public=is_public) + data = compute_client.flavors.list(is_public=is_public, + marker=parsed_args.marker, + limit=parsed_args.limit) if parsed_args.long: columns = columns + ( diff --git a/openstackclient/compute/v2/floatingip.py b/openstackclient/compute/v2/floatingip.py index c557c24b..65fe5910 100644 --- a/openstackclient/compute/v2/floatingip.py +++ b/openstackclient/compute/v2/floatingip.py @@ -26,7 +26,7 @@ from openstackclient.common import utils class AddFloatingIP(command.Command): - """Add floating-ip to server""" + """Add floating IP address to server""" log = logging.getLogger(__name__ + ".AddFloatingIP") @@ -35,7 +35,7 @@ class AddFloatingIP(command.Command): parser.add_argument( "ip_address", metavar="<ip-address>", - help="IP address to add to server", + help="IP address to add to server (name only)", ) parser.add_argument( "server", @@ -56,7 +56,7 @@ class AddFloatingIP(command.Command): class CreateFloatingIP(show.ShowOne): - """Create new floating-ip""" + """Create new floating IP address""" log = logging.getLogger(__name__ + '.CreateFloatingIP') @@ -65,7 +65,7 @@ class CreateFloatingIP(show.ShowOne): parser.add_argument( 'pool', metavar='<pool>', - help='Pool to fetch floating IP from', + help='Pool to fetch IP address from (name or ID)', ) return parser @@ -80,7 +80,7 @@ class CreateFloatingIP(show.ShowOne): class DeleteFloatingIP(command.Command): - """Delete a floating-ip""" + """Delete a floating IP address""" log = logging.getLogger(__name__ + '.DeleteFloatingIP') @@ -89,7 +89,7 @@ class DeleteFloatingIP(command.Command): parser.add_argument( "ip_address", metavar="<ip-address>", - help="IP address to delete", + help="IP address to delete (ID only)", ) return parser @@ -107,7 +107,7 @@ class DeleteFloatingIP(command.Command): class ListFloatingIP(lister.Lister): - """List floating-ips""" + """List floating IP addresses""" log = logging.getLogger(__name__ + '.ListFloatingIP') @@ -127,7 +127,7 @@ class ListFloatingIP(lister.Lister): class RemoveFloatingIP(command.Command): - """Remove floating-ip from server""" + """Remove floating IP address from server""" log = logging.getLogger(__name__ + ".RemoveFloatingIP") @@ -136,7 +136,7 @@ class RemoveFloatingIP(command.Command): parser.add_argument( "ip_address", metavar="<ip-address>", - help="IP address to remove from server", + help="IP address to remove from server (name only)", ) parser.add_argument( "server", diff --git a/openstackclient/compute/v2/floatingippool.py b/openstackclient/compute/v2/floatingippool.py index cc485552..39a2d8fe 100644 --- a/openstackclient/compute/v2/floatingippool.py +++ b/openstackclient/compute/v2/floatingippool.py @@ -23,7 +23,7 @@ from openstackclient.common import utils class ListFloatingIPPool(lister.Lister): - """List floating-ip-pools""" + """List pools of floating IP addresses""" log = logging.getLogger(__name__ + '.ListFloatingIPPool') diff --git a/openstackclient/compute/v2/security_group.py b/openstackclient/compute/v2/security_group.py index 3dd0c49b..6d38195c 100644 --- a/openstackclient/compute/v2/security_group.py +++ b/openstackclient/compute/v2/security_group.py @@ -23,7 +23,7 @@ from cliff import command from cliff import lister from cliff import show -from keystoneclient import exceptions as ksc_exc +from keystoneauth1 import exceptions as ks_exc try: from novaclient.v2 import security_group_rules @@ -93,6 +93,64 @@ class CreateSecurityGroup(show.ShowOne): return zip(*sorted(six.iteritems(info))) +class CreateSecurityGroupRule(show.ShowOne): + """Create a new security group rule""" + + log = logging.getLogger(__name__ + ".CreateSecurityGroupRule") + + def get_parser(self, prog_name): + parser = super(CreateSecurityGroupRule, self).get_parser(prog_name) + parser.add_argument( + 'group', + metavar='<group>', + help='Create rule in this security group (name or ID)', + ) + parser.add_argument( + "--proto", + metavar="<proto>", + default="tcp", + help="IP protocol (icmp, tcp, udp; default: tcp)", + ) + parser.add_argument( + "--src-ip", + metavar="<ip-address>", + default="0.0.0.0/0", + help="Source IP (may use CIDR notation; default: 0.0.0.0/0)", + ) + parser.add_argument( + "--dst-port", + metavar="<port-range>", + default=(0, 0), + action=parseractions.RangeAction, + help="Destination port, may be a range: 137:139 (default: 0; " + "only required for proto tcp and udp)", + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + + compute_client = self.app.client_manager.compute + group = utils.find_resource( + compute_client.security_groups, + parsed_args.group, + ) + if parsed_args.proto.lower() == 'icmp': + from_port, to_port = -1, -1 + else: + from_port, to_port = parsed_args.dst_port + data = compute_client.security_group_rules.create( + group.id, + parsed_args.proto, + from_port, + to_port, + parsed_args.src_ip, + ) + + info = _xform_security_group_rule(data._info) + return zip(*sorted(six.iteritems(info))) + + class DeleteSecurityGroup(command.Command): """Delete a security group""" @@ -103,7 +161,7 @@ class DeleteSecurityGroup(command.Command): parser.add_argument( 'group', metavar='<group>', - help='Name or ID of security group to delete', + help='Security group to delete (name or ID)', ) return parser @@ -119,8 +177,30 @@ class DeleteSecurityGroup(command.Command): return +class DeleteSecurityGroupRule(command.Command): + """Delete a security group rule""" + + log = logging.getLogger(__name__ + '.DeleteSecurityGroupRule') + + def get_parser(self, prog_name): + parser = super(DeleteSecurityGroupRule, self).get_parser(prog_name) + parser.add_argument( + 'rule', + metavar='<rule>', + help='Security group rule to delete (ID only)', + ) + return parser + + @utils.log_method(log) + def take_action(self, parsed_args): + + compute_client = self.app.client_manager.compute + compute_client.security_group_rules.delete(parsed_args.rule) + return + + class ListSecurityGroup(lister.Lister): - """List all security groups""" + """List security groups""" log = logging.getLogger(__name__ + ".ListSecurityGroup") @@ -161,7 +241,7 @@ class ListSecurityGroup(lister.Lister): project_hash = {} try: projects = self.app.client_manager.identity.projects.list() - except ksc_exc.ClientException: + except ks_exc.ClientException: # This fails when the user is not an admin, just move along pass else: @@ -175,6 +255,49 @@ class ListSecurityGroup(lister.Lister): ) for s in data)) +class ListSecurityGroupRule(lister.Lister): + """List security group rules""" + + log = logging.getLogger(__name__ + ".ListSecurityGroupRule") + + def get_parser(self, prog_name): + parser = super(ListSecurityGroupRule, self).get_parser(prog_name) + parser.add_argument( + 'group', + metavar='<group>', + help='List all rules in this security group (name or ID)', + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + + compute_client = self.app.client_manager.compute + group = utils.find_resource( + compute_client.security_groups, + parsed_args.group, + ) + + # Argh, the rules are not Resources... + rules = [] + for rule in group.rules: + rules.append(security_group_rules.SecurityGroupRule( + compute_client.security_group_rules, + _xform_security_group_rule(rule), + )) + + columns = column_headers = ( + "ID", + "IP Protocol", + "IP Range", + "Port Range", + ) + return (column_headers, + (utils.get_item_properties( + s, columns, + ) for s in rules)) + + class SetSecurityGroup(show.ShowOne): """Set security group properties""" @@ -185,7 +308,7 @@ class SetSecurityGroup(show.ShowOne): parser.add_argument( 'group', metavar='<group>', - help='Name or ID of security group to change', + help='Security group to modify (name or ID)', ) parser.add_argument( '--name', @@ -195,7 +318,7 @@ class SetSecurityGroup(show.ShowOne): parser.add_argument( "--description", metavar="<description>", - help="New security group name", + help="New security group description", ) return parser @@ -227,7 +350,7 @@ class SetSecurityGroup(show.ShowOne): class ShowSecurityGroup(show.ShowOne): - """Show a specific security group""" + """Display security group details""" log = logging.getLogger(__name__ + '.ShowSecurityGroup') @@ -236,7 +359,7 @@ class ShowSecurityGroup(show.ShowOne): parser.add_argument( 'group', metavar='<group>', - help='Name or ID of security group to change', + help='Security group to display (name or ID)', ) return parser @@ -263,126 +386,3 @@ class ShowSecurityGroup(show.ShowOne): ) return zip(*sorted(six.iteritems(info))) - - -class CreateSecurityGroupRule(show.ShowOne): - """Create a new security group rule""" - - log = logging.getLogger(__name__ + ".CreateSecurityGroupRule") - - def get_parser(self, prog_name): - parser = super(CreateSecurityGroupRule, self).get_parser(prog_name) - parser.add_argument( - 'group', - metavar='<group>', - help='Create rule in this security group', - ) - parser.add_argument( - "--proto", - metavar="<proto>", - default="tcp", - help="IP protocol (icmp, tcp, udp; default: tcp)", - ) - parser.add_argument( - "--src-ip", - metavar="<ip-address>", - default="0.0.0.0/0", - help="Source IP (may use CIDR notation; default: 0.0.0.0/0)", - ) - parser.add_argument( - "--dst-port", - metavar="<port-range>", - default=(0, 0), - action=parseractions.RangeAction, - help="Destination port, may be a range: 137:139 (default: 0; " - "only required for proto tcp and udp)", - ) - return parser - - def take_action(self, parsed_args): - self.log.debug("take_action(%s)", parsed_args) - - compute_client = self.app.client_manager.compute - group = utils.find_resource( - compute_client.security_groups, - parsed_args.group, - ) - if parsed_args.proto.lower() == 'icmp': - from_port, to_port = -1, -1 - else: - from_port, to_port = parsed_args.dst_port - data = compute_client.security_group_rules.create( - group.id, - parsed_args.proto, - from_port, - to_port, - parsed_args.src_ip, - ) - - info = _xform_security_group_rule(data._info) - return zip(*sorted(six.iteritems(info))) - - -class DeleteSecurityGroupRule(command.Command): - """Delete a security group rule""" - - log = logging.getLogger(__name__ + '.DeleteSecurityGroupRule') - - def get_parser(self, prog_name): - parser = super(DeleteSecurityGroupRule, self).get_parser(prog_name) - parser.add_argument( - 'rule', - metavar='<rule>', - help='Security group rule ID to delete', - ) - return parser - - @utils.log_method(log) - def take_action(self, parsed_args): - - compute_client = self.app.client_manager.compute - compute_client.security_group_rules.delete(parsed_args.rule) - return - - -class ListSecurityGroupRule(lister.Lister): - """List all security group rules""" - - log = logging.getLogger(__name__ + ".ListSecurityGroupRule") - - def get_parser(self, prog_name): - parser = super(ListSecurityGroupRule, self).get_parser(prog_name) - parser.add_argument( - 'group', - metavar='<group>', - help='List all rules in this security group', - ) - return parser - - def take_action(self, parsed_args): - self.log.debug("take_action(%s)", parsed_args) - - compute_client = self.app.client_manager.compute - group = utils.find_resource( - compute_client.security_groups, - parsed_args.group, - ) - - # Argh, the rules are not Resources... - rules = [] - for rule in group.rules: - rules.append(security_group_rules.SecurityGroupRule( - compute_client.security_group_rules, - _xform_security_group_rule(rule), - )) - - columns = column_headers = ( - "ID", - "IP Protocol", - "IP Range", - "Port Range", - ) - return (column_headers, - (utils.get_item_properties( - s, columns, - ) for s in rules)) diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py index 661ce847..d58ebacd 100644 --- a/openstackclient/compute/v2/server.py +++ b/openstackclient/compute/v2/server.py @@ -43,7 +43,7 @@ from openstackclient.network import common def _format_servers_list_networks(networks): """Return a formatted string of a server's networks - :param server: a Server.networks field + :param networks: a Server.networks field :rtype: a string of formatted network addresses """ output = [] @@ -56,6 +56,29 @@ def _format_servers_list_networks(networks): return '; '.join(output) +def _format_servers_list_power_state(state): + """Return a formatted string of a server's power state + + :param state: the power state number of a server + :rtype: a string mapped to the power state number + """ + power_states = [ + 'NOSTATE', # 0x00 + 'Running', # 0x01 + '', # 0x02 + 'Paused', # 0x03 + 'Shutdown', # 0x04 + '', # 0x05 + 'Crashed', # 0x06 + 'Suspended' # 0x07 + ] + + try: + return power_states[state] + except Exception: + return 'N/A' + + def _get_ip_address(addresses, address_type, ip_address_family): # Old style addresses if address_type in addresses: @@ -425,10 +448,17 @@ class CreateServer(show.ShowOne): dev_key, dev_vol = dev_map.split('=', 1) block_volume = None if dev_vol: - block_volume = utils.find_resource( - volume_client.volumes, - dev_vol, - ).id + vol = dev_vol.split(':', 1)[0] + if vol: + vol_id = utils.find_resource( + volume_client.volumes, + vol, + ).id + block_volume = dev_vol.replace(vol, vol_id) + else: + msg = _("Volume name or ID must be specified if " + "--block-device-mapping is specified") + raise exceptions.CommandError(msg) block_device_mapping.update({dev_key: block_volume}) nics = [] @@ -607,7 +637,7 @@ class DeleteServer(command.Command): def get_parser(self, prog_name): parser = super(DeleteServer, self).get_parser(prog_name) parser.add_argument( - 'servers', + 'server', metavar='<server>', nargs="+", help=_('Server(s) to delete (name or ID)'), @@ -622,7 +652,7 @@ class DeleteServer(command.Command): @utils.log_method(log) def take_action(self, parsed_args): compute_client = self.app.client_manager.compute - for server in parsed_args.servers: + for server in parsed_args.server: server_obj = utils.find_resource( compute_client.servers, server) compute_client.servers.delete(server_obj.id) @@ -682,12 +712,12 @@ class ListServer(lister.Lister): parser.add_argument( '--flavor', metavar='<flavor>', - help=_('Search by flavor'), + help=_('Search by flavor (name or ID)'), ) parser.add_argument( '--image', metavar='<image>', - help=_('Search by image'), + help=_('Search by image (name or ID)'), ) parser.add_argument( '--host', @@ -717,6 +747,24 @@ class ListServer(lister.Lister): default=False, help=_('List additional fields in output'), ) + parser.add_argument( + '--marker', + metavar='<marker>', + default=None, + help=('The last server (name or ID) of the previous page. Display' + ' list of servers after marker. Display all servers if not' + ' specified.') + ) + parser.add_argument( + '--limit', + metavar='<limit>', + type=int, + default=None, + help=("Maximum number of servers to display. If limit equals -1," + " all servers will be displayed. If limit is greater than" + " 'osapi_max_limit' option of Nova API," + " 'osapi_max_limit' will be used instead."), + ) return parser @utils.log_method(log) @@ -735,12 +783,26 @@ class ListServer(lister.Lister): user_id = None if parsed_args.user: - user_id = identity_common.find_project( + user_id = identity_common.find_user( identity_client, parsed_args.user, parsed_args.user_domain, ).id + # Nova only supports list servers searching by flavor ID. So if a + # flavor name is given, map it to ID. + flavor_id = None + if parsed_args.flavor: + flavor_id = utils.find_resource(compute_client.flavors, + parsed_args.flavor).id + + # Nova only supports list servers searching by image ID. So if a + # image name is given, map it to ID. + image_id = None + if parsed_args.image: + image_id = utils.find_resource(compute_client.images, + parsed_args.image).id + search_opts = { 'reservation_id': parsed_args.reservation_id, 'ip': parsed_args.ip, @@ -748,8 +810,8 @@ class ListServer(lister.Lister): 'name': parsed_args.name, 'instance_name': parsed_args.instance_name, 'status': parsed_args.status, - 'flavor': parsed_args.flavor, - 'image': parsed_args.image, + 'flavor': flavor_id, + 'image': image_id, 'host': parsed_args.host, 'tenant_id': project_id, 'all_tenants': parsed_args.all_projects, @@ -762,6 +824,8 @@ class ListServer(lister.Lister): 'ID', 'Name', 'Status', + 'OS-EXT-STS:task_state', + 'OS-EXT-STS:power_state', 'Networks', 'OS-EXT-AZ:availability_zone', 'OS-EXT-SRV-ATTR:host', @@ -771,25 +835,49 @@ class ListServer(lister.Lister): 'ID', 'Name', 'Status', + 'Task State', + 'Power State', 'Networks', 'Availability Zone', 'Host', 'Properties', ) mixed_case_fields = [ + 'OS-EXT-STS:task_state', + 'OS-EXT-STS:power_state', 'OS-EXT-AZ:availability_zone', 'OS-EXT-SRV-ATTR:host', ] else: - columns = ('ID', 'Name', 'Status', 'Networks') - column_headers = columns + columns = ( + 'ID', + 'Name', + 'Status', + 'Networks', + ) + column_headers = ( + 'ID', + 'Name', + 'Status', + 'Networks', + ) mixed_case_fields = [] - data = compute_client.servers.list(search_opts=search_opts) + + marker_id = None + if parsed_args.marker: + marker_id = utils.find_resource(compute_client.servers, + parsed_args.marker).id + + data = compute_client.servers.list(search_opts=search_opts, + marker=marker_id, + limit=parsed_args.limit) return (column_headers, (utils.get_item_properties( s, columns, mixed_case_fields=mixed_case_fields, formatters={ + 'OS-EXT-STS:power_state': + _format_servers_list_power_state, 'Networks': _format_servers_list_networks, 'Metadata': utils.format_dict, }, @@ -798,7 +886,7 @@ class ListServer(lister.Lister): class LockServer(command.Command): - """Lock a server. A non-admin user will not be able to execute actions""" + """Lock server(s). A non-admin user will not be able to execute actions""" log = logging.getLogger(__name__ + '.LockServer') @@ -807,7 +895,8 @@ class LockServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help=_('Server (name or ID)'), + nargs='+', + help=_('Server(s) to lock (name or ID)'), ) return parser @@ -815,10 +904,11 @@ class LockServer(command.Command): def take_action(self, parsed_args): compute_client = self.app.client_manager.compute - utils.find_resource( - compute_client.servers, - parsed_args.server, - ).lock() + for server in parsed_args.server: + utils.find_resource( + compute_client.servers, + server, + ).lock() # FIXME(dtroyer): Here is what I want, how with argparse/cliff? @@ -915,7 +1005,7 @@ class MigrateServer(command.Command): class PauseServer(command.Command): - """Pause server""" + """Pause server(s)""" log = logging.getLogger(__name__ + '.PauseServer') @@ -924,18 +1014,19 @@ class PauseServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help=_('Server (name or ID)'), + nargs='+', + help=_('Server(s) to pause (name or ID)'), ) return parser @utils.log_method(log) def take_action(self, parsed_args): - compute_client = self.app.client_manager.compute - utils.find_resource( - compute_client.servers, - parsed_args.server, - ).pause() + for server in parsed_args.server: + utils.find_resource( + compute_client.servers, + server + ).pause() class RebootServer(command.Command): @@ -1217,7 +1308,7 @@ class ResizeServer(command.Command): class ResumeServer(command.Command): - """Resume server""" + """Resume server(s)""" log = logging.getLogger(__name__ + '.ResumeServer') @@ -1226,7 +1317,8 @@ class ResumeServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help=_('Server (name or ID)'), + nargs='+', + help=_('Server(s) to resume (name or ID)'), ) return parser @@ -1234,10 +1326,11 @@ class ResumeServer(command.Command): def take_action(self, parsed_args): compute_client = self.app.client_manager.compute - utils.find_resource( - compute_client.servers, - parsed_args.server, - ) .resume() + for server in parsed_args.server: + utils.find_resource( + compute_client.servers, + server, + ).resume() class SetServer(command.Command): @@ -1299,6 +1392,31 @@ class SetServer(command.Command): raise exceptions.CommandError(msg) +class ShelveServer(command.Command): + """Shelve server(s)""" + + log = logging.getLogger(__name__ + '.ShelveServer') + + def get_parser(self, prog_name): + parser = super(ShelveServer, self).get_parser(prog_name) + parser.add_argument( + 'server', + metavar='<server>', + nargs='+', + help=_('Server(s) to shelve (name or ID)'), + ) + return parser + + @utils.log_method(log) + def take_action(self, parsed_args): + compute_client = self.app.client_manager.compute + for server in parsed_args.server: + utils.find_resource( + compute_client.servers, + server, + ).shelve() + + class ShowServer(show.ShowOne): """Show server details""" @@ -1483,8 +1601,58 @@ class SshServer(command.Command): os.system(cmd % (login, ip_address)) +class StartServer(command.Command): + """Start server(s).""" + + log = logging.getLogger(__name__ + '.StartServer') + + def get_parser(self, prog_name): + parser = super(StartServer, self).get_parser(prog_name) + parser.add_argument( + 'server', + metavar='<server>', + nargs="+", + help=_('Server(s) to start (name or ID)'), + ) + return parser + + @utils.log_method(log) + def take_action(self, parsed_args): + compute_client = self.app.client_manager.compute + for server in parsed_args.server: + utils.find_resource( + compute_client.servers, + server, + ).start() + + +class StopServer(command.Command): + """Stop server(s).""" + + log = logging.getLogger(__name__ + '.StopServer') + + def get_parser(self, prog_name): + parser = super(StopServer, self).get_parser(prog_name) + parser.add_argument( + 'server', + metavar='<server>', + nargs="+", + help=_('Server(s) to stop (name or ID)'), + ) + return parser + + @utils.log_method(log) + def take_action(self, parsed_args): + compute_client = self.app.client_manager.compute + for server in parsed_args.server: + utils.find_resource( + compute_client.servers, + server, + ).stop() + + class SuspendServer(command.Command): - """Suspend server""" + """Suspend server(s)""" log = logging.getLogger(__name__ + '.SuspendServer') @@ -1493,7 +1661,8 @@ class SuspendServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help=_('Server (name or ID)'), + nargs='+', + help=_('Server(s) to suspend (name or ID)'), ) return parser @@ -1501,14 +1670,15 @@ class SuspendServer(command.Command): def take_action(self, parsed_args): compute_client = self.app.client_manager.compute - utils.find_resource( - compute_client.servers, - parsed_args.server, - ).suspend() + for server in parsed_args.server: + utils.find_resource( + compute_client.servers, + server, + ).suspend() class UnlockServer(command.Command): - """Unlock server""" + """Unlock server(s)""" log = logging.getLogger(__name__ + '.UnlockServer') @@ -1517,7 +1687,8 @@ class UnlockServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help=_('Server (name or ID)'), + nargs='+', + help=_('Server(s) to unlock (name or ID)'), ) return parser @@ -1525,14 +1696,15 @@ class UnlockServer(command.Command): def take_action(self, parsed_args): compute_client = self.app.client_manager.compute - utils.find_resource( - compute_client.servers, - parsed_args.server, - ).unlock() + for server in parsed_args.server: + utils.find_resource( + compute_client.servers, + server, + ).unlock() class UnpauseServer(command.Command): - """Unpause server""" + """Unpause server(s)""" log = logging.getLogger(__name__ + '.UnpauseServer') @@ -1541,7 +1713,8 @@ class UnpauseServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help=_('Server (name or ID)'), + nargs='+', + help=_('Server(s) to unpause (name or ID)'), ) return parser @@ -1549,10 +1722,11 @@ class UnpauseServer(command.Command): def take_action(self, parsed_args): compute_client = self.app.client_manager.compute - utils.find_resource( - compute_client.servers, - parsed_args.server, - ).unpause() + for server in parsed_args.server: + utils.find_resource( + compute_client.servers, + server, + ).unpause() class UnrescueServer(command.Command): @@ -1614,3 +1788,28 @@ class UnsetServer(command.Command): server, parsed_args.property, ) + + +class UnshelveServer(command.Command): + """Unshelve server(s)""" + + log = logging.getLogger(__name__ + '.UnshelveServer') + + def get_parser(self, prog_name): + parser = super(UnshelveServer, self).get_parser(prog_name) + parser.add_argument( + 'server', + metavar='<server>', + nargs='+', + help=_('Server(s) to unshelve (name or ID)'), + ) + return parser + + @utils.log_method(log) + def take_action(self, parsed_args): + compute_client = self.app.client_manager.compute + for server in parsed_args.server: + utils.find_resource( + compute_client.servers, + server, + ).unshelve() diff --git a/openstackclient/compute/v2/service.py b/openstackclient/compute/v2/service.py index 3a031bff..c2d51c2a 100644 --- a/openstackclient/compute/v2/service.py +++ b/openstackclient/compute/v2/service.py @@ -17,11 +17,33 @@ import logging +from cliff import command from cliff import lister from openstackclient.common import utils +class DeleteService(command.Command): + """Delete service command""" + + log = logging.getLogger(__name__ + ".DeleteService") + + def get_parser(self, prog_name): + parser = super(DeleteService, self).get_parser(prog_name) + parser.add_argument( + "service", + metavar="<service>", + help="Compute service to delete (ID only)") + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + compute_client = self.app.client_manager.compute + + compute_client.services.delete(parsed_args.service) + return + + class ListService(lister.Lister): """List service command""" diff --git a/openstackclient/compute/v2/usage.py b/openstackclient/compute/v2/usage.py index 31b90c22..4e7cf100 100644 --- a/openstackclient/compute/v2/usage.py +++ b/openstackclient/compute/v2/usage.py @@ -183,25 +183,16 @@ class ShowUsage(show.ShowOne): )) info = {} - info['Servers'] = len(usage.server_usages) - info['RAM MB-Hours'] = float("%.2f" % usage.total_memory_mb_usage) - info['CPU Hours'] = float("%.2f" % usage.total_vcpus_usage) - info['Disk GB-Hours'] = float("%.2f" % usage.total_local_gb_usage) + info['Servers'] = ( + len(usage.server_usages) + if hasattr(usage, "server_usages") else None) + info['RAM MB-Hours'] = ( + float("%.2f" % usage.total_memory_mb_usage) + if hasattr(usage, "total_memory_mb_usage") else None) + info['CPU Hours'] = ( + float("%.2f" % usage.total_vcpus_usage) + if hasattr(usage, "total_vcpus_usage") else None) + info['Disk GB-Hours'] = ( + float("%.2f" % usage.total_local_gb_usage) + if hasattr(usage, "total_local_gb_usage") else None) return zip(*sorted(six.iteritems(info))) - - -# This is out of order due to the subclass, will eventually be removed - -class ListProjectUsage(ListUsage): - """List resource usage per project""" - - deprecated = True - - log = logging.getLogger('DEPRECATED:') - - def take_action(self, parsed_args): - self.log.warning( - "%s is deprecated, use 'usage list'", - getattr(self, 'cmd_name', 'this command'), - ) - return super(ListProjectUsage, self).take_action(parsed_args) |
