From 67ecf4ef436f3f70427658225a34c342ba8ea482 Mon Sep 17 00:00:00 2001
From: Brad Behle <behle@us.ibm.com>
Date: Wed, 27 Jan 2016 20:50:22 -0600
Subject: [PATCH] Add availability zone support for network commands

Add --availability-zone-hint parm to network create. Also add
availability_zones and availability_zone_hints to the network list and network
show commands

Change-Id: Ib4dc2e3e7897939be7bef6b25a095c8222b885bc
Partially-implements: blueprint neutron-client
---
 doc/source/command-objects/network.rst        |  6 +++++
 openstackclient/network/v2/network.py         | 21 +++++++++++++++++-
 openstackclient/tests/network/v2/fakes.py     |  5 ++++-
 .../tests/network/v2/test_network.py          | 22 ++++++++++++++++++-
 4 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/doc/source/command-objects/network.rst b/doc/source/command-objects/network.rst
index 7c791840fc..bb36667253 100644
--- a/doc/source/command-objects/network.rst
+++ b/doc/source/command-objects/network.rst
@@ -16,6 +16,7 @@ Create new network
         [--project <project> [--project-domain <project-domain>]]
         [--enable | --disable]
         [--share | --no-share]
+        [--availability-zone-hint <availability-zone>]
         <name>
 
 .. option:: --project <project>
@@ -43,6 +44,11 @@ Create new network
 
     Do not share the network between projects
 
+.. option:: --availability-zone-hint <availability-zone>
+
+     Availability Zone in which to create this network (requires the Network
+     Availability Zone extension, this option can be repeated).
+
 .. _network_create-name:
 .. describe:: <name>
 
diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py
index 38dff8d92a..7d9324f085 100644
--- a/openstackclient/network/v2/network.py
+++ b/openstackclient/network/v2/network.py
@@ -36,6 +36,8 @@ _formatters = {
     'subnets': utils.format_list,
     'admin_state_up': _format_admin_state,
     'router_external': _format_router_external,
+    'availability_zones': utils.format_list,
+    'availability_zone_hints': utils.format_list,
 }
 
 
@@ -93,8 +95,19 @@ class CreateNetwork(show.ShowOne):
         parser.add_argument(
             '--project',
             metavar='<project>',
-            help="Owner's project (name or ID)")
+            help="Owner's project (name or ID)"
+        )
         identity_common.add_project_domain_option_to_parser(parser)
+
+        parser.add_argument(
+            '--availability-zone-hint',
+            action='append',
+            dest='availability_zone_hints',
+            metavar='<availability-zone>',
+            help='Availability Zone in which to create this network '
+                 '(requires the Network Availability Zone extension, '
+                 'this option can be repeated).',
+        )
         return parser
 
     def take_action(self, parsed_args):
@@ -119,6 +132,10 @@ class CreateNetwork(show.ShowOne):
                 parsed_args.project_domain,
             ).id
             body['tenant_id'] = project_id
+        if parsed_args.availability_zone_hints is not None:
+            body['availability_zone_hints'] = \
+                parsed_args.availability_zone_hints
+
         return body
 
 
@@ -181,6 +198,7 @@ class ListNetwork(lister.Lister):
                 'subnets',
                 'provider_network_type',
                 'router_external',
+                'availability_zones',
             )
             column_headers = (
                 'ID',
@@ -192,6 +210,7 @@ class ListNetwork(lister.Lister):
                 'Subnets',
                 'Network Type',
                 'Router Type',
+                'Availability Zones',
             )
         else:
             columns = (
diff --git a/openstackclient/tests/network/v2/fakes.py b/openstackclient/tests/network/v2/fakes.py
index de885c62ab..146ba61649 100644
--- a/openstackclient/tests/network/v2/fakes.py
+++ b/openstackclient/tests/network/v2/fakes.py
@@ -85,6 +85,8 @@ class FakeNetwork(object):
             'provider_network_type': 'vlan',
             'router_external': True,
             'is_dirty': True,
+            'availability_zones': [],
+            'availability_zone_hints': [],
         }
 
         # Overwrite default attributes.
