From ac4950b46e65e5b3e4a98a0b0ce2a2c80747b3e8 Mon Sep 17 00:00:00 2001
From: Dean Troyer <dtroyer@gmail.com>
Date: Mon, 17 Nov 2014 21:56:18 -0600
Subject: [PATCH] Command object docs: server, server image

server
server image

Some cosmetic changes in the command source, sorting classes, help strings, etc.

Change-Id: I3f68dae77b9fe02bc6866684e05aeff943dd9cc3
---
 doc/source/command-objects/server-image.rst |  27 +
 doc/source/command-objects/server.rst       | 544 ++++++++++++++++++++
 doc/source/commands.rst                     |   3 +-
 openstackclient/compute/v2/server.py        | 192 ++++---
 4 files changed, 683 insertions(+), 83 deletions(-)
 create mode 100644 doc/source/command-objects/server-image.rst
 create mode 100644 doc/source/command-objects/server.rst

diff --git a/doc/source/command-objects/server-image.rst b/doc/source/command-objects/server-image.rst
new file mode 100644
index 0000000000..681f6e4f2c
--- /dev/null
+++ b/doc/source/command-objects/server-image.rst
@@ -0,0 +1,27 @@
+============
+server image
+============
+
+A server image is a disk image created from a running server instance.  The
+image is created in the Image store.
+
+server image create
+-------------------
+
+Create a new disk image from a running server
+
+.. code:: bash
+
+    os server image create
+        [--name <image-name>]
+        [--wait]
+        <server>
+
+:option:`--name` <image-name>
+    Name of new image (default is server name)
+
+:option:`--wait`
+    Wait for image create to complete
+
+:option:`<server>`
+    Server (name or ID)
diff --git a/doc/source/command-objects/server.rst b/doc/source/command-objects/server.rst
new file mode 100644
index 0000000000..4f07632957
--- /dev/null
+++ b/doc/source/command-objects/server.rst
@@ -0,0 +1,544 @@
+======
+server
+======
+
+
+server add security group
+-------------------------
+
+Add security group to server
+
+.. code:: bash
+
+    os server add security group
+        <server>
+        <group>
+
+:option:`<server>`
+    Server (name or ID)
+
+:option:`<group>`
+    Security group to add (name or ID)
+
+server add volume
+-----------------
+
+Add volume to server
+
+.. code:: bash
+
+    os server add volume
+        [--device <device>]
+        <server>
+        <volume>
+
+:option:`--device` <device>
+    Server internal device name for volume
+
+:option:`<server>`
+    Server (name or ID)
+
+:option:`<volume>`
+    Volume to add (name or ID)
+
+server create
+-------------
+
+Create a new server
+
+.. code:: bash
+
+    os server create
+        --image <image> | --volume <volume>
+        --flavor <flavor>
+        [--security-group <security-group-list> [...] ]
+        [--key-name <key-name>]
+        [--property <key=value> [...] ]
+        [--file <dest-filename=source-filename>] [...] ]
+        [--user-data <user-data>]
+        [--availability-zone <zone-name>]
+        [--block-device-mapping <dev-name=mapping> [...] ]
+        [--nic <net-id=net-uuid,v4-fixed-ip=ip-addr> [...] ]
+        [--hint <key=value> [...] ]
+        [--config-drive <value>|True ]
+        [--min <count>]
+        [--max <count>]
+        [--wait]
+        <server-name>
+
+:option:`--image` <image>
+    Create server from this image
+
+:option:`--volume` <volume>
+    Create server from this volume
+
+:option:`--flavor` <flavor>
+    Create server with this flavor
+
+:option:`--security-group` <security-group-name>
+    Security group to assign to this server (repeat for multiple groups)
+
+:option:`--key-name` <key-name>
+    Keypair to inject into this server (optional extension)
+
+:option:`--property` <key=value>
+    Set a property on this server (repeat for multiple values)
+
+:option:`--file` <dest-filename=source-filename>
+    File to inject into image before boot (repeat for multiple files)
+
+:option:`--user-data` <user-data>
+    User data file to serve from the metadata server
+
+:option:`--availability-zone` <zone-name>
+    Select an availability zone for the server
+
+:option:`--block-device-mapping` <dev-name=mapping>
+    Map block devices; map is <id>:<type>:<size(GB)>:<delete_on_terminate> (optional extension)
+
+:option:`--nic` <nic-config-string>
+    Specify NIC configuration (optional extension)
+
+:option:`--hint` <key=value>
+    Hints for the scheduler (optional extension)
+
+:option:`--config-drive` <config-drive-volume>|True
+    Use specified volume as the config drive, or 'True' to use an ephemeral drive
+
+:option:`--min` <count>
+    Minimum number of servers to launch (default=1)
+
+:option:`--max` <count>
+    Maximum number of servers to launch (default=1)
+
+:option:`--wait`
+    Wait for build to complete
+
+:option:`<server-name>`
+    New server name
+
+server delete
+-------------
+
+Delete server command
+
+.. code:: bash
+
+    os server delete
+        <server>
+
+:option:`<server>`
+    Server (name or ID)
+
+server list
+-----------
+
+List servers
+
+.. code:: bash
+
+    os server list
+        [--reservation-id <reservation-id>]
+        [--ip <ip-regex>]
+        [--ip6 <ip6-regex>]
+        [--name <name-regex>]
+        [--instance-name <instance-name-regex>]
+        [--status <status>]
+        [--flavor <flavor>]
+        [--image <image>]
+        [--host <hostname>]
+        [--all-projects]
+        [--long]
+
+:option:`--reservation-id` <reservation-id>
+    Only return instances that match the reservation
+
+:option:`--ip` <ip-address-regex>
+    Regular expression to match IP addresses
+
+:option:`--ip6` <ip-address-regex>
+    Regular expression to match IPv6 addresses
+
+:option:`--name` <name-regex>
+    Regular expression to match names
+
+:option:`--instance-name` <server-name-regex>
+    Regular expression to match instance name (admin only)
+
+:option:`--status` <status>
+    Search by server status
+
+:option:`--flavor` <flavor>
+    Search by flavor ID
+
+:option:`--image` <image>
+    Search by image ID
+
+:option:`--host` <hostname>
+    Search by hostname
+
+:option:`--all-projects`
+    Include all projects (admin only)
+
+:option:`--long`
+    List additional fields in output
+
+server lock
+-----------
+
+Lock server
+
+.. code:: bash
+
+    os server lock
+        <server>
+
+:option:`<server>`
+    Server (name or ID)
+
+server migrate
+--------------
+
+Migrate server to different host
+
+.. code:: bash
+
+    os server migrate
+        --live <host>
+        [--shared-migration | --block-migration]
+        [--disk-overcommit | --no-disk-overcommit]
+        [--wait]
+        <server>
+
+:option:`--wait`
+    Wait for resize to complete
+
+:option:`--live` <hostname>
+    Target hostname
+
+:option:`--shared-migration`
+    Perform a shared live migration (default)
+
+:option:`--block-migration`
+    Perform a block live migration
+
+:option:`--disk-overcommit`
+    Allow disk over-commit on the destination host
+
+:option:`--no-disk-overcommit`
+    Do not over-commit disk on the destination host (default)
+
+:option:`<server>`
+    Server to migrate (name or ID)
+
+server pause
+------------
+
+Pause server
+
+.. code:: bash
+
+    os server pause
+        <server>
+
+:option:`<server>`
+    Server (name or ID)
+
+server reboot
+-------------
+
+Perform a hard or soft server reboot
+
+.. code:: bash
+
+    os server reboot
+        [--hard | --soft]
+        [--wait]
+        <server>
+
+:option:`--hard`
+    Perform a hard reboot
+
+:option:`--soft`
+    Perform a soft reboot
+
+:option:`--wait`
+    Wait for reboot to complete
+
+:option:`<server>`
+    Server (name or ID)
+
+server rebuild
+--------------
+
+Rebuild server
+
+.. code:: bash
+
+    os server rebuild
+        --image <image>
+        [--password <password>]
+        [--wait]
+        <server>
+
+:option:`--image` <image>
+    Recreate server from this image
+
+:option:`--password` <password>
+    Set the password on the rebuilt instance
+
+:option:`--wait`
+    Wait for rebuild to complete
+
+:option:`<server>`
+    Server (name or ID)
+
+server remove security group
+----------------------------
+
+Remove security group from server
+
+.. code:: bash
+
+    os server remove security group
+        <server>
+        <group>
+
+:option:`<server>`
+    Name or ID of server to use
+
+:option:`<group>`
+    Name or ID of security group to remove from server
+
+server remove volume
+--------------------
+
+Remove volume from server
+
+.. code:: bash
+
+    os server remove volume
+        <server>
+        <volume>
+
+:option:`<server>`
+    Server (name or ID)
+
+:option:`<volume>`
+    Volume to remove (name or ID)
+
+server rescue
+-------------
+
+Put server in rescue mode
+
+.. code:: bash
+
+    os server rescue
+        <server>
+
+:option:`<server>`
+    Server (name or ID)
+
+server resize
+-------------
+
+Scale server to a new flavor
+
+.. code:: bash
+
+    os server resize
+        --flavor <flavor>
+        [--wait]
+        <server>
+
+    os server resize
+        --verify | --revert
+        <server>
+
+:option:`--flavor` <flavor>
+    Resize server to specified flavor
+
+:option:`--verify`
+    Verify server resize is complete
+
+:option:`--revert`
+    Restore server state before resize
+
+:option:`--wait`
+    Wait for resize to complete
+
+:option:`<server>`
+    Server (name or ID)
+
+A resize operation is implemented by creating a new server and copying
+the contents of the original disk into a new one.  It is also a two-step
+process for the user: the first is to perform the resize, the second is
+to either confirm (verify) success and release the old server, or to declare
+a revert to release the new server and restart the old one.
+
+server resume
+-------------
+
+Resume server
+
+.. code:: bash
+
+    os server resume
+        <server>
+
+:option:`<server>`
+    Server (name or ID)
+
+server set
+----------
+
+Set server properties
+
+.. code:: bash
+
+    os server set
+        --name <new-name>
+        --property <key=value>
+        [--property <key=value>] ...
+        --root-password
+        <server>
+
+:option:`--name` <new-name>
+    New server name
+
+:option:`--root-password`
+    Set new root password (interactive only)
+
+:option:`--property` <key=value>
+    Property to add/change for this server (repeat option to set
+    multiple properties)
+
+:option:`<server>`
+    Server (name or ID)
+
+server show
+-----------
+
+Show server details
+
+.. code:: bash
+
+    os server show
+        [--diagnostics]
+        <server>
+
+:option:`--diagnostics`
+    Display server diagnostics information
+
+:option:`<server>`
+    Server (name or ID)
+
+server ssh
+----------
+
+Ssh to server
+
+.. code:: bash
+
+    os server ssh
+        [--login <login-name>]
+        [--port <port>]
+        [--identity <keyfile>]
+        [--option <config-options>]
+        [--public | --private | --address-type <address-type>]
+        <server>
+
+:option:`--login` <login-name>
+    Login name (ssh -l option)
+
+:option:`--port` <port>
+    Destination port (ssh -p option)
+
+:option:`--identity` <keyfile>
+    Private key file (ssh -i option)
+
+:option:`--option` <config-options>
+    Options in ssh_config(5) format (ssh -o option)
+
+:option:`--public`
+    Use public IP address
+
+:option:`--private`
+    Use private IP address
+
+:option:`--address-type` <address-type>
+    Use other IP address (public, private, etc)
+
+:option:`<server>`
+    Server (name or ID)
+
+server suspend
+--------------
+
+Suspend server
+
+.. code:: bash
+
+    os server suspend
+        <server>
+
+:option:`<server>`
+    Server (name or ID)
+
+server unlock
+-------------
+
+Unlock server
+
+.. code:: bash
+
+    os server unlock
+        <server>
+
+:option:`<server>`
+    Server (name or ID)
+
+server unpause
+--------------
+
+Unpause server
+
+.. code:: bash
+
+    os server unpause
+        <server>
+
+:option:`<server>`
+    Server (name or ID)
+
+server unrescue
+---------------
+
+Restore server from rescue mode
+
+.. code:: bash
+
+    os server unrescue
+        <server>
+
+:option:`<server>`
+    Server (name or ID)
+
+server unset
+------------
+
+Unset server properties
+
+.. code:: bash
+
+    os server unset
+        --property <key>
+        [--property <key>] ...
+        <server>
+
+:option:`--property` <key>
+    Property key to remove from server (repeat to set multiple values)
+
+:option:`<server>`
+    Server (name or ID)
diff --git a/doc/source/commands.rst b/doc/source/commands.rst
index 250a8039d8..7b38134e42 100644
--- a/doc/source/commands.rst
+++ b/doc/source/commands.rst
@@ -100,7 +100,8 @@ referring to both Compute and Volume quotas.
 * ``role``: Identity - a policy object used to determine authorization
 * ``security group``: Compute, Network - groups of network access rules
 * ``security group rule``: Compute, Network - the individual rules that define protocol/IP/port access
