Add tests to cover trunks subports

This patch set adds tests to cover the neutron subports API [0].
Test adds, gets, removes trunks subports.
Part of "Increase Neutron RBAC Coverage" initiative [1]

[0] https://developer.openstack.org/api-ref/network/v2/index.html#add-subports-to-trunk
[1] https://storyboard.openstack.org/#!/story/2002641

Change-Id: I5ddefe2df23b4888ce6706a27784c461f9af1614
Story: 2002641
Task: 22328
diff --git a/patrole_tempest_plugin/tests/api/network/test_trunks_rbac.py b/patrole_tempest_plugin/tests/api/network/test_trunks_rbac.py
index 4b2eefd..80c4157 100644
--- a/patrole_tempest_plugin/tests/api/network/test_trunks_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_trunks_rbac.py
@@ -83,3 +83,105 @@
 
         with self.rbac_utils.override_role(self):
             self.ntp_client.delete_trunk(trunk['trunk']['id'])
+
+
+class TrunksSubportsExtRbacTest(base.BaseNetworkExtRbacTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(TrunksSubportsExtRbacTest, cls).skip_checks()
+        if not utils.is_extension_enabled('trunk', 'network'):
+            msg = "trunk extension not enabled."
+            raise cls.skipException(msg)
+
+    @classmethod
+    def resource_setup(cls):
+        super(TrunksSubportsExtRbacTest, cls).resource_setup()
+        cls.network = cls.create_network()
+        cls.port_id = cls.create_port(cls.network)["id"]
+        cls.trunk_id = cls.ntp_client.create_trunk(
+            cls.port_id, [])['trunk']['id']
+
+        cls.addClassResourceCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            cls.ntp_client.delete_trunk, cls.trunk_id)
+
+    def create_subports(self, trunk_id, port_id):
+        subports = [{'port_id': port_id,
+                     'segmentation_type': 'vlan',
+                     'segmentation_id': 4000}]
+        sub = self.ntp_client.add_subports(trunk_id, subports)
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.ntp_client.remove_subports,
+            trunk_id, subports)
+        return sub["sub_ports"]
+
+    @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08133')
+    @rbac_rule_validation.action(service="neutron",
+                                 rules=["get_trunk",
+                                        "get_subports"],
+                                 expected_error_codes=[404, 403])
+    def test_get_subports(self):
+        """Get subports.
+
+        RBAC test for the neutron "get_subports" policy.
+
+        Error 403 expected due to implementation of subports as a part of
+        trunk object.
+        """
+        network = self.create_network()
+        port = self.create_port(network)
+
+        self.create_subports(self.trunk_id, port["id"])
+
+        with self.rbac_utils.override_role(self):
+            self.ntp_client.get_subports(self.trunk_id)
+
+    @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08134')
+    @rbac_rule_validation.action(service="neutron",
+                                 rules=["get_trunk",
+                                        "add_subports"],
+                                 expected_error_codes=[404, 403])
+    def test_add_subports(self):
+        """Add subports.
+
+        RBAC test for the neutron "add_subports" policy
+
+        Error 403 expected due to implementation of subports as a part of
+        trunk object.
+        """
+        network = self.create_network()
+        port = self.create_port(network)
+
+        subports = [{'port_id': port["id"],
+                     'segmentation_type': 'vlan',
+                     'segmentation_id': 4000}]
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.ntp_client.remove_subports,
+            self.trunk_id, subports)
+
+        with self.rbac_utils.override_role(self):
+            self.ntp_client.add_subports(self.trunk_id, subports)
+
+    @decorators.idempotent_id('c02618e7-bb20-1a3a-83c8-6eec2af08135')
+    @rbac_rule_validation.action(service="neutron",
+                                 rules=["get_trunk",
+                                        "remove_subports"],
+                                 expected_error_codes=[404, 403])
+    def test_remove_subports(self):
+        """Remove subports.
+
+        RBAC test for the neutron "remove_subports" policy
+
+        Error 403 expected due to implementation of subports as a part of
+        trunk object.
+        """
+        network = self.create_network()
+        port = self.create_port(network)
+
+        subports = self.create_subports(self.trunk_id, port["id"])
+
+        with self.rbac_utils.override_role(self):
+            self.ntp_client.remove_subports(self.trunk_id, subports)