~ubuntu-branches/ubuntu/utopic/neutron/utopic-updates

« back to all changes in this revision

Viewing changes to neutron/tests/unit/ml2/test_mechanism_odl.py

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-10-03 18:45:23 UTC
  • mfrom: (1.1.15)
  • Revision ID: package-import@ubuntu.com-20141003184523-4mt6dy1q3j8n30c9
Tags: 1:2014.2~rc1-0ubuntu1
* New upstream release candidate:
  - d/p/*: Refreshed.
  - d/control: Add python-requests-mock to BD's.
  - d/control: Align versioned requirements with upstream.
* Transition linuxbridge and openvswitch plugin users to modular
  layer 2 plugin (LP: #1323729):
  - d/control: Mark removed plugin packages as transitional, depend
    on neutron-plugin-ml2, mark oldlibs/extra.
  - d/neutron-plugin-{linuxbridge,openvswitch}.install: Drop.
  - d/control: Depend on neutron-plugin-ml2 for linuxbridge
    agent package.
  - d/neutron-plugin-linuxbridge-agent.upstart: Use ml2 plugin
    configuration files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
13
#    License for the specific language governing permissions and limitations
14
14
#    under the License.
15
 
# @author: Kyle Mestery, Cisco Systems, Inc.
16
15
 
17
16
import mock
18
17
import requests
19
18
 
 
19
from neutron.openstack.common import jsonutils
20
20
from neutron.plugins.common import constants
21
21
from neutron.plugins.ml2 import config as config
22
22
from neutron.plugins.ml2 import driver_api as api
122
122
 
123
123
 
124
124
class AuthMatcher(object):
 
125
 
125
126
    def __eq__(self, obj):
126
127
        return (obj.username == config.cfg.CONF.ml2_odl.username and
127
128
                obj.password == config.cfg.CONF.ml2_odl.password)
128
129
 
129
130
 
 
131
class DataMatcher(object):
 
132
 
 
133
    def __init__(self, operation, object_type, context):
 
134
        self._data = context.current.copy()
 
135
        self._object_type = object_type
 
136
        filter_map = getattr(mechanism_odl.OpenDaylightMechanismDriver,
 
137
                             '%s_object_map' % operation)
 
138
        attr_filter = filter_map["%ss" % object_type]
 
139
        attr_filter(self._data, context)
 
140
 
 
141
    def __eq__(self, s):
 
142
        data = jsonutils.loads(s)
 
143
        return self._data == data[self._object_type]
 
144
 
 
145
 
130
146
class OpenDaylightMechanismDriverTestCase(base.BaseTestCase):
131
147
 
132
148
    def setUp(self):
140
156
        self.mech.initialize()
141
157
 
142
158
    @staticmethod
143
 
    def _get_mock_delete_resource_context():
144
 
        current = {'id': '00000000-1111-2222-3333-444444444444'}
145
 
        context = mock.Mock(current=current)
146
 
        return context
 
159
    def _get_mock_network_operation_context():
 
160
        current = {'status': 'ACTIVE',
 
161
                   'subnets': [],
 
162
                   'name': 'net1',
 
163
                   'provider:physical_network': None,
 
164
                   'admin_state_up': True,
 
165
                   'tenant_id': 'test-tenant',
 
166
                   'provider:network_type': 'local',
 
167
                   'router:external': False,
 
168
                   'shared': False,
 
169
                   'id': 'd897e21a-dfd6-4331-a5dd-7524fa421c3e',
 
170
                   'provider:segmentation_id': None}
 
171
        context = mock.Mock(current=current)
 
172
        return context
 
173
 
 
174
    @staticmethod
 
175
    def _get_mock_subnet_operation_context():
 
176
        current = {'ipv6_ra_mode': None,
 
177
                   'allocation_pools': [{'start': '10.0.0.2',
 
178
                                         'end': '10.0.1.254'}],
 
179
                   'host_routes': [],
 
180
                   'ipv6_address_mode': None,
 
181
                   'cidr': '10.0.0.0/23',
 
182
                   'id': '72c56c48-e9b8-4dcf-b3a7-0813bb3bd839',
 
183
                   'name': '',
 
184
                   'enable_dhcp': True,
 
185
                   'network_id': 'd897e21a-dfd6-4331-a5dd-7524fa421c3e',
 
186
                   'tenant_id': 'test-tenant',
 
187
                   'dns_nameservers': [],
 
188
                   'gateway_ip': '10.0.0.1',
 
189
                   'ip_version': 4,
 
190
                   'shared': False}
 
191
        context = mock.Mock(current=current)
 
192
        return context
 
193
 
 
194
    @staticmethod
 
195
    def _get_mock_port_operation_context():
 
196
        current = {'status': 'DOWN',
 
197
                   'binding:host_id': '',
 
198
                   'allowed_address_pairs': [],
 
199
                   'device_owner': 'fake_owner',
 
200
                   'binding:profile': {},
 
201
                   'fixed_ips': [],
 
202
                   'id': '72c56c48-e9b8-4dcf-b3a7-0813bb3bd839',
 
203
                   'security_groups': ['2f9244b4-9bee-4e81-bc4a-3f3c2045b3d7'],
 
204
                   'device_id': 'fake_device',
 
205
                   'name': '',
 
206
                   'admin_state_up': True,
 
207
                   'network_id': 'c13bba05-eb07-45ba-ace2-765706b2d701',
 
208
                   'tenant_id': 'bad_tenant_id',
 
209
                   'binding:vif_details': {},
 
210
                   'binding:vnic_type': 'normal',
 
211
                   'binding:vif_type': 'unbound',
 
212
                   'mac_address': '12:34:56:78:21:b6'}
 
213
        context = mock.Mock(current=current)
 
214
        context._plugin.get_security_group = mock.Mock(return_value={})
 
215
        return context
 
216
 
 
217
    @classmethod
 
218
    def _get_mock_operation_context(cls, object_type):
 
219
        getter = getattr(cls, '_get_mock_%s_operation_context' % object_type)
 
220
        return getter()
147
221
 
148
222
    _status_code_msgs = {
 
223
        200: '',
 
224
        201: '',
149
225
        204: '',
 
226
        400: '400 Client Error: Bad Request',
150
227
        401: '401 Client Error: Unauthorized',
151
228
        403: '403 Client Error: Forbidden',
152
229
        404: '404 Client Error: Not Found',
153
230
        409: '409 Client Error: Conflict',
154
 
        501: '501 Server Error: Not Implemented'
 
231
        501: '501 Server Error: Not Implemented',
 
232
        503: '503 Server Error: Service Unavailable',
155
233
    }
156
234
 
157
235
    @classmethod
162
240
                cls._status_code_msgs[status_code])))
163
241
        return response
164
242
 
165
 
    def _test_delete_resource_postcommit(self, object_type, status_code,
166
 
                                         exc_class=None):
 
243
    def _test_single_operation(self, method, context, status_code,
 
244
                               exc_class=None, *args, **kwargs):
167
245
        self.mech.out_of_sync = False
168
 
        method = getattr(self.mech, 'delete_%s_postcommit' % object_type)
169
 
        context = self._get_mock_delete_resource_context()
170
246
        request_response = self._get_mock_request_response(status_code)
171
247
        with mock.patch('requests.request',
172
248
                        return_value=request_response) as mock_method:
174
250
                self.assertRaises(exc_class, method, context)
175
251
            else:
176
252
                method(context)
177
 
        url = '%s/%ss/%s' % (config.cfg.CONF.ml2_odl.url, object_type,
178
 
                             context.current['id'])
179
253
        mock_method.assert_called_once_with(
180
 
            'delete', url=url, headers={'Content-Type': 'application/json'},
181
 
            data=None, auth=AuthMatcher(),
182
 
            timeout=config.cfg.CONF.ml2_odl.timeout)
 
254
            headers={'Content-Type': 'application/json'}, auth=AuthMatcher(),
 
255
            timeout=config.cfg.CONF.ml2_odl.timeout, *args, **kwargs)
 
256
 
 
257
    def _test_create_resource_postcommit(self, object_type, status_code,
 
258
                                         exc_class=None):
 
259
        method = getattr(self.mech, 'create_%s_postcommit' % object_type)
 
260
        context = self._get_mock_operation_context(object_type)
 
261
        url = '%s/%ss' % (config.cfg.CONF.ml2_odl.url, object_type)
 
262
        kwargs = {'url': url,
 
263
                  'data': DataMatcher('create', object_type, context)}
 
264
        self._test_single_operation(method, context, status_code, exc_class,
 
265
                                    'post', **kwargs)
 
266
 
 
267
    def _test_update_resource_postcommit(self, object_type, status_code,
 
268
                                         exc_class=None):
 
269
        method = getattr(self.mech, 'update_%s_postcommit' % object_type)
 
270
        context = self._get_mock_operation_context(object_type)
 
271
        url = '%s/%ss/%s' % (config.cfg.CONF.ml2_odl.url, object_type,
 
272
                             context.current['id'])
 
273
        kwargs = {'url': url,
 
274
                  'data': DataMatcher('update', object_type, context)}
 
275
        self._test_single_operation(method, context, status_code, exc_class,
 
276
                                    'put', **kwargs)
 
277
 
 
278
    def _test_delete_resource_postcommit(self, object_type, status_code,
 
279
                                         exc_class=None):
 
280
        method = getattr(self.mech, 'delete_%s_postcommit' % object_type)
 
281
        context = self._get_mock_operation_context(object_type)
 
282
        url = '%s/%ss/%s' % (config.cfg.CONF.ml2_odl.url, object_type,
 
283
                             context.current['id'])
 
284
        kwargs = {'url': url, 'data': None}
 
285
        self._test_single_operation(method, context, status_code, exc_class,
 
286
                                    'delete', **kwargs)
 
287
 
 
288
    def test_create_network_postcommit(self):
 
289
        for status_code in (requests.codes.created,
 
290
                            requests.codes.bad_request):
 
291
            self._test_create_resource_postcommit('network', status_code)
 
292
        self._test_create_resource_postcommit(
 
293
            'network', requests.codes.unauthorized,
 
294
            requests.exceptions.HTTPError)
 
295
 
 
296
    def test_create_subnet_postcommit(self):
 
297
        for status_code in (requests.codes.created,
 
298
                            requests.codes.bad_request):
 
299
            self._test_create_resource_postcommit('subnet', status_code)
 
300
        for status_code in (requests.codes.unauthorized,
 
301
                            requests.codes.forbidden,
 
302
                            requests.codes.not_found,
 
303
                            requests.codes.conflict,
 
304
                            requests.codes.not_implemented):
 
305
            self._test_create_resource_postcommit(
 
306
                'subnet', status_code, requests.exceptions.HTTPError)
 
307
 
 
308
    def test_create_port_postcommit(self):
 
309
        for status_code in (requests.codes.created,
 
310
                            requests.codes.bad_request):
 
311
            self._test_create_resource_postcommit('port', status_code)
 
312
        for status_code in (requests.codes.unauthorized,
 
313
                            requests.codes.forbidden,
 
314
                            requests.codes.not_found,
 
315
                            requests.codes.conflict,
 
316
                            requests.codes.not_implemented,
 
317
                            requests.codes.service_unavailable):
 
318
            self._test_create_resource_postcommit(
 
319
                'port', status_code, requests.exceptions.HTTPError)
 
320
 
 
321
    def test_update_network_postcommit(self):
 
322
        for status_code in (requests.codes.ok,
 
323
                            requests.codes.bad_request):
 
324
            self._test_update_resource_postcommit('network', status_code)
 
325
        for status_code in (requests.codes.forbidden,
 
326
                            requests.codes.not_found):
 
327
            self._test_update_resource_postcommit(
 
328
                'network', status_code, requests.exceptions.HTTPError)
 
329
 
 
330
    def test_update_subnet_postcommit(self):
 
331
        for status_code in (requests.codes.ok,
 
332
                            requests.codes.bad_request):
 
333
            self._test_update_resource_postcommit('subnet', status_code)
 
334
        for status_code in (requests.codes.unauthorized,
 
335
                            requests.codes.forbidden,
 
336
                            requests.codes.not_found,
 
337
                            requests.codes.not_implemented):
 
338
            self._test_update_resource_postcommit(
 
339
                'subnet', status_code, requests.exceptions.HTTPError)
 
340
 
 
341
    def test_update_port_postcommit(self):
 
342
        for status_code in (requests.codes.ok,
 
343
                            requests.codes.bad_request):
 
344
            self._test_update_resource_postcommit('port', status_code)
 
345
        for status_code in (requests.codes.unauthorized,
 
346
                            requests.codes.forbidden,
 
347
                            requests.codes.not_found,
 
348
                            requests.codes.conflict,
 
349
                            requests.codes.not_implemented):
 
350
            self._test_update_resource_postcommit(
 
351
                'port', status_code, requests.exceptions.HTTPError)
183
352
 
184
353
    def test_delete_network_postcommit(self):
185
354
        self._test_delete_resource_postcommit('network',