-* ``server``: Compute - a virtual machine instance
+* ``server``: (**Compute**) virtual machine instance
+* ``server image``: (**Compute**) saved server disk image
 * ``service``: Identity - a cloud service
 * ``snapshot``: Volume - a point-in-time copy of a volume
 * ``token``: (**Identity**) a bearer token managed by Identity service
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index d58df86c10..5ab1d5f3ff 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -99,6 +99,43 @@ def _show_progress(progress):
         sys.stdout.flush()
 
 
+class AddServerSecurityGroup(command.Command):
+    """Add security group to server"""
+
+    log = logging.getLogger(__name__ + '.AddServerSecurityGroup')
+
+    def get_parser(self, prog_name):
+        parser = super(AddServerSecurityGroup, self).get_parser(prog_name)
+        parser.add_argument(
+            'server',
+            metavar='<server>',
+            help=_('Server (name or ID)'),
+        )
+        parser.add_argument(
+            'group',
+            metavar='<group>',
+            help=_('Security group to add (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
+
+        server = utils.find_resource(
+            compute_client.servers,
+            parsed_args.server,
+        )
+        security_group = utils.find_resource(
+            compute_client.security_groups,
+            parsed_args.group,
+        )
+
+        server.add_security_group(security_group.name)
+        return
+
+
 class AddServerVolume(command.Command):
     """Add volume to server"""
 
@@ -145,43 +182,6 @@ class AddServerVolume(command.Command):
         )
 
 
-class AddServerSecurityGroup(command.Command):
-    """Add security group to server"""
-
-    log = logging.getLogger(__name__ + '.AddServerSecurityGroup')
-
-    def get_parser(self, prog_name):
-        parser = super(AddServerSecurityGroup, self).get_parser(prog_name)
-        parser.add_argument(
-            'server',
-            metavar='<server>',
-            help=_('Name or ID of server to use'),
-        )
-        parser.add_argument(
-            'group',
-            metavar='<group>',
-            help=_('Name or ID of security group to add to server'),
-        )
-        return parser
-
-    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,
-        )
-        security_group = utils.find_resource(
-            compute_client.security_groups,
-            parsed_args.group,
-        )
-
-        server.add_security_group(security_group.name)
-        return
-
-
 class CreateServer(show.ShowOne):
     """Create a new server"""
 
