Browse Source

Detaching the API from OpenStack Dependencies

- removing OpenStack imports from the API
- moving mech driver related logging into the mech driver
- updated tests to provide 100% coverage of API and mech driver
- updated docs to reflect updates to syntax in API

Change-Id: Ia855fd57d1c1ee4f9d90e40b998d62c3bc46f794
Dan Radez 6 months ago
parent
commit
e0d18657d4

+ 26
- 15
doc/source/user/api.rst View File

@@ -13,9 +13,9 @@ execute switch level network configuration.
13 13
 
14 14
 #. In a python environment import the networking-ansible class.
15 15
 
16
-  .. code-block:: console
16
+    .. code-block:: console
17 17
 
18
-    from networking_ansible.api import NetworkingAnsible
18
+      from networking_ansible.api import NetworkingAnsible
19 19
 
20 20
 #. Instantiate the NetworkingAnsible class. This requires a dictionary that
21 21
    represents an Ansible Inventory data structure. This data structure could be
@@ -23,24 +23,35 @@ execute switch level network configuration.
23 23
    class. This example will statically assign the data structure to a variable
24 24
    to show the expected data structure.
25 25
 
26
-  .. code-block:: console
26
+    .. code-block:: console
27 27
 
28
-    inventory = {'all':
29
-      {'hosts':
30
-        {'examplehost':
31
-          {'ansible_network_os': 'openswitch',
32
-           'ansible_host': '5.6.7.8',
33
-           'ansible_user': 'ansible',
34
-           'ansible_ssh_pass': 'password',
28
+      inventory = {'all':
29
+        {'hosts':
30
+          {'examplehost':
31
+            {'ansible_network_os': 'openswitch',
32
+             'ansible_host': '5.6.7.8',
33
+             'ansible_user': 'ansible',
34
+             'ansible_ssh_pass': 'password',
35
+            }
35 36
           }
36 37
         }
37 38
       }
38
-    }
39
-    net_ans = NetworkingAnsible(inventory)
39
+      net_ans = NetworkingAnsible(inventory)
40 40
 
41 41
 #. Call functions to configure the inventory.
42 42
 
43
-  .. code-block:: console
43
+    .. code-block:: console
44
+
45
+      host = 'examplehost'
46
+      port = 'port123'
47
+      vlan_id = 37
48
+
49
+      # create the VLAN
50
+      net_ans.create_vlan(host, vlan_id)
51
+      # configure a port in access mode on the VLAN
52
+      net_ans.update_access_port(host, port, vlan_id)
53
+      # shutdown the port
54
+      net_ans.delete_port(host, port)
55
+      # delete the VLAN
56
+      net_ans.delete_vlan(host, vlan_id)
44 57
 
45
-    vlan = 37
46
-    net_ans.create_network(vlan)

+ 23
- 62
networking_ansible/api.py View File

@@ -14,12 +14,9 @@
14 14
 #    under the License.
15 15
 
16 16
 import ansible_runner
17
-from oslo_log import log as logging
18 17
 
19 18
 from networking_ansible import exceptions
20 19
 
21
-LOG = logging.getLogger(__name__)
22
-
23 20
 
24 21
 class NetworkingAnsible(object):
25 22
     """Object to invoke ansible_runner to call Ansible Networking
@@ -31,7 +28,7 @@ class NetworkingAnsible(object):
31 28
     def __init__(self, inventory):
32 29
         self.inventory = inventory
33 30
 
34
-    def _run_task(self, task, host_name, segmentation_id, switch_port=None):
31
+    def _run_task(self, task, hostname, port=None, vlan_id=None):
35 32
         """Run a task.
36 33
 
37 34
         :param task: name of task in openstack-ml2 ansible role
@@ -45,7 +42,7 @@ class NetworkingAnsible(object):
45 42
         # build out the ansible playbook
46 43
         playbook = [{
47 44
             'name': 'Openstack networking-ansible playbook',
48
-            'hosts': host_name,
45
+            'hosts': hostname,
49 46
             'gather_facts': 'no',  # no need to gather facts every run
50 47
             'tasks': [{
51 48
                 'name': 'do {}'.format(task),
@@ -54,80 +51,44 @@ class NetworkingAnsible(object):
54 51
                     'tasks_from': task,
55 52
                 },
56 53
                 'vars': {
57
-                    'segmentation_id': segmentation_id,
54
+                    'segmentation_id': vlan_id,
58 55
                 }
59 56
             }]
60 57
         }]
61
-        if switch_port:
62
-            playbook[0]['tasks'][0]['vars']['port_name'] = switch_port
63
-            playbook[0]['tasks'][0]['vars']['port_description'] = switch_port
58
+        if port:
59
+            playbook[0]['tasks'][0]['vars']['port_name'] = port
60
+            playbook[0]['tasks'][0]['vars']['port_description'] = port
64 61
 
65
-        # TODO(radez) should we pass ident?
62
+        # invoke ansible networking via ansible runner
66 63
         result = ansible_runner.run(playbook=playbook,
67 64
                                     inventory=self.inventory,
68 65
                                     settings={'pexpect_use_poll': False})
66
+        # check for failure
69 67
         if result.status == 'failed' or \
70 68
                 (result.stats and result.stats.get('failures', [])):
71 69
             raise exceptions.AnsibleRunnerException(' '.join(result.stdout))
72 70
         return result
73 71
 
74
-    def create_network(self, host_name, segmentation_id):
75
-        self._run_task('create_network', host_name, segmentation_id)
72
+    def create_vlan(self, hostname, vlan_id):
73
+        return self._run_task('create_network', hostname, vlan_id=vlan_id)
76 74
 
77
-    def delete_network(self, host_name, segmentation_id):
78
-        self._run_task('delete_network', host_name, segmentation_id)
75
+    def delete_vlan(self, hostname, vlan_id):
76
+        return self._run_task('delete_network', hostname, vlan_id=vlan_id)
79 77
 
80
-    def vlan_access_port(self, assign_remove, port, network):
81
-        """Assign an access port to a vlan.
78
+    def update_access_port(self, hostname, port, vlan_id):
79
+        """Configure access port on a vlan or shutdown the port.
82 80
 
83 81
         If the configuration required to unplug the port is not present
84 82
         (e.g. local link information), the port will not be unplugged and no
85 83
         exception will be raised.
86 84
 
87
-        :param assign_remove: 'assign' or 'remove'
88
-        :param port: The port to unplug
89
-        :param network: The network from which to unplug the port
85
+        :param hostname: The name of the host in Ansible inventory.
86
+        :param port: The port to configure.
87
+        :param lan_id: The vlan_id to assign to the port.
88
+                       An empty is will get translated in Ansible to the
89
+                       target device's default VLAN assignment.
90 90
         """
91
-        task = {'assign': 'update_port',
92
-                'remove': 'delete_port'}
93
-        debug_msg = {'assign': 'Plugging in port {switch_port} on '
94
-                               '{switch_name} to vlan: {segmentation_id}',
95
-                     'remove': 'Unplugging port {switch_port} on '
96
-                               '{switch_name} from vlan: {segmentation_id}'}
97
-        info_msg = {'assign': 'Port {neutron_port} has been plugged into '
98
-                              'network {net_id} on device {switch_name}',
99
-                    'remove': 'Port {neutron_port} has been unplugged from '
100
-                              'network {net_id} on device {switch_name}'}
101
-        error_msg = {'assign': 'Failed to unplug port {neutron_port} on '
102
-                               'device: {switch_name} from network {net_id} '
103
-                               'reason: {exc}',
104
-                     'remove': 'Failed to plug in port {neutron_port} on '
105
-                               'device: {switch_name} from network {net_id} '
106
-                               'reason: {exc}'}
107
-
108
-        # If segmentation ID is None, its default is defined in ansible
109
-        segmentation_id = network['provider:segmentation_id'] or ''
110
-
111
-        local_link_info = port['binding:profile'].get('local_link_information')
112
-        if not local_link_info:
113
-            return
114
-        switch_name = local_link_info[0].get('switch_info')
115
-        switch_port = local_link_info[0].get('port_id')
116
-        try:
117
-            LOG.debug(debug_msg[assign_remove].format(
118
-                switch_port=switch_port,
119
-                switch_name=switch_name,
120
-                segmentation_id=segmentation_id))
121
-            self._run_task(task[assign_remove], switch_name,
122
-                           segmentation_id, switch_port)
123
-            LOG.info(info_msg[assign_remove].format(
124
-                neutron_port=port['id'],
125
-                net_id=network['id'],
126
-                switch_name=switch_name))
127
-        except Exception as e:
128
-            LOG.error(error_msg[assign_remove].format(
129
-                neutron_port=port['id'],
130
-                net_id=network['id'],
131
-                switch_name=switch_name,
132
-                exc=e))
133
-            raise
91
+        return self._run_task('update_port', hostname, port, vlan_id)
92
+
93
+    def delete_port(self, hostname, port):
94
+        return self._run_task('delete_port', hostname, port)

+ 2
- 7
networking_ansible/exceptions.py View File

@@ -13,12 +13,7 @@
13 13
 #    License for the specific language governing permissions and limitations
14 14
 #    under the License.
15 15
 
16
-from neutron_lib._i18n import _
17
-from neutron_lib import exceptions
18
-
19
-
20
-class AnsibleRunnerException(exceptions.NeutronException):
21
-    message = _('%(stdout)s')
22 16
 
17
+class AnsibleRunnerException(Exception):
23 18
     def __init__(self, message):
24
-        super(AnsibleRunnerException, self).__init__(stdout=message)
19
+        super(AnsibleRunnerException, self).__init__(message)

+ 24
- 0
networking_ansible/ml2/exceptions.py View File

@@ -0,0 +1,24 @@
1
+# Copyright (c) 2018 Red Hat Inc.
2
+# All Rights Reserved.
3
+#
4
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+#    not use this file except in compliance with the License. You may obtain
6
+#    a copy of the License at
7
+#
8
+#         http://www.apache.org/licenses/LICENSE-2.0
9
+#
10
+#    Unless required by applicable law or agreed to in writing, software
11
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+#    License for the specific language governing permissions and limitations
14
+#    under the License.
15
+
16
+from neutron_lib._i18n import _
17
+from neutron_lib import exceptions
18
+
19
+
20
+class LocalLinkInfoMissingException(exceptions.NeutronException):
21
+    message = _('%(stdout)s')
22
+
23
+    def __init__(self, message):
24
+        super(LocalLinkInfoMissingException, self).__init__(stdout=message)

+ 108
- 20
networking_ansible/ml2/mech_driver.py View File

@@ -22,6 +22,8 @@ from oslo_log import log as logging
22 22
 
23 23
 from networking_ansible import api
24 24
 from networking_ansible import config
25
+from networking_ansible.ml2 import exceptions
26
+
25 27
 
26 28
 LOG = logging.getLogger(__name__)
27 29
 
@@ -66,7 +68,7 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):
66 68
                 if host.get('manage_vlans', True):
67 69
                     # Create VLAN on the switch
68 70
                     try:
69
-                        self.ansnet.create_network(host_name, segmentation_id)
71
+                        self.ansnet.create_vlan(host_name, segmentation_id)
70 72
                         LOG.info('Network {net_id} has been added on ansible '
71 73
                                  'host {host}'.format(
72 74
                                      net_id=network['id'],
@@ -109,7 +111,7 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):
109 111
                 if host.get('manage_vlans', True):
110 112
                     # Delete VLAN on the switch
111 113
                     try:
112
-                        self.ansnet.delete_network(host_name, segmentation_id)
114
+                        self.ansnet.delete_vlan(host_name, segmentation_id)
113 115
                         LOG.info('Network {net_id} has been deleted on '
114 116
                                  'ansible host {host}'.format(
115 117
                                      net_id=network['id'],
@@ -121,6 +123,7 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):
121 123
                                   'reason: {err}'.format(net_id=network['id'],
122 124
                                                          host=host_name,
123 125
                                                          err=e))
126
+                        raise ml2_exc.MechanismDriverError(e)
124 127
 
125 128
     def update_port_postcommit(self, context):
126 129
         """Update a port.
@@ -137,16 +140,45 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):
137 140
         state. It is up to the mechanism driver to ignore state or
138 141
         state changes that it does not know or care about.
139 142
         """
140
-        port = context.network.current
143
+        # Validate current locallink info
144
+        # Raises a LocalLink error if invalid
145
+        self._link_info_from_port(context.current)
146
+
141 147
         if self._is_port_bound(context.current):
148
+            port = context.current
142 149
             provisioning_blocks.provisioning_complete(
143 150
                 context._plugin_context, port['id'], resources.PORT,
144 151
                 ANSIBLE_NETWORKING_ENTITY)
145 152
         elif self._is_port_bound(context.original):
153
+            port = context.original
154
+            network = context.network.current
155
+            switch_name, switch_port, segmentation_id = \
156
+                self._link_info_from_port(context.original, network)
157
+
158
+            LOG.debug('Unplugging port {switch_port} on '
159
+                      '{switch_name} from vlan: {segmentation_id}'.format(
160
+                          switch_port=switch_port,
161
+                          switch_name=switch_name,
162
+                          segmentation_id=segmentation_id))
146 163
             # The port has been unbound. This will cause the local link
147 164
             # information to be lost, so remove the port from the network on
148 165
             # the switch now while we have the required information.
149
-            self.ansnet.vlan_access_port('remove', context.original, port)
166
+            try:
167
+                self.ansnet.delete_port(switch_name, switch_port)
168
+                LOG.info('Port {neutron_port} has been unplugged from '
169
+                         'network {net_id} on device {switch_name}'.format(
170
+                             neutron_port=port['id'],
171
+                             net_id=network['id'],
172
+                             switch_name=switch_name))
173
+            except Exception as e:
174
+                LOG.error('Failed to unplug port {neutron_port} on '
175
+                          'device: {switch_name} from network {net_id} '
176
+                          'reason: {exc}'.format(
177
+                              neutron_port=port['id'],
178
+                              net_id=network['id'],
179
+                              switch_name=switch_name,
180
+                              exc=e))
181
+                raise ml2_exc.MechanismDriverError(e)
150 182
 
151 183
     def delete_port_postcommit(self, context):
152 184
         """Delete a port.
@@ -160,10 +192,32 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):
160 192
         expected, and will not prevent the resource from being
