summaryrefslogtreecommitdiff
path: root/openstackclient/compute
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient/compute')
-rw-r--r--openstackclient/compute/v2/console.py2
-rw-r--r--openstackclient/compute/v2/fixedip.py12
-rw-r--r--openstackclient/compute/v2/flavor.py13
-rw-r--r--openstackclient/compute/v2/floatingip.py18
-rw-r--r--openstackclient/compute/v2/floatingippool.py2
-rw-r--r--openstackclient/compute/v2/security_group.py262
-rw-r--r--openstackclient/compute/v2/server.py303
-rw-r--r--openstackclient/compute/v2/service.py22
-rw-r--r--openstackclient/compute/v2/usage.py33
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)