@@ -192,55 +192,65 @@ class CreateServer(show.ShowOne):
         parser.add_argument(
             'server_name',
             metavar='<server-name>',
-            help=_('New server name'))
+            help=_('New server name'),
+        )
         disk_group = parser.add_mutually_exclusive_group(
             required=True,
         )
         disk_group.add_argument(
             '--image',
             metavar='<image>',
-            help=_('Create server from this image'))
+            help=_('Create server from this image'),
+        )
         disk_group.add_argument(
             '--volume',
             metavar='<volume>',
-            help=_('Create server from this volume'))
+            help=_('Create server from this volume'),
+        )
         parser.add_argument(
             '--flavor',
             metavar='<flavor>',
             required=True,
-            help=_('Create server with this flavor'))
+            help=_('Create server with this flavor'),
+        )
         parser.add_argument(
             '--security-group',
             metavar='<security-group-name>',
             action='append',
             default=[],
             help=_('Security group to assign to this server '
-                   '(repeat for multiple groups)'))
+                   '(repeat for multiple groups)'),
+        )
         parser.add_argument(
             '--key-name',
             metavar='<key-name>',
-            help=_('Keypair to inject into this server (optional extension)'))
+            help=_('Keypair to inject into this server (optional extension)'),
+        )
         parser.add_argument(
             '--property',
             metavar='<key=value>',
             action=parseractions.KeyValueAction,
             help=_('Set a property on this server '
-                   '(repeat for multiple values)'))
+                   '(repeat for multiple values)'),
+        )
         parser.add_argument(
             '--file',
             metavar='<dest-filename=source-filename>',
             action='append',
             default=[],
             help=_('File to inject into image before boot '
-                   '(repeat for multiple files)'))
+                   '(repeat for multiple files)'),
+        )
         parser.add_argument(
             '--user-data',
             metavar='<user-data>',
-            help=_('User data file to serve from the metadata server'))
+            help=_('User data file to serve from the metadata server'),
+        )
         parser.add_argument(
             '--availability-zone',
             metavar='<zone-name>',
-            help=_('Select an availability zone for the server'))
+            help=_('Select an availability zone for the server'),
+        )
         parser.add_argument(
             '--block-device-mapping',
             metavar='<dev-name=mapping>',
@@ -248,37 +258,43 @@ class CreateServer(show.ShowOne):
             default=[],
             help=_('Map block devices; map is '
                    '<id>:<type>:<size(GB)>:<delete_on_terminate> '
-                   '(optional extension)'))
+                   '(optional extension)'),
+        )
         parser.add_argument(
             '--nic',
             metavar='<nic-config-string>',
             action='append',
             default=[],
-            help=_('Specify NIC configuration (optional extension)'))
+            help=_('Specify NIC configuration (optional extension)'),
+        )
         parser.add_argument(
             '--hint',
             metavar='<key=value>',
             action='append',
             default=[],
-            help=_('Hints for the scheduler (optional extension)'))
+            help=_('Hints for the scheduler (optional extension)'),
+        )
         parser.add_argument(
             '--config-drive',
             metavar='<config-drive-volume>|True',
             default=False,
             help=_('Use specified volume as the config drive, '
-                   'or \'True\' to use an ephemeral drive'))
+                   'or \'True\' to use an ephemeral drive'),
+        )
         parser.add_argument(
             '--min',
             metavar='<count>',
             type=int,
             default=1,
-            help=_('Minimum number of servers to launch (default=1)'))
+            help=_('Minimum number of servers to launch (default=1)'),
+        )
         parser.add_argument(
             '--max',
             metavar='<count>',
             type=int,
             default=1,
-            help=_('Maximum number of servers to launch (default=1)'))
+            help=_('Maximum number of servers to launch (default=1)'),
+        )
         parser.add_argument(
             '--wait',
             action='store_true',
@@ -504,7 +520,8 @@ class DeleteServer(command.Command):
         parser.add_argument(
             'server',
             metavar='<server>',
-            help=_('Name or ID of server to delete'))
+            help=_('Server (name or ID)'),
+        )
         return parser
 
     def take_action(self, parsed_args):