161 193
         deleted.
162 194
         """
195
+        port = context.current
196
+        network = context.network.current
163 197
         if self._is_port_bound(context.current):
164
-            self.ansnet.vlan_access_port('remove',
165
-                                         context.current,
166
-                                         context.network.current)
198
+            switch_name, switch_port, segmentation_id = \
199
+                self._link_info_from_port(port, network)
200
+            LOG.debug('Unplugging port {switch_port} on '
201
+                      '{switch_name} from vlan: {segmentation_id}'.format(
202
+                          switch_port=switch_port,
203
+                          switch_name=switch_name,
204
+                          segmentation_id=segmentation_id))
205
+            try:
206
+                self.ansnet.delete_port(switch_name, switch_port)
207
+                LOG.info('Port {neutron_port} has been unplugged from '
208
+                         'network {net_id} on device {switch_name}'.format(
209
+                             neutron_port=port['id'],
210
+                             net_id=network['id'],
211
+                             switch_name=switch_name))
212
+            except Exception as e:
213
+                LOG.error('Failed to unplug port {neutron_port} on '
214
+                          'device: {switch_name} from network {net_id} '
215
+                          'reason: {exc}'.format(
216
+                              neutron_port=port['id'],
217
+                              net_id=network['id'],
218
+                              switch_name=switch_name,
219
+                              exc=e))
220
+                raise ml2_exc.MechanismDriverError(e)
167 221
 
168 222
     def bind_port(self, context):
169 223
         """Attempt to bind a port.
