예제 #1
0
    def sync_from_callback(self, context, operation, res_type,
                           res_id, resource_dict, **kwrags):
        object_type = odl_utils.neutronify(res_type.plural)
        try:
            if operation == odl_const.ODL_DELETE:
                self.out_of_sync |= not self.client.try_delete(
                    object_type + '/' + res_id)
            else:
                if operation == odl_const.ODL_CREATE:
                    urlpath = object_type
                    method = 'post'
                elif operation == odl_const.ODL_UPDATE:
                    urlpath = object_type + '/' + res_id
                    method = 'put'
                self.client.sendjson(method, urlpath, resource_dict)
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.error("Unable to perform %(operation)s on "
                          "%(object_type)s %(res_id)s %(resource_dict)s",
                          {'operation': operation,
                           'object_type': object_type,
                           'res_id': res_id,
                           'resource_dict': resource_dict})
                self.out_of_sync = True

        # NOTE(yamahata) when security group is created, default rules
        # are also created.
        if (operation == odl_const.ODL_CREATE and
                res_type.singular == odl_const.ODL_SG):
            for rule in resource_dict[odl_const.ODL_SG][
                    odl_const.ODL_SG_RULES]:
                self.sync_from_callback(
                    context, odl_const.ODL_CREATE,
                    odl_call._RESOURCE_MAPPING[resources.SECURITY_GROUP_RULE],
                    rule['id'], {odl_const.ODL_SG_RULE: rule})
    def sync_resources(self, plugin, dbcontext, collection_name):
        """Sync objects from Neutron over to OpenDaylight.

        This will handle syncing networks, subnets, and ports from Neutron to
        OpenDaylight. It also filters out the requisite items which are not
        valid for create API operations.
        """
        filter_cls = self.FILTER_MAP[collection_name]
        to_be_synced = []
        obj_getter = getattr(plugin, 'get_%s' % collection_name)
        if collection_name == odl_const.ODL_SGS:
            resources = obj_getter(dbcontext, default_sg=True)
        else:
            resources = obj_getter(dbcontext)
        for resource in resources:
            try:
                # Convert underscores to dashes in the URL for ODL
                collection_name_url = odl_utils.neutronify(collection_name)
                urlpath = collection_name_url + '/' + resource['id']
                self.client.sendjson('get', urlpath, None)
            except requests.exceptions.HTTPError as e:
                with excutils.save_and_reraise_exception() as ctx:
                    if e.response.status_code == requests.codes.not_found:
                        filter_cls.filter_create_attributes_with_plugin(
                            resource, plugin, dbcontext)
                        to_be_synced.append(resource)
                        ctx.reraise = False
                    else:
                        # sync failed, indicate DB sync failure.
                        # If other failures were raised by self.client.json,
                        # then they would be alarmed first
                        self.client.set_audit_failure('dbsync_failure')
            else:
                # TODO(yamahata): compare result with resource.
                # If they don't match, update it below
                pass

        if to_be_synced:
            key = collection_name[:-1] if len(to_be_synced) == 1 else (
                collection_name)
            # Convert underscores to dashes in the URL for ODL
            collection_name_url = odl_utils.neutronify(collection_name)
            self.client.sendjson('post', collection_name_url,
                                 {key: to_be_synced})
    def _test_thread_processing(self,
                                operation,
                                object_type,
                                expected_calls=1):
        http_requests = {
            odl_const.ODL_CREATE: 'post',
            odl_const.ODL_UPDATE: 'put',
            odl_const.ODL_DELETE: 'delete'
        }
        status_codes = {
            odl_const.ODL_CREATE: requests.codes.created,
            odl_const.ODL_UPDATE: requests.codes.ok,
            odl_const.ODL_DELETE: requests.codes.no_content
        }

        http_request = http_requests[operation]
        status_code = status_codes[operation]

        self._call_operation_object(operation, object_type)

        context = self._get_mock_operation_context(object_type)
        url_object_type = utils.neutronify(object_type)
        if operation in [odl_const.ODL_UPDATE, odl_const.ODL_DELETE]:
            if object_type in [odl_const.ODL_SG, odl_const.ODL_SG_RULE]:
                uuid = context[object_type]['id']
            else:
                uuid = context.current['id']
            url = '%s/%ss/%s' % (cfg.CONF.ml2_odl.url, url_object_type, uuid)
        else:
            url = '%s/%ss' % (cfg.CONF.ml2_odl.url, url_object_type)

        if (object_type == odl_const.ODL_SG
                and operation == odl_const.ODL_CREATE):
            context = copy.deepcopy(context)
            context[odl_const.ODL_SG].pop('rules')
        if operation in [odl_const.ODL_CREATE, odl_const.ODL_UPDATE]:
            kwargs = {
                'url': url,
                'data': DataMatcher(operation, object_type, context)
            }
        else:
            kwargs = {'url': url, 'data': None}
        with mock.patch.object(self.thread.event, 'wait', return_value=False):
            self._test_operation(self.thread.run_sync_thread, status_code,
                                 expected_calls, http_request, **kwargs)
    def sync_single_resource(self, operation, object_type, context):
        """Sync over a single resource from Neutron to OpenDaylight.

        Handle syncing a single operation over to OpenDaylight, and correctly
        filter attributes out which are not required for the requisite
        operation (create or update) being handled.
        """
        # Convert underscores to dashes in the URL for ODL
        object_type_url = odl_utils.neutronify(object_type)
        try:
            obj_id = context.current['id']
            if operation == odl_const.ODL_DELETE:
                self.out_of_sync |= not self.client.try_delete(
                    object_type_url + '/' + obj_id)
            else:
                filter_cls = self.FILTER_MAP[object_type]
                if operation == odl_const.ODL_CREATE:
                    urlpath = object_type_url
                    method = 'post'
                    attr_filter = filter_cls.filter_create_attributes
                elif operation == odl_const.ODL_UPDATE:
                    urlpath = object_type_url + '/' + obj_id
                    method = 'put'
                    attr_filter = filter_cls.filter_update_attributes
                resource = copy.deepcopy(context.current)
                attr_filter(resource, context)
                self.client.sendjson(method, urlpath,
                                     {object_type_url[:-1]: resource})
        except Exception:
            with excutils.save_and_reraise_exception():
                LOG.error(
                    "Unable to perform %(operation)s on "
                    "%(object_type)s %(object_id)s", {
                        'operation': operation,
                        'object_type': object_type,
                        'object_id': obj_id
                    })
                self.out_of_sync = True
                # sync failed, indicate DB sync failure.
                # If other failures were raised by self.client.json,
                # then they would be alarmed first
                self.client.set_audit_failure('dbsync_failure')