@@ -526,50 +543,61 @@ class ListServer(lister.Lister):
         parser.add_argument(
             '--reservation-id',
             metavar='<reservation-id>',
-            help=_('Only return instances that match the reservation'))
+            help=_('Only return instances that match the reservation'),
+        )
         parser.add_argument(
             '--ip',
             metavar='<ip-address-regex>',
-            help=_('Regular expression to match IP addresses'))
+            help=_('Regular expression to match IP addresses'),
+        )
         parser.add_argument(
             '--ip6',
             metavar='<ip-address-regex>',
-            help=_('Regular expression to match IPv6 addresses'))
+            help=_('Regular expression to match IPv6 addresses'),
+        )
         parser.add_argument(
             '--name',
-            metavar='<name>',
-            help=_('Regular expression to match names'))
+            metavar='<name-regex>',
+            help=_('Regular expression to match names'),
+        )
+        parser.add_argument(
+            '--instance-name',
+            metavar='<server-name>',
+            help=_('Regular expression to match instance name (admin only)'),
+        )
         parser.add_argument(
             '--status',
             metavar='<status>',
             # FIXME(dhellmann): Add choices?
-            help=_('Search by server status'))
+            help=_('Search by server status'),
+        )
         parser.add_argument(
             '--flavor',
             metavar='<flavor>',
-            help=_('Search by flavor ID'))
+            help=_('Search by flavor'),
+        )
         parser.add_argument(
             '--image',
             metavar='<image>',
-            help=_('Search by image ID'))
+            help=_('Search by image'),
+        )
         parser.add_argument(
             '--host',
             metavar='<hostname>',
-            help=_('Search by hostname'))
-        parser.add_argument(
-            '--instance-name',
-            metavar='<server-name>',
-            help=_('Regular expression to match instance name (admin only)'))
+            help=_('Search by hostname'),
+        )
         parser.add_argument(
             '--all-projects',
             action='store_true',
             default=bool(int(os.environ.get("ALL_PROJECTS", 0))),
-            help=_('Include all projects (admin only)'))
+            help=_('Include all projects (admin only)'),
+        )
         parser.add_argument(
             '--long',
             action='store_true',
             default=False,
-            help=_('List additional fields in output'))
+            help=_('List additional fields in output'),
+        )
         return parser
 
     def take_action(self, parsed_args):
