From e8c731547d85b1241c7898d2fb77b8d635901dfd Mon Sep 17 00:00:00 2001
From: Harald Jensas <hjensas@redhat.com>
Date: Mon, 27 Nov 2017 21:08:26 +0100
Subject: [PATCH] Allow setting network-segment on subnet update

To enable the possibility to migrate a non-routed network to a
routed network allow updating the segment_id of a subnet.

Change-Id: I3ebae2ff28d5d4e5373ebd1f52194f8c52071b88
Partial-Bug: bug/1692490
Depends-On: I1aee29dfb59e9769ec0f1cb1f5d2933bc5dc0dc5
---
 doc/source/cli/command-objects/subnet.rst     |  8 +++++++
 openstackclient/network/v2/subnet.py          | 16 +++++++++----
 .../tests/unit/network/v2/test_subnet.py      | 23 +++++++++++++++++++
 ...ubnet-set-segment-id-4440e433b170f9f3.yaml |  5 ++++
 4 files changed, 48 insertions(+), 4 deletions(-)
 create mode 100644 releasenotes/notes/subnet-set-segment-id-4440e433b170f9f3.yaml

diff --git a/doc/source/cli/command-objects/subnet.rst b/doc/source/cli/command-objects/subnet.rst
index 0a56ccf18b..73e656d895 100644
--- a/doc/source/cli/command-objects/subnet.rst
+++ b/doc/source/cli/command-objects/subnet.rst
@@ -265,6 +265,7 @@ Set subnet properties
         [--dns-nameserver <dns-nameserver>]
         [--no-dns-nameserver]
         [--gateway <gateway-ip>]
+        [--network-segment <network-segment>]
         [--host-route destination=<subnet>,gateway=<ip-address>]
         [--no-host-route]
         [--service-type <service-type>]
@@ -310,6 +311,13 @@ Set subnet properties
      'none': This subnet will not use a gateway,
      e.g.: ``--gateway 192.168.9.1``, ``--gateway none``.
 
+.. option:: --network-segment <network-segment>
+
+     Network segment to associate with this subnet (name or ID). It is only
+     allowed to set the segment if the current value is `None`, the network
+     must also have only one segment and only one subnet can exist on the
+     network.
+
 .. option:: --host-route destination=<subnet>,gateway=<ip-address>
 
      Additional route for this subnet e.g.:
diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py
index 2c71e1e085..b5a8b35af8 100644
--- a/openstackclient/network/v2/subnet.py
+++ b/openstackclient/network/v2/subnet.py
@@ -167,6 +167,7 @@ def convert_entries_to_gateway(entries):
 
 def _get_attrs(client_manager, parsed_args, is_create=True):
     attrs = {}
+    client = client_manager.network
     if 'name' in parsed_args and parsed_args.name is not None:
         attrs['name'] = str(parsed_args.name)
 
@@ -179,7 +180,6 @@ def _get_attrs(client_manager, parsed_args, is_create=True):
                 parsed_args.project_domain,
             ).id
             attrs['tenant_id'] = project_id
-        client = client_manager.network
         attrs['network_id'] = client.find_network(parsed_args.network,
                                                   ignore_missing=False).id
         if parsed_args.subnet_pool is not None:
@@ -200,10 +200,10 @@ def _get_attrs(client_manager, parsed_args, is_create=True):
             attrs['ipv6_ra_mode'] = parsed_args.ipv6_ra_mode
         if parsed_args.ipv6_address_mode is not None:
             attrs['ipv6_address_mode'] = parsed_args.ipv6_address_mode
-        if parsed_args.network_segment is not None:
-            attrs['segment_id'] = client.find_segment(
-                parsed_args.network_segment, ignore_missing=False).id
 
+    if parsed_args.network_segment is not None:
+        attrs['segment_id'] = client.find_segment(
+            parsed_args.network_segment, ignore_missing=False).id
     if 'gateway' in parsed_args and parsed_args.gateway is not None:
         gateway = parsed_args.gateway.lower()
 
@@ -558,6 +558,14 @@ class SetSubnet(command.Command):
                    "'none': This subnet will not use a gateway, "
                    "e.g.: --gateway 192.168.9.1, --gateway none.")
         )
+        parser.add_argument(
+            '--network-segment',
+            metavar='<network-segment>',
+            help=_("Network segment to associate with this subnet (name or "
+                   "ID). It is only allowed to set the segment if the current "
+                   "value is `None`, the network must also have only one "
+                   "segment and only one subnet can exist on the network.")
+        )
         parser.add_argument(
             '--description',
             metavar='<description>',
diff --git a/openstackclient/tests/unit/network/v2/test_subnet.py b/openstackclient/tests/unit/network/v2/test_subnet.py
index b7f741cd91..f5212c6172 100644
--- a/openstackclient/tests/unit/network/v2/test_subnet.py
+++ b/openstackclient/tests/unit/network/v2/test_subnet.py
@@ -1074,6 +1074,29 @@ class TestSetSubnet(TestSubnet):
     def test_set_with_no_tag(self):
         self._test_set_tags(with_tags=False)
 
+    def test_set_segment(self):
+        _net = network_fakes.FakeNetwork.create_one_network()
+        _segment = network_fakes.FakeNetworkSegment.create_one_network_segment(
+            attrs={'network_id': _net.id})
+        _subnet = network_fakes.FakeSubnet.create_one_subnet(
+            {'host_routes': [{'destination': '10.20.20.0/24',
+                              'nexthop': '10.20.20.1'}],
+             'allocation_pools': [{'start': '8.8.8.200',
+                                   'end': '8.8.8.250'}],
+             'dns_nameservers': ["10.0.0.1"],
+             'network_id': _net.id,
+             'segment_id': None})
+        self.network.find_subnet = mock.Mock(return_value=_subnet)
+        self.network.find_segment = mock.Mock(return_value=_segment)
+        arglist = ['--network-segment', _segment.id, _subnet.name]
+        verifylist = [('network_segment', _segment.id)]
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        result = self.cmd.take_action(parsed_args)
+        attrs = {'segment_id': _segment.id}
+        self.network.update_subnet.assert_called_once_with(_subnet, **attrs)
+        self.network.update_subnet.assert_called_with(_subnet, **attrs)
+        self.assertIsNone(result)
+
 
 class TestShowSubnet(TestSubnet):
     # The subnets to be shown
diff --git a/releasenotes/notes/subnet-set-segment-id-4440e433b170f9f3.yaml b/releasenotes/notes/subnet-set-segment-id-4440e433b170f9f3.yaml
new file mode 100644
index 0000000000..55a823188a
--- /dev/null
+++ b/releasenotes/notes/subnet-set-segment-id-4440e433b170f9f3.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - Add ``--network-segment`` option to ``subnet set`` command. This
+    enables the possiblity to set the ``segment_id`` of a subnet on
+    update.