From 58f1c90971969ee12089c2e5aeea4993d8c095d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafael=20Weing=C3=A4rtner?= <rafael@apache.org>
Date: Wed, 2 Sep 2020 17:26:00 -0300
Subject: [PATCH] Add source_ip_prefix and destination_ip_prefix to metering
 label rules

As proposed in the RFE and then approved in the spec, we are adding to
the neutron metering rules two new parameters. The source IP prefix, and
destination IP prefix.

Partially-Implements: https://bugs.launchpad.net/neutron/+bug/1889431
RFE: https://bugs.launchpad.net/neutron/+bug/1889431

Depends-On: https://review.opendev.org/#/c/746586/
Change-Id: Ic44d88fabea0fffef2279f2f2c3d2b1da6426d4d
---
 .../network/v2/network_meter_rule.py          | 22 ++++++++++++++++++-
 .../tests/unit/network/v2/fakes.py            |  2 ++
 .../network/v2/test_network_meter_rule.py     | 12 ++++++++++
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/openstackclient/network/v2/network_meter_rule.py b/openstackclient/network/v2/network_meter_rule.py
index 49ff9e1b0e..1cf0395f44 100644
--- a/openstackclient/network/v2/network_meter_rule.py
+++ b/openstackclient/network/v2/network_meter_rule.py
@@ -46,6 +46,10 @@ def _get_attrs(client_manager, parsed_args):
         attrs['direction'] = 'egress'
     if parsed_args.remote_ip_prefix is not None:
         attrs['remote_ip_prefix'] = parsed_args.remote_ip_prefix
+    if parsed_args.source_ip_prefix is not None:
+        attrs['source_ip_prefix'] = parsed_args.source_ip_prefix
+    if parsed_args.destination_ip_prefix is not None:
+        attrs['destination_ip_prefix'] = parsed_args.destination_ip_prefix
     if parsed_args.meter is not None:
         attrs['metering_label_id'] = parsed_args.meter
     if parsed_args.project is not None:
@@ -97,9 +101,21 @@ class CreateMeterRule(command.ShowOne):
         parser.add_argument(
             '--remote-ip-prefix',
             metavar='<remote-ip-prefix>',
-            required=True,
+            required=False,
             help=_('The remote IP prefix to associate with this rule'),
         )
+        parser.add_argument(
+            '--source-ip-prefix',
+            metavar='<remote-ip-prefix>',
+            required=False,
+            help=_('The source IP prefix to associate with this rule'),
+        )
+        parser.add_argument(
+            '--destination-ip-prefix',
+            metavar='<remote-ip-prefix>',
+            required=False,
+            help=_('The destination IP prefix to associate with this rule'),
+        )
         parser.add_argument(
             'meter',
             metavar='<meter>',
@@ -168,12 +184,16 @@ class ListMeterRule(command.Lister):
             'excluded',
             'direction',
             'remote_ip_prefix',
+            'source_ip_prefix',
+            'destination_ip_prefix',
         )
         column_headers = (
             'ID',
             'Excluded',
             'Direction',
             'Remote IP Prefix',
+            'Source IP Prefix',
+            'Destination IP Prefix',
         )
         data = client.metering_label_rules()
         return (column_headers,
diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py
index cef0a11c91..5095cb9125 100644
--- a/openstackclient/tests/unit/network/v2/fakes.py
+++ b/openstackclient/tests/unit/network/v2/fakes.py
@@ -1590,6 +1590,8 @@ class FakeNetworkMeterRule(object):
             'excluded': False,
             'metering_label_id': 'meter-label-id-' + uuid.uuid4().hex,
             'remote_ip_prefix': '10.0.0.0/24',
+            'source_ip_prefix': '8.8.8.8/32',
+            'destination_ip_prefix': '10.0.0.0/24',
             'tenant_id': 'project-id-' + uuid.uuid4().hex,
         }
 
diff --git a/openstackclient/tests/unit/network/v2/test_network_meter_rule.py b/openstackclient/tests/unit/network/v2/test_network_meter_rule.py
index 8f8922c020..e9224fa650 100644
--- a/openstackclient/tests/unit/network/v2/test_network_meter_rule.py
+++ b/openstackclient/tests/unit/network/v2/test_network_meter_rule.py
@@ -42,20 +42,24 @@ class TestCreateMeterRule(TestMeterRule):
     )
 
     columns = (
+        'destination_ip_prefix',
         'direction',
         'excluded',
         'id',
         'metering_label_id',
         'project_id',
         'remote_ip_prefix',
+        'source_ip_prefix',
     )
     data = (
+        new_rule.destination_ip_prefix,
         new_rule.direction,
         new_rule.excluded,
         new_rule.id,
         new_rule.metering_label_id,
         new_rule.project_id,
         new_rule.remote_ip_prefix,
+        new_rule.source_ip_prefix,
     )
 
     def setUp(self):
@@ -228,6 +232,8 @@ class TestListMeterRule(TestMeterRule):
         'Excluded',
         'Direction',
         'Remote IP Prefix',
+        'Source IP Prefix',
+        'Destination IP Prefix'
     )
 
     data = []
@@ -238,6 +244,8 @@ class TestListMeterRule(TestMeterRule):
             rule.excluded,
             rule.direction,
             rule.remote_ip_prefix,
+            rule.source_ip_prefix,
+            rule.destination_ip_prefix
         ))
 
     def setUp(self):
@@ -270,21 +278,25 @@ class TestShowMeterRule(TestMeterRule):
     )
 
     columns = (
+        'destination_ip_prefix',
         'direction',
         'excluded',
         'id',
         'metering_label_id',
         'project_id',
         'remote_ip_prefix',
+        'source_ip_prefix',
     )
 
     data = (
+        new_rule.destination_ip_prefix,
         new_rule.direction,
         new_rule.excluded,
         new_rule.id,
         new_rule.metering_label_id,
         new_rule.project_id,
         new_rule.remote_ip_prefix,
+        new_rule.source_ip_prefix,
     )
 
     def setUp(self):