예제 #5
0
    def send_resource(self, operation, object_type, data):
        """Send over a single resource from Neutron to OpenDaylight.

        Prepare a rest call and send a single resource to ODL NB
        """
        # Convert underscores to dashes in the URL for ODL
        object_type_url = utils.neutronify(object_type)
        obj_id = data['id']
        if operation == odl_const.ODL_DELETE:
            self.client.try_delete(object_type_url + '/' + obj_id)
        else:
            if operation == odl_const.ODL_CREATE:
                urlpath = object_type_url
                method = 'post'
            elif operation == odl_const.ODL_UPDATE:
                urlpath = object_type_url + '/' + obj_id
                method = 'put'
            policy_data = qos_utils.convert_rules_format(data)
            self.client.sendjson(method, urlpath,
                                 {odl_const.ODL_QOS_POLICY: policy_data})
    def _test_thread_processing(self, operation, object_type,
                                expected_calls=1):
        http_requests = {odl_const.ODL_CREATE: 'post',
                         odl_const.ODL_UPDATE: 'put',
                         odl_const.ODL_DELETE: 'delete'}
        status_codes = {odl_const.ODL_CREATE: requests.codes.created,
                        odl_const.ODL_UPDATE: requests.codes.ok,
                        odl_const.ODL_DELETE: requests.codes.no_content}

        http_request = http_requests[operation]
        status_code = status_codes[operation]

        self._call_operation_object(operation, object_type)

        context = self._get_mock_operation_context(object_type)
        url_object_type = utils.neutronify(object_type)
        if operation in [odl_const.ODL_UPDATE, odl_const.ODL_DELETE]:
            if object_type in [odl_const.ODL_SG, odl_const.ODL_SG_RULE]:
                uuid = context[object_type]['id']
            else:
                uuid = context.current['id']
            url = '%s/%ss/%s' % (cfg.CONF.ml2_odl.url, url_object_type, uuid)
        else:
            url = '%s/%ss' % (cfg.CONF.ml2_odl.url, url_object_type)

        if (object_type == odl_const.ODL_SG and
                operation == odl_const.ODL_CREATE):
            context = copy.deepcopy(context)
        if operation in [odl_const.ODL_CREATE, odl_const.ODL_UPDATE]:
            kwargs = {
                'url': url,
                'data': DataMatcher(operation, object_type, context)}
        else:
            kwargs = {'url': url, 'data': None}

        self._test_operation(status_code, expected_calls, http_request,
                             **kwargs)
 def test_neutronify_empty(self):
     self.assertEqual('', utils.neutronify(''))
 def test_neutronify(self):
     self.assertEqual('a-b-c', utils.neutronify('a_b_c'))
예제 #9
0
 def test_neutronify_empty(self):
     self.assertEqual('', utils.neutronify(''))
예제 #10
0
 def test_neutronify(self):
     self.assertEqual('a-b-c', utils.neutronify('a_b_c'))