@@ -93,7 +95,8 @@ class FakeNetwork(object):
         # Set default methods.
         network_methods = {
             'keys': ['id', 'name', 'admin_state_up', 'router_external',
-                     'status', 'subnets', 'tenant_id'],
+                     'status', 'subnets', 'tenant_id', 'availability_zones',
+                     'availability_zone_hints'],
         }
 
         # Overwrite default methods.
diff --git a/openstackclient/tests/network/v2/test_network.py b/openstackclient/tests/network/v2/test_network.py
index 12ac802c82..37cc66742a 100644
--- a/openstackclient/tests/network/v2/test_network.py
+++ b/openstackclient/tests/network/v2/test_network.py
@@ -37,11 +37,16 @@ class TestCreateNetworkIdentityV3(TestNetwork):
 
     # The new network created.
     _network = network_fakes.FakeNetwork.create_one_network(
-        attrs={'tenant_id': identity_fakes_v3.project_id}
+        attrs={
+            'tenant_id': identity_fakes_v3.project_id,
+            'availability_zone_hints': ["nova"],
+        }
     )
 
     columns = (
         'admin_state_up',
+        'availability_zone_hints',
+        'availability_zones',
         'id',
         'name',
         'project_id',
@@ -52,6 +57,8 @@ class TestCreateNetworkIdentityV3(TestNetwork):
 
     data = (
         network._format_admin_state(_network.admin_state_up),
+        utils.format_list(_network.availability_zone_hints),
+        utils.format_list(_network.availability_zones),
         _network.id,
         _network.name,
         _network.project_id,
@@ -129,6 +136,7 @@ class TestCreateNetworkIdentityV3(TestNetwork):
             "--share",
             "--project", identity_fakes_v3.project_name,
             "--project-domain", identity_fakes_v3.domain_name,
+            "--availability-zone-hint", "nova",
             self._network.name,
         ]
         verifylist = [
@@ -136,6 +144,7 @@ class TestCreateNetworkIdentityV3(TestNetwork):
             ('shared', True),
             ('project', identity_fakes_v3.project_name),
             ('project_domain', identity_fakes_v3.domain_name),
+            ('availability_zone_hints', ["nova"]),
             ('name', self._network.name),
         ]
 
@@ -144,6 +153,7 @@ class TestCreateNetworkIdentityV3(TestNetwork):
 
         self.network.create_network.assert_called_with(**{
             'admin_state_up': False,
+            'availability_zone_hints': ["nova"],
             'name': self._network.name,
             'shared': True,
             'tenant_id': identity_fakes_v3.project_id,
@@ -184,6 +194,8 @@ class TestCreateNetworkIdentityV2(TestNetwork):
 
     columns = (
         'admin_state_up',
+        'availability_zone_hints',
+        'availability_zones',
         'id',
         'name',
         'project_id',
@@ -194,6 +206,8 @@ class TestCreateNetworkIdentityV2(TestNetwork):
 
     data = (
         network._format_admin_state(_network.admin_state_up),
+        utils.format_list(_network.availability_zone_hints),
+        utils.format_list(_network.availability_zones),
         _network.id,
         _network.name,
         _network.project_id,
@@ -324,6 +338,7 @@ class TestListNetwork(TestNetwork):
         'Subnets',
         'Network Type',
         'Router Type',
+        'Availability Zones',
     )
 
     data = []
@@ -346,6 +361,7 @@ class TestListNetwork(TestNetwork):
             utils.format_list(net.subnets),
             net.provider_network_type,
             network._format_router_external(net.router_external),
+            utils.format_list(net.availability_zones),
         ))
 
     def setUp(self):
@@ -483,6 +499,8 @@ class TestShowNetwork(TestNetwork):
 
     columns = (
         'admin_state_up',
+        'availability_zone_hints',
+        'availability_zones',
         'id',
         'name',
         'project_id',
@@ -493,6 +511,8 @@ class TestShowNetwork(TestNetwork):
 
     data = (
         network._format_admin_state(_network.admin_state_up),
+        utils.format_list(_network.availability_zone_hints),
+        utils.format_list(_network.availability_zones),
         _network.id,
         _network.name,
         _network.project_id,