@@ -207,29 +261,63 @@ class AnsibleMechanismDriver(ml2api.MechanismDriver):
207 261
         can use with ports.
208 262
         """
209 263
         port = context.current
210
-        # Validate port and local link info
211
-        if 'local_link_information' not in port['binding:profile']:
212
-            LOG.debug(
213
-                "local_link_information is missing in port binding:profile")
214
-            return
264
+        network = context.network.current
265
+        switch_name, switch_port, segmentation_id = \
266
+            self._link_info_from_port(port, network)
215 267
         if not self._is_port_supported(port):
216
-            LOG.debug(
217
-                "Port %s has vnic_type set to %s which is not correct to work "
218
-                "with networking-ansible driver.", port['id'],
219
-                port[portbindings.VNIC_TYPE])
268
+            LOG.debug('Port {} has vnic_type set to %s which is not correct '
269
+                      'to work with networking-ansible driver.'.format(
270
+                          port['id'],
271
+                          port[portbindings.VNIC_TYPE]))
220 272
             return
221 273
 
222 274
         segments = context.segments_to_bind
223 275
 
276
+        LOG.debug('Plugging in port {switch_port} on '
277
+                  '{switch_name} to vlan: {segmentation_id}'.format(
278
+                      switch_port=switch_port,
279
+                      switch_name=switch_name,
280
+                      segmentation_id=segmentation_id))
281
+
224 282
         provisioning_blocks.add_provisioning_component(
225 283
             context._plugin_context, port['id'], resources.PORT,
226 284
             ANSIBLE_NETWORKING_ENTITY)
227 285
 
228 286
         # Assign port to network
229
-        self.ansnet.vlan_access_port('assign', context.current,
230
-                                     context.network.current)
231
-        context.set_binding(segments[0][ml2api.ID],
232
-                            portbindings.VIF_TYPE_OTHER, {})
287
+        try:
288
+            self.ansnet.update_access_port(switch_name,
289
+                                           switch_port,
290
+                                           segmentation_id)
291
+            context.set_binding(segments[0][ml2api.ID],
292
+                                portbindings.VIF_TYPE_OTHER, {})
293
+            LOG.info('Port {neutron_port} has been plugged into '
294
+                     'network {net_id} on device {switch_name}'.format(
295
+                         neutron_port=port['id'],
296
+                         net_id=network['id'],
297
+                         switch_name=switch_name))
298
+        except Exception as e:
299
+            LOG.error('Failed to plug in port {neutron_port} on '
300
+                      'device: {switch_name} from network {net_id} '
301
+                      'reason: {exc}'.format(
302
+                          neutron_port=port['id'],
303
+                          net_id=network['id'],
304
+                          switch_name=switch_name,
305
+                          exc=e))
306
+            raise ml2_exc.MechanismDriverError(e)
307
+
308
+    def _link_info_from_port(self, port, network=None):
309
+        network = network or {}
310
+        # Validate port and local link info
311
+        local_link_info = port['binding:profile'].get('local_link_information')
312
+        if not local_link_info:
313
+            msg = 'local_link_information is missing in port {port_id} ' \
314
+                  'binding:profile'.format(port_id=port['id'])
315
+            LOG.debug(msg)
316
+            raise exceptions.LocalLinkInfoMissingException(msg)
317
+        switch_name = local_link_info[0].get('switch_info')
318
+        switch_port = local_link_info[0].get('port_id')
319
+        segmentation_id = network.get('provider:segmentation_id', '')
320
+        return switch_name, switch_port, segmentation_id
233 321
 
234 322
     @staticmethod
235 323
     def _is_port_supported(port):

+ 56
- 33
networking_ansible/tests/unit/ml2/test_mech_driver.py View File

@@ -27,6 +27,7 @@ import webob.exc
27 27
 
28 28
 from networking_ansible import api
29 29
 from networking_ansible import exceptions
30
+from networking_ansible.ml2 import exceptions as netans_ml2exc
30 31
 from networking_ansible.tests.unit import base
31 32
 
32 33
 
@@ -49,32 +50,34 @@ class NetAnsibleML2Base(test_plugin.Ml2PluginV2TestCase):
49 50
         super(NetAnsibleML2Base, self).setUp()
50 51
 
51 52
 
52
-@mock.patch.object(api.NetworkingAnsible, 'vlan_access_port')
53
+@mock.patch.object(api.NetworkingAnsible, 'update_access_port')
53 54
 @mock.patch('networking_ansible.ml2.mech_driver.provisioning_blocks',
54 55
             autospec=True)
55 56
 class TestBindPort(base.NetworkingAnsibleTestCase):
56
-    def test_bind_port(self, mock_prov_blks, mock_vlan_access_port):
57
+    def test_bind_port(self, mock_prov_blks, mock_update_access_port):
57 58
         self.mech.bind_port(self.mock_port_context)
58
-        mock_vlan_access_port.assert_called_once()
59
+        mock_update_access_port.assert_called_once()
59 60
 
60 61
     @mock.patch('networking_ansible.ml2.mech_driver.'
61 62
                 'AnsibleMechanismDriver._is_port_supported')
62 63
     def test_bind_port_port_not_supported(self,
63
-                                          mock_prov_blks,
64
-                                          mock_vlan_access_port,
65
-                                          mock_port_supported):
64
+                                          mock_port_supported,
65
+                                          mock_update_access_port,
66
+                                          mock_prov_blks):
66 67
         mock_port_supported.return_value = False
67 68
         self.mech.bind_port(self.mock_port_context)
68
-        mock_vlan_access_port.assert_not_called()
69
+        mock_update_access_port.assert_not_called()
69 70
 
70 71
     def test_bind_port_no_local_link_info(self,
71 72
                                           mock_prov_blks,
72
-                                          mock_vlan_access_port):
73
+                                          mock_update_access_port):
73 74
         bind_prof = 'binding:profile'
74 75
         local_link_info = 'local_link_information'
75 76
         del self.mock_port_context.current[bind_prof][local_link_info]
76
-        self.mech.bind_port(self.mock_port_context)
77
-        mock_vlan_access_port.assert_not_called()
77
+        self.assertRaises(netans_ml2exc.LocalLinkInfoMissingException,
78
+                          self.mech.bind_port,
79
+                          self.mock_port_context)
80
+        mock_update_access_port.assert_not_called()
78 81
 
79 82
 
80 83
 class TestIsPortSupported(base.NetworkingAnsibleTestCase):
@@ -106,7 +109,7 @@ class TestIsPortBound(base.NetworkingAnsibleTestCase):
106 109
             self.mech._is_port_bound(self.mock_port_context.current))
107 110
 
108 111
 
109
-@mock.patch.object(api.NetworkingAnsible, 'create_network')
112
+@mock.patch.object(api.NetworkingAnsible, 'create_vlan')
110 113
 class TestCreateNetworkPostCommit(base.NetworkingAnsibleTestCase):
111 114
     def test_create_network_postcommit(self, mock_create_network):
112 115
         self.mech.create_network_postcommit(self.mock_net_context)
@@ -137,7 +140,7 @@ class TestCreateNetworkPostCommit(base.NetworkingAnsibleTestCase):
137 140
         mock_create_netwrk.assert_not_called()
138 141
 
139 142
 
140
-@mock.patch.object(api.NetworkingAnsible, 'delete_network')
143
+@mock.patch.object(api.NetworkingAnsible, 'delete_vlan')
141 144
 class TestDeleteNetworkPostCommit(base.NetworkingAnsibleTestCase):
142 145
     def test_delete_network_postcommit(self, mock_delete_network):
143 146
         self.mech.delete_network_postcommit(self.mock_net_context)
@@ -151,7 +154,9 @@ class TestDeleteNetworkPostCommit(base.NetworkingAnsibleTestCase):
151 154
 
152 155
     def test_delete_network_postcommit_fails(self, mock_delete_network):
153 156
         mock_delete_network.side_effect = Exception()
154
-        self.mech.delete_network_postcommit(self.mock_net_context)
157
+        self.assertRaises(ml2_exc.MechanismDriverError,
158
+                          self.mech.delete_network_postcommit,
159
+                          self.mock_net_context)
155 160
         mock_delete_network.assert_called_once()
156 161
 
157 162
     def test_delete_network_postcommit_not_vlan(self, mock_delete_network):
@@ -168,23 +173,29 @@ class TestDeleteNetworkPostCommit(base.NetworkingAnsibleTestCase):
168 173
 
169 174
 @mock.patch('networking_ansible.ml2.mech_driver.'
170 175
             'AnsibleMechanismDriver._is_port_bound')
171
-@mock.patch.object(api.NetworkingAnsible, 'vlan_access_port')
176
+@mock.patch.object(api.NetworkingAnsible, 'delete_port')
172 177
 class TestDeletePortPostCommit(base.NetworkingAnsibleTestCase):
173 178
     def test_delete_port_postcommit_current(self,
174
-                                            mock_vlan_access,
179
+                                            mock_delete_port,
175 180
                                             mock_port_bound):
176 181
         self.mech.delete_port_postcommit(self.mock_port_context)
177
-        mock_vlan_access.assert_called_once_with(
178
-            'remove',
179
-            self.mock_port_context.current,
180
-            self.mock_port_context.network.current)
182
+        mock_delete_port.assert_called_once_with(self.testhost, self.testport)
183
+
184
+    def test_delete_port_postcommit_fails(self,
185
+                                          mock_delete_port,
186
+                                          mock_port_bound):
187
+        mock_delete_port.side_effect = Exception()
188
+        self.assertRaises(ml2_exc.MechanismDriverError,
189
+                          self.mech.delete_port_postcommit,
190
+                          self.mock_port_context)
191
+        mock_delete_port.assert_called_once_with(self.testhost, self.testport)
181 192
 
182 193
     def test_delete_port_postcommit_not_bound(self,
183
-                                              mock_vlan_access,
194
+                                              mock_delete_port,
184 195
                                               mock_port_bound):
185 196
         mock_port_bound.return_value = False
186 197
         self.mech.delete_port_postcommit(self.mock_port_context)
187
-        mock_vlan_access.assert_not_called()
198
+        mock_delete_port.assert_not_called()
188 199
 
189 200
 
190 201
 @mock.patch('networking_ansible.config.build_ansible_inventory', autospec=True)
@@ -196,32 +207,43 @@ class TestInit(base.NetworkingAnsibleTestCase):
196 207
 
197 208
 @mock.patch('networking_ansible.ml2.mech_driver.'
198 209
             'AnsibleMechanismDriver._is_port_bound')
199
-@mock.patch.object(api.NetworkingAnsible, 'vlan_access_port')
210
+@mock.patch.object(api.NetworkingAnsible, 'delete_port')
200 211
 @mock.patch('networking_ansible.ml2.mech_driver.provisioning_blocks',
201 212
             autospec=True)
202 213
 class TestUpdatePortPostCommit(base.NetworkingAnsibleTestCase):
203 214
     def test_update_port_postcommit_current(self,
204 215
                                             mock_prov_blks,
205
-                                            mock_vlan_access,
216
+                                            mock_delete_port,
206 217
                                             mock_port_bound):
207 218
         self.mech.update_port_postcommit(self.mock_port_context)
208 219
         mock_prov_blks.provisioning_complete.assert_called_once()
209 220
 
210 221
     def test_update_port_postcommit_original(self,
211 222
                                              mock_prov_blks,
212
-                                             mock_vlan_access,
223
+                                             mock_delete_port,
213 224
                                              mock_port_bound):
214 225
         mock_port_bound.side_effect = [False, True]
215 226
         self.mech.update_port_postcommit(self.mock_port_context)
216
-        mock_vlan_access.assert_called_once()
227
+        mock_delete_port.assert_called_once()
228
+
229
+    def test_update_port_postcommit_original_fails(self,
230
+                                                   mock_prov_blks,
231
+                                                   mock_delete_port,
232
+                                                   mock_port_bound):
233
+        mock_port_bound.side_effect = [False, True]
234
+        mock_delete_port.side_effect = Exception()
235
+        self.assertRaises(ml2_exc.MechanismDriverError,
236
+                          self.mech.update_port_postcommit,
237
+                          self.mock_port_context)
238
+        mock_delete_port.assert_called_once()
217 239
 
218 240
     def test_update_port_postcommit_not_bound(self,
219 241
                                               mock_prov_blks,
220
-                                              mock_vlan_access,
242
+                                              mock_delete_port,
221 243
                                               mock_port_bound):
222 244
         mock_port_bound.side_effect = [False, False]
223 245
         self.mech.update_port_postcommit(self.mock_port_context)
224
-        mock_vlan_access.assert_not_called()
246
+        mock_delete_port.assert_not_called()
225 247
 
226 248
 
227 249
 @mock.patch.object(api.NetworkingAnsible, '_run_task')
@@ -304,7 +326,7 @@ class TestML2PluginIntegration(NetAnsibleML2Base):
304 326
             mock.call(
305 327
                 'create_network',
306 328
                 host,
307
-                int(self.network_spec[provider_net.SEGMENTATION_ID]))
329
+                vlan_id=int(self.network_spec[provider_net.SEGMENTATION_ID]))
308 330
             for host in self.HOSTS if 'manage_vlans=False' not in
309 331
             self.CONFIG_CONTENT['ansible:%s' % host]]
310 332
         self.assertItemsEqual(
@@ -322,7 +344,7 @@ class TestML2PluginIntegration(NetAnsibleML2Base):
322 344
             mock.call(
323 345
                 'delete_network',
324 346
                 host,
325
-                int(self.network_spec[provider_net.SEGMENTATION_ID]))
347
+                vlan_id=int(self.network_spec[provider_net.SEGMENTATION_ID]))
326 348
             for host in self.HOSTS if 'manage_vlans=False' not in
327 349
             self.CONFIG_CONTENT['ansible:%s' % host]]
328 350
         self.assertItemsEqual(
@@ -356,11 +378,12 @@ class TestML2PluginIntegration(NetAnsibleML2Base):
356 378
 
357 379
             port = self.deserialize(
358 380
                 self.fmt, req.get_response(self.api))
381
+
359 382
             m_run_task.called_once_with(
360 383
                 'update_port',
361 384
                 self.HOSTS[0],
362
-                self.network_spec[provider_net.SEGMENTATION_ID],
363
-                self.LOCAL_LINK_INFORMATION[0]['port_id'])
385
+                self.LOCAL_LINK_INFORMATION[0]['port_id'],
386
+                self.network_spec[provider_net.SEGMENTATION_ID])
364 387
             self.assertNotEqual(
365 388
                 portbindings.VIF_TYPE_BINDING_FAILED,
366 389
                 port['port'][portbindings.VIF_TYPE])
@@ -379,8 +402,8 @@ class TestML2PluginIntegration(NetAnsibleML2Base):
379 402
             m_run_task.called_once_with(
380 403
                 'delete_port',
381 404
                 self.HOSTS[0],
382
-                self.network_spec[provider_net.SEGMENTATION_ID],
383
-                self.LOCAL_LINK_INFORMATION[0]['port_id'])
405
+                self.LOCAL_LINK_INFORMATION[0]['port_id'],
406
+                self.network_spec[provider_net.SEGMENTATION_ID])
384 407
 
385 408
     def test_update_port_error(self, m_run_task):
386 409
         with self._create_unbound_port() as p:

+ 19
- 33
networking_ansible/tests/unit/test_api.py View File

@@ -24,18 +24,18 @@ class TestCreateDeleteNetwork(base.NetworkingAnsibleTestCase):
24 24
     @mock.patch('networking_ansible.api'
25 25
                 '.NetworkingAnsible._run_task')
26 26
     def test_create_network(self, mock_run_task):
27
-        self.mech.ansnet.create_network(self.testhost, self.testsegid)
27
+        self.mech.ansnet.create_vlan(self.testhost, self.testsegid)
28 28
         mock_run_task.assert_called_once_with('create_network',
29 29
                                               self.testhost,
30
-                                              self.testsegid)
30
+                                              vlan_id=self.testsegid)
31 31
 
32 32
     @mock.patch('networking_ansible.api'
33 33
                 '.NetworkingAnsible._run_task')
34 34
     def test_delete_network(self, mock_run_task):
35
-        self.mech.ansnet.delete_network(self.testhost, self.testsegid)
35
+        self.mech.ansnet.delete_vlan(self.testhost, self.testsegid)
36 36
         mock_run_task.assert_called_once_with('delete_network',
37 37
                                               self.testhost,
38
-                                              self.testsegid)
38
+                                              vlan_id=self.testsegid)
39 39
 
40 40
 
41 41
 @mock.patch('networking_ansible.api.ansible_runner')
@@ -45,8 +45,7 @@ class TestRunTask(base.NetworkingAnsibleTestCase):
45 45
         mock_result.stats = {'failures': []}
46 46
 
47 47
         self.mech.ansnet._run_task('fake_task',
48
-                                   self.testhost,
49
-                                   self.testsegid)
48
+                                   self.testhost)
50 49
         # Assert switch_port is not set
51 50
         self.assertNotIn('port_name',
52 51
                          mock_ans_runner.run.call_args[1]['playbook'][0]
@@ -64,16 +63,16 @@ class TestRunTask(base.NetworkingAnsibleTestCase):
64 63
 
65 64
         self.mech.ansnet._run_task('fake_task',
66 65
                                    self.testhost,
67
-                                   self.testsegid,
68
-                                   'fake_switchport')
66
+                                   self.testport,
67
+                                   self.testsegid)
69 68
         # Assert switch_port is set
70 69
         self.assertEqual(
71
-            'fake_switchport',
70
+            self.testport,
72 71
             mock_ans_runner.run.call_args[1]['playbook'][0]['tasks']
73 72
                                          [0]['vars']['port_name'])
74 73
         # Assert switch_port is set
75 74
         self.assertEqual(
76
-            'fake_switchport',
75
+            self.testport,
77 76
             mock_ans_runner.run.call_args[1]['playbook'][0]['tasks']
78 77
                                          [0]['vars']['port_description'])
79 78
 
@@ -93,8 +92,8 @@ class TestRunTask(base.NetworkingAnsibleTestCase):
93 92
                           self.mech.ansnet._run_task,
94 93
                           'fake_task',
95 94
                           self.testhost,
96
-                          self.testsegid,
97
-                          'fake_switchport')
95
+                          'fake_switchport',
96
+                          self.testsegid)
98 97
 
99 98
 
100 99
 @mock.patch('networking_ansible.api'
@@ -102,35 +101,22 @@ class TestRunTask(base.NetworkingAnsibleTestCase):
102 101
 class TestVlanAccessPort(base.NetworkingAnsibleTestCase):
103 102
 
104 103
     def test_assign_vlan_access_port(self, mock_run_task):
105
-        self.mech.ansnet.vlan_access_port('assign',
106
-                                          self.mock_port_context.current,
107
-                                          self.mock_net_context.current)
104
+        self.mech.ansnet.update_access_port(self.testhost,
105
+                                            self.testport,
106
+                                            self.testsegid)
108 107
         mock_run_task.assert_called_once_with('update_port',
109 108
                                               self.testhost,
110
-                                              self.testsegid,
111
-                                              self.testport)
109
+                                              self.testport,
110
+                                              self.testsegid)
112 111
 
113 112
     def test_remove_vlan_access_port(self, mock_run_task):
114
-        self.mech.ansnet.vlan_access_port('remove',
115
-                                          self.mock_port_context.current,
116
-                                          self.mock_net_context.current)
113
+        self.mech.ansnet.delete_port(self.testhost, self.testport)
117 114
         mock_run_task.assert_called_once_with('delete_port',
118 115
                                               self.testhost,
119
-                                              self.testsegid,
120 116
                                               self.testport)
121 117
 
122
-    def test_remove_vlan_access_port_wo_link_local(self, mock_run_task):
123
-        port = self.mock_port_context.current
124
-        del port['binding:profile']['local_link_information']
125
-        self.mech.ansnet.vlan_access_port('remove',
126
-                                          self.mock_port_context.current,
127
-                                          self.mock_net_context.current)
128
-        mock_run_task.assert_not_called()
129
-
130 118
     def test_remove_vlan_access_port_raises(self, mock_run_task):
131 119
         mock_run_task.side_effect = exceptions.AnsibleRunnerException('test')
132 120
         self.assertRaises(exceptions.AnsibleRunnerException,
133
-                          self.mech.ansnet.vlan_access_port,
134
-                          'remove',
135
-                          self.mock_port_context.current,
136
-                          self.mock_net_context.current)
121
+                          self.mech.ansnet.delete_port,
122
+                          self.testhost, self.testport)

Loading…
Cancel
Save