@@ -672,12 +700,7 @@ class MigrateServer(command.Command):
         parser.add_argument(
             'server',
             metavar='<server>',
-            help=_('Server to migrate (name or ID)'),
-        )
-        parser.add_argument(
-            '--wait',
-            action='store_true',
-            help=_('Wait for resize to complete'),
+            help=_('Server (name or ID)'),
         )
         parser.add_argument(
             '--live',
@@ -699,6 +722,12 @@ class MigrateServer(command.Command):
             help=_('Perform a block live migration'),
         )
         disk_group = parser.add_mutually_exclusive_group()
+        disk_group.add_argument(
+            '--disk-overcommit',
+            action='store_true',
+            default=False,
+            help=_('Allow disk over-commit on the destination host'),
+        )
         disk_group.add_argument(
             '--no-disk-overcommit',
             dest='disk_overcommit',
@@ -707,11 +736,10 @@ class MigrateServer(command.Command):
             help=_('Do not over-commit disk on the'
                    ' destination host (default)'),
         )
-        disk_group.add_argument(
-            '--disk-overcommit',
+        parser.add_argument(
+            '--wait',
             action='store_true',
-            default=False,
-            help=_('Allow disk over-commit on the destination host'),
+            help=_('Wait for resize to complete'),
         )
         return parser
 
@@ -1140,13 +1168,13 @@ class ShowServer(show.ShowOne):
         parser.add_argument(
             'server',
             metavar='<server>',
-            help=_('Server to show (name or ID)'),
+            help=_('Server (name or ID)'),
         )
         parser.add_argument(
             '--diagnostics',
             action='store_true',
             default=False,
-            help=_('Display diagnostics information for a given server'),
+            help=_('Display server diagnostics information'),
         )
         return parser
 
@@ -1439,7 +1467,7 @@ class UnsetServer(command.Command):
             action='append',
             default=[],
             help=_('Property key to remove from server '
-                   '(repeat to set multiple values)'),
+                   '(repeat to unset multiple values)'),
         )
         return parser