Пример #1
0
    def sync_address_sets(self, ctx):
        """Sync Address Sets between neutron and NB.

        @param ctx: neutron context
        @type  ctx: object of type neutron.context.Context
        @var   db_ports: List of ports from neutron DB
        """
        LOG.debug('Address-Set-SYNC: started @ %s' % str(datetime.now()))

        neutron_sgs = {}
        with ctx.session.begin(subtransactions=True):
            db_sgs = self.core_plugin.get_security_groups(ctx)
            db_ports = self.core_plugin.get_ports(ctx)

        for sg in db_sgs:
            for ip_version in ['ip4', 'ip6']:
                name = utils.ovn_addrset_name(sg['id'], ip_version)
                neutron_sgs[name] = {
                    'name': name,
                    'addresses': [],
                    'external_ids': {
                        const.OVN_SG_NAME_EXT_ID_KEY: sg['name']
                    }
                }

        for port in db_ports:
            sg_ids = port.get('security_groups', [])
            if port.get('fixed_ips') and sg_ids:
                addresses = acl_utils.acl_port_ips(port)
                for sg_id in sg_ids:
                    for ip_version in addresses:
                        name = utils.ovn_addrset_name(sg_id, ip_version)
                        neutron_sgs[name]['addresses'].extend(
                            addresses[ip_version])

        nb_sgs = self.get_address_sets()

        sgnames_to_add, sgnames_to_delete, sgs_to_update =\
            self.compute_address_set_difference(neutron_sgs, nb_sgs)

        LOG.debug('Address_Sets added %d, removed %d, updated %d',
                  len(sgnames_to_add), len(sgnames_to_delete),
                  len(sgs_to_update))

        if self.mode == SYNC_MODE_REPAIR:
            LOG.debug('Address-Set-SYNC: transaction started @ %s' %
                      str(datetime.now()))
            with self.ovn_api.transaction(check_error=True) as txn:
                for sgname in sgnames_to_add:
                    sg = neutron_sgs[sgname]
                    txn.add(self.ovn_api.create_address_set(**sg))
                for sgname, sg in six.iteritems(sgs_to_update):
                    txn.add(self.ovn_api.update_address_set(**sg))
                for sgname in sgnames_to_delete:
                    txn.add(self.ovn_api.delete_address_set(name=sgname))
            LOG.debug('Address-Set-SYNC: transaction finished @ %s' %
                      str(datetime.now()))
Пример #2
0
    def test__process_sg_notification_delete(self):
        self.mech_driver._process_sg_notification(
            resources.SECURITY_GROUP, events.BEFORE_DELETE, {}, security_group=self.fake_sg
        )
        ip4_name = ovn_utils.ovn_addrset_name(self.fake_sg["id"], "ip4")
        ip6_name = ovn_utils.ovn_addrset_name(self.fake_sg["id"], "ip6")
        delete_address_set_calls = [mock.call(name=name) for name in [ip4_name, ip6_name]]

        self.nb_ovn.delete_address_set.assert_has_calls(delete_address_set_calls, any_order=True)
Пример #3
0
    def test__process_sg_notification_update(self):
        self.mech_driver._process_sg_notification(
            resources.SECURITY_GROUP, events.AFTER_UPDATE, {}, security_group=self.fake_sg
        )
        external_ids = {ovn_const.OVN_SG_NAME_EXT_ID_KEY: self.fake_sg["name"]}
        ip4_name = ovn_utils.ovn_addrset_name(self.fake_sg["id"], "ip4")
        ip6_name = ovn_utils.ovn_addrset_name(self.fake_sg["id"], "ip6")
        update_address_set_calls = [mock.call(name=name, external_ids=external_ids) for name in [ip4_name, ip6_name]]

        self.nb_ovn.update_address_set_ext_ids.assert_has_calls(update_address_set_calls, any_order=True)
Пример #4
0
    def sync_address_sets(self, ctx):
        """Sync Address Sets between neutron and NB.

        @param ctx: neutron context
        @type  ctx: object of type neutron.context.Context
        @var   db_ports: List of ports from neutron DB
        """
        LOG.debug('Address-Set-SYNC: started @ %s' % str(datetime.now()))

        neutron_sgs = {}
        with ctx.session.begin(subtransactions=True):
            db_sgs = self.core_plugin.get_security_groups(ctx)
            db_ports = self.core_plugin.get_ports(ctx)

        for sg in db_sgs:
            for ip_version in ['ip4', 'ip6']:
                name = utils.ovn_addrset_name(sg['id'], ip_version)
                neutron_sgs[name] = {
                    'name': name, 'addresses': [],
                    'external_ids': {const.OVN_SG_NAME_EXT_ID_KEY:
                                     sg['name']}}

        for port in db_ports:
            sg_ids = port.get('security_groups', [])
            if port.get('fixed_ips') and sg_ids:
                addresses = acl_utils.acl_port_ips(port)
                for sg_id in sg_ids:
                    for ip_version in addresses:
                        name = utils.ovn_addrset_name(sg_id, ip_version)
                        neutron_sgs[name]['addresses'].extend(
                            addresses[ip_version])

        nb_sgs = self.get_address_sets()

        sgnames_to_add, sgnames_to_delete, sgs_to_update =\
            self.compute_address_set_difference(neutron_sgs, nb_sgs)

        LOG.debug('Address_Sets added %d, removed %d, updated %d',
                  len(sgnames_to_add), len(sgnames_to_delete),
                  len(sgs_to_update))

        if self.mode == SYNC_MODE_REPAIR:
            LOG.debug('Address-Set-SYNC: transaction started @ %s' %
                      str(datetime.now()))
            with self.ovn_api.transaction(check_error=True) as txn:
                for sgname in sgnames_to_add:
                    sg = neutron_sgs[sgname]
                    txn.add(self.ovn_api.create_address_set(**sg))
                for sgname, sg in six.iteritems(sgs_to_update):
                    txn.add(self.ovn_api.update_address_set(**sg))
                for sgname in sgnames_to_delete:
                    txn.add(self.ovn_api.delete_address_set(name=sgname))
            LOG.debug('Address-Set-SYNC: transaction finished @ %s' %
                      str(datetime.now()))
Пример #5
0
 def _process_sg_notification(self, resource, event, trigger, **kwargs):
     sg = kwargs.get('security_group')
     external_ids = {ovn_const.OVN_SG_NAME_EXT_ID_KEY: sg['name']}
     with self._nb_ovn.transaction(check_error=True) as txn:
         for ip_version in ['ip4', 'ip6']:
             if event == events.AFTER_CREATE:
                 txn.add(self._nb_ovn.create_address_set(
                         name=utils.ovn_addrset_name(sg['id'], ip_version),
                         external_ids=external_ids))
             elif event == events.BEFORE_DELETE:
                 txn.add(self._nb_ovn.delete_address_set(
                         name=utils.ovn_addrset_name(sg['id'], ip_version)))
Пример #6
0
    def test__process_sg_notification_delete(self):
        self.mech_driver._process_sg_notification(resources.SECURITY_GROUP,
                                                  events.BEFORE_DELETE, {},
                                                  security_group=self.fake_sg)
        ip4_name = ovn_utils.ovn_addrset_name(self.fake_sg['id'], 'ip4')
        ip6_name = ovn_utils.ovn_addrset_name(self.fake_sg['id'], 'ip6')
        delete_address_set_calls = [
            mock.call(name=name) for name in [ip4_name, ip6_name]
        ]

        self.nb_ovn.delete_address_set.assert_has_calls(
            delete_address_set_calls, any_order=True)
Пример #7
0
    def test__process_sg_notification_create(self):
        self.mech_driver._process_sg_notification(
            resources.SECURITY_GROUP, events.AFTER_CREATE, {},
            security_group=self.fake_sg)
        external_ids = {ovn_const.OVN_SG_NAME_EXT_ID_KEY: self.fake_sg['name']}
        ip4_name = ovn_utils.ovn_addrset_name(self.fake_sg['id'], 'ip4')
        ip6_name = ovn_utils.ovn_addrset_name(self.fake_sg['id'], 'ip6')
        create_address_set_calls = [mock.call(name=name,
                                              external_ids=external_ids)
                                    for name in [ip4_name, ip6_name]]

        self.nb_ovn.create_address_set.assert_has_calls(
            create_address_set_calls, any_order=True)
Пример #8
0
    def test__process_sg_notification_update(self):
        self.mech_driver._process_sg_notification(resources.SECURITY_GROUP,
                                                  events.AFTER_UPDATE, {},
                                                  security_group=self.fake_sg)
        external_ids = {ovn_const.OVN_SG_NAME_EXT_ID_KEY: self.fake_sg['name']}
        ip4_name = ovn_utils.ovn_addrset_name(self.fake_sg['id'], 'ip4')
        ip6_name = ovn_utils.ovn_addrset_name(self.fake_sg['id'], 'ip6')
        update_address_set_calls = [
            mock.call(name=name, external_ids=external_ids)
            for name in [ip4_name, ip6_name]
        ]

        self.nb_ovn.update_address_set_ext_ids.assert_has_calls(
            update_address_set_calls, any_order=True)
Пример #9
0
    def delete_port_postcommit(self, context):
        """Delete a port.

        :param context: PortContext instance describing the current
        state of the port, prior to the call to delete it.

        Called after the transaction completes. Call can block, though
        will block the entire process so care should be taken to not
        drastically affect performance.  Runtime errors are not
        expected, and will not prevent the resource from being
        deleted.
        """
        port = context.current
        with self._nb_ovn.transaction(check_error=True) as txn:
            txn.add(self._nb_ovn.delete_lswitch_port(port['id'],
                    utils.ovn_name(port['network_id'])))
            txn.add(self._nb_ovn.delete_acl(
                    utils.ovn_name(port['network_id']), port['id']))

            if port.get('fixed_ips'):
                addresses = ovn_acl.acl_port_ips(port)
                for sg_id in port.get('security_groups', []):
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(self._nb_ovn.update_address_set(
                                name=utils.ovn_addrset_name(sg_id, ip_version),
                                addrs_add=None,
                                addrs_remove=addresses[ip_version]))
Пример #10
0
def acl_remote_group_id(r, ip_version):
    if not r["remote_group_id"]:
        return ""

    src_or_dst = "src" if r["direction"] == "ingress" else "dst"
    addrset_name = utils.ovn_addrset_name(r["remote_group_id"], ip_version)
    return " && %s.%s == $%s" % (ip_version, src_or_dst, addrset_name)
Пример #11
0
    def _validate_address_sets(self, should_match=True):
        db_ports = self._list('ports')['ports']
        db_sgs = {}
        for port in db_ports:
            sg_ids = port.get('security_groups', [])
            addresses = acl_utils.acl_port_ips(port)
            for sg_id in sg_ids:
                for ip_version in addresses:
                    name = utils.ovn_addrset_name(sg_id, ip_version)
                    addr_list = db_sgs.setdefault(name, [])
                    addr_list.extend(addresses[ip_version])

        _plugin_nb_ovn = self.mech_driver._nb_ovn
        nb_address_sets = _plugin_nb_ovn.get_address_sets()
        nb_sgs = {}
        for nb_sgid, nb_values in six.iteritems(nb_address_sets):
            nb_sgs[nb_sgid] = nb_values['addresses']
        mn_sgs = {}
        for row in self.monitor_nb_db_idl.tables['Address_Set'].rows.values():
            mn_sgs[getattr(row, 'name')] = getattr(row, 'addresses')

        if should_match:
            self.assertItemsEqual(nb_sgs, db_sgs)
            self.assertItemsEqual(mn_sgs, db_sgs)
        else:
            self.assertRaises(AssertionError, self.assertItemsEqual,
                              nb_sgs, db_sgs)
            self.assertRaises(AssertionError, self.assertItemsEqual,
                              mn_sgs, db_sgs)
Пример #12
0
    def _validate_address_sets(self, should_match=True):
        db_ports = self._list('ports')['ports']
        db_sgs = {}
        for port in db_ports:
            sg_ids = port.get('security_groups', [])
            addresses = acl_utils.acl_port_ips(port)
            for sg_id in sg_ids:
                for ip_version in addresses:
                    name = utils.ovn_addrset_name(sg_id, ip_version)
                    addr_list = db_sgs.setdefault(name, [])
                    addr_list.extend(addresses[ip_version])

        _plugin_nb_ovn = self.mech_driver._nb_ovn
        nb_address_sets = _plugin_nb_ovn.get_address_sets()
        nb_sgs = {}
        for nb_sgid, nb_values in six.iteritems(nb_address_sets):
            nb_sgs[nb_sgid] = nb_values['addresses']
        mn_sgs = {}
        for row in self.monitor_nb_db_idl.tables['Address_Set'].rows.values():
            mn_sgs[getattr(row, 'name')] = getattr(row, 'addresses')

        if should_match:
            self.assertItemsEqual(nb_sgs, db_sgs)
            self.assertItemsEqual(mn_sgs, db_sgs)
        else:
            self.assertRaises(AssertionError, self.assertItemsEqual, nb_sgs,
                              db_sgs)
            self.assertRaises(AssertionError, self.assertItemsEqual, mn_sgs,
                              db_sgs)
Пример #13
0
def acl_remote_group_id(r, ip_version):
    if not r['remote_group_id']:
        return ''

    src_or_dst = 'src' if r['direction'] == 'ingress' else 'dst'
    addrset_name = utils.ovn_addrset_name(r['remote_group_id'], ip_version)
    return ' && %s.%s == $%s' % (ip_version, src_or_dst, addrset_name)
Пример #14
0
 def get_address_set(self, addrset_id, ip_version='ip4'):
     addr_name = utils.ovn_addrset_name(addrset_id, ip_version)
     try:
         return idlutils.row_by_value(self.idl, 'Address_Set',
                                      'name', addr_name)
     except idlutils.RowNotFound:
         return None
Пример #15
0
    def _test_fix_security_group_create(self, mock_bump, revision_number):
        sg_name = utils.ovn_addrset_name('fake_id', 'ip4')
        sg = self._make_security_group(self.fmt, sg_name, '')['security_group']

        db_rev.create_initial_revision(
            sg['id'], constants.TYPE_SECURITY_GROUPS, self.session,
            revision_number=revision_number)
        row = db_rev.get_revision_row(sg['id'])
        self.assertEqual(revision_number, row.revision_number)

        if revision_number < 0:
            self.fake_ovn_client._nb_idl.get_address_set.return_value = None
            self.fake_ovn_client._nb_idl.get_port_group.return_value = None
        else:
            self.fake_ovn_client._nb_idl.get_address_set.return_value = (
                mock.sentinel.AddressSet)

        self.fake_ovn_client._plugin.get_security_group.return_value = sg
        self.periodic._fix_create_update(row)

        if revision_number < 0:
            self.fake_ovn_client.create_security_group.assert_called_once_with(
                sg)
        else:
            # If the object already exist let's make sure we just bump
            # the revision number in the ovn_revision_numbers table
            self.assertFalse(self.fake_ovn_client.create_security_group.called)
            mock_bump.assert_called_once_with(
                sg, constants.TYPE_SECURITY_GROUPS)
Пример #16
0
    def delete_port_postcommit(self, context):
        """Delete a port.

        :param context: PortContext instance describing the current
        state of the port, prior to the call to delete it.

        Called after the transaction completes. Call can block, though
        will block the entire process so care should be taken to not
        drastically affect performance.  Runtime errors are not
        expected, and will not prevent the resource from being
        deleted.
        """
        port = context.current
        with self._nb_ovn.transaction(check_error=True) as txn:
            txn.add(self._nb_ovn.delete_lswitch_port(port['id'],
                    utils.ovn_name(port['network_id'])))
            txn.add(self._nb_ovn.delete_acl(
                    utils.ovn_name(port['network_id']), port['id']))

            if port.get('fixed_ips'):
                addresses = ovn_acl.acl_port_ips(port)
                for sg_id in port.get('security_groups', []):
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(self._nb_ovn.update_address_set(
                                name=utils.ovn_addrset_name(sg_id, ip_version),
                                addrs_add=None,
                                addrs_remove=addresses[ip_version]))

            # NOTE(lizk): Always try to clean port dhcp options, to make sure
            # no orphaned DHCP_Options row related to port left behind, which
            # may be created in get_port_dhcpv4_options.
            cmd = self._get_delete_lsp_dhcpv4_options_cmd(port)
            if cmd:
                txn.add(cmd)
Пример #17
0
    def delete_port_postcommit(self, context):
        """Delete a port.

        :param context: PortContext instance describing the current
        state of the port, prior to the call to delete it.

        Called after the transaction completes. Call can block, though
        will block the entire process so care should be taken to not
        drastically affect performance.  Runtime errors are not
        expected, and will not prevent the resource from being
        deleted.
        """
        port = context.current
        self._delete_lsp_dhcpv4_options(port)
        with self._nb_ovn.transaction(check_error=True) as txn:
            txn.add(self._nb_ovn.delete_lswitch_port(port['id'],
                    utils.ovn_name(port['network_id'])))
            txn.add(self._nb_ovn.delete_acl(
                    utils.ovn_name(port['network_id']), port['id']))

            if port.get('fixed_ips'):
                addresses = ovn_acl.acl_port_ips(port)
                for sg_id in port.get('security_groups', []):
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(self._nb_ovn.update_address_set(
                                name=utils.ovn_addrset_name(sg_id, ip_version),
                                addrs_add=None,
                                addrs_remove=addresses[ip_version]))
Пример #18
0
 def _process_sg_notification(self, resource, event, trigger, **kwargs):
     sg = kwargs.get('security_group')
     external_ids = {ovn_const.OVN_SG_NAME_EXT_ID_KEY: sg['name']}
     with self._nb_ovn.transaction(check_error=True) as txn:
         for ip_version in ['ip4', 'ip6']:
             if event == events.AFTER_CREATE:
                 txn.add(self._nb_ovn.create_address_set(
                         name=utils.ovn_addrset_name(sg['id'], ip_version),
                         external_ids=external_ids))
             elif event == events.AFTER_UPDATE:
                 txn.add(self._nb_ovn.update_address_set_ext_ids(
                         name=utils.ovn_addrset_name(sg['id'], ip_version),
                         external_ids=external_ids))
             elif event == events.BEFORE_DELETE:
                 txn.add(self._nb_ovn.delete_address_set(
                         name=utils.ovn_addrset_name(sg['id'], ip_version)))
Пример #19
0
def acl_remote_group_id(r, ip_version):
    if not r['remote_group_id']:
        return ''

    src_or_dst = 'src' if r['direction'] == 'ingress' else 'dst'
    addrset_name = utils.ovn_addrset_name(r['remote_group_id'],
                                          ip_version)
    return ' && %s.%s == $%s' % (ip_version, src_or_dst, addrset_name)
Пример #20
0
def acl_remote_group_id(r, ip_version, ovn=None):
    if not r['remote_group_id']:
        return ''

    src_or_dst = 'src' if r['direction'] == 'ingress' else 'dst'
    if (ovn and ovn.is_port_groups_supported()):
        addrset_name = utils.ovn_pg_addrset_name(r['remote_group_id'],
                                                 ip_version)
    else:
        addrset_name = utils.ovn_addrset_name(r['remote_group_id'], ip_version)
    return ' && %s.%s == $%s' % (ip_version, src_or_dst, addrset_name)
Пример #21
0
def acl_remote_group_id(r, ip_version, ovn=None):
    if not r['remote_group_id']:
        return ''

    src_or_dst = 'src' if r['direction'] == 'ingress' else 'dst'
    # Check if the remote group is modelled as a Port Group or not as the
    # name of the Address Set differs.
    if (ovn and ovn.is_port_groups_supported()
            and not ovn.get_address_set(r['security_group_id'])):
        addrset_name = utils.ovn_pg_addrset_name(r['remote_group_id'],
                                                 ip_version)
    else:
        addrset_name = utils.ovn_addrset_name(r['remote_group_id'], ip_version)
    return ' && %s.%s == $%s' % (ip_version, src_or_dst, addrset_name)
Пример #22
0
    def create_port_in_ovn(self, port, ovn_port_info):
        external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY: port["name"]}
        lswitch_name = utils.ovn_name(port["network_id"])
        admin_context = n_context.get_admin_context()
        sg_cache = {}
        subnet_cache = {}

        with self._nb_ovn.transaction(check_error=True) as txn:
            # The lport_name *must* be neutron port['id'].  It must match the
            # iface-id set in the Interfaces table of the Open_vSwitch
            # database which nova sets to be the port ID.
            txn.add(
                self._nb_ovn.create_lswitch_port(
                    lport_name=port["id"],
                    lswitch_name=lswitch_name,
                    addresses=ovn_port_info.addresses,
                    external_ids=external_ids,
                    parent_name=ovn_port_info.parent_name,
                    tag=ovn_port_info.tag,
                    enabled=port.get("admin_state_up"),
                    options=ovn_port_info.options,
                    type=ovn_port_info.type,
                    port_security=ovn_port_info.port_security,
                    dhcpv4_options=ovn_port_info.dhcpv4_options,
                )
            )

            acls_new = ovn_acl.add_acls(self._plugin, admin_context, port, sg_cache, subnet_cache)
            for acl in acls_new:
                txn.add(self._nb_ovn.add_acl(**acl))

            sg_ids = port.get("security_groups", [])
            if port.get("fixed_ips") and sg_ids:
                addresses = ovn_acl.acl_port_ips(port)
                # NOTE(rtheis): Fail port creation if the address set doesn't
                # exist. This prevents ports from being created on any security
                # groups out-of-sync between neutron and OVN.
                for sg_id in sg_ids:
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(
                                self._nb_ovn.update_address_set(
                                    name=utils.ovn_addrset_name(sg_id, ip_version),
                                    addrs_add=addresses[ip_version],
                                    addrs_remove=None,
                                    if_exists=False,
                                )
                            )
Пример #23
0
    def create_port_in_ovn(self, port, ovn_port_info):
        external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY: port['name']}
        lswitch_name = utils.ovn_name(port['network_id'])
        admin_context = n_context.get_admin_context()
        sg_cache = {}
        subnet_cache = {}

        with self._nb_ovn.transaction(check_error=True) as txn:
            # The lport_name *must* be neutron port['id'].  It must match the
            # iface-id set in the Interfaces table of the Open_vSwitch
            # database which nova sets to be the port ID.
            txn.add(
                self._nb_ovn.create_lswitch_port(
                    lport_name=port['id'],
                    lswitch_name=lswitch_name,
                    addresses=ovn_port_info.addresses,
                    external_ids=external_ids,
                    parent_name=ovn_port_info.parent_name,
                    tag=ovn_port_info.tag,
                    enabled=port.get('admin_state_up'),
                    options=ovn_port_info.options,
                    type=ovn_port_info.type,
                    port_security=ovn_port_info.port_security,
                    dhcpv4_options=ovn_port_info.dhcpv4_options))

            acls_new = ovn_acl.add_acls(self._plugin, admin_context, port,
                                        sg_cache, subnet_cache)
            for acl in acls_new:
                txn.add(self._nb_ovn.add_acl(**acl))

            sg_ids = port.get('security_groups', [])
            if port.get('fixed_ips') and sg_ids:
                addresses = ovn_acl.acl_port_ips(port)
                # NOTE(rtheis): Fail port creation if the address set doesn't
                # exist. This prevents ports from being created on any security
                # groups out-of-sync between neutron and OVN.
                for sg_id in sg_ids:
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(
                                self._nb_ovn.update_address_set(
                                    name=utils.ovn_addrset_name(
                                        sg_id, ip_version),
                                    addrs_add=addresses[ip_version],
                                    addrs_remove=None,
                                    if_exists=False))
Пример #24
0
    def delete_port_postcommit(self, context):
        """Delete a port.

        :param context: PortContext instance describing the current
        state of the port, prior to the call to delete it.

        Called after the transaction completes. Call can block, though
        will block the entire process so care should be taken to not
        drastically affect performance.  Runtime errors are not
        expected, and will not prevent the resource from being
        deleted.
        """
        port = context.current
        with self._nb_ovn.transaction(check_error=True) as txn:
            txn.add(
                self._nb_ovn.delete_lswitch_port(
                    port['id'], utils.ovn_name(port['network_id'])))
            txn.add(
                self._nb_ovn.delete_acl(utils.ovn_name(port['network_id']),
                                        port['id']))

            if port.get('fixed_ips'):
                addresses = ovn_acl.acl_port_ips(port)
                for sg_id in port.get('security_groups', []):
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(
                                self._nb_ovn.update_address_set(
                                    name=utils.ovn_addrset_name(
                                        sg_id, ip_version),
                                    addrs_add=None,
                                    addrs_remove=addresses[ip_version]))

                # Delete the DHCP_Options row if created for this port.
                # A separate DHCP_Options row would have be created if the port
                # has extra DHCP options defined.
                for fixed_ip in port['fixed_ips']:
                    if netaddr.IPAddress(fixed_ip['ip_address']).version == 4:
                        lsp_dhcp_options = self._nb_ovn.get_port_dhcp_options(
                            fixed_ip['subnet_id'], port['id'])
                        if lsp_dhcp_options:
                            txn.add(
                                self._nb_ovn.delete_dhcp_options(
                                    lsp_dhcp_options['uuid']))
                            break
Пример #25
0
    def test_acl_remote_group_id(self):
        sg_rule = fakes.FakeSecurityGroupRule.create_one_security_group_rule({
            'direction': 'ingress',
            'remote_group_id': None
        }).info()
        ip_version = 'ip4'
        sg_id = sg_rule['security_group_id']

        addrset_name = ovn_utils.ovn_addrset_name(sg_id, ip_version)

        match = ovn_acl.acl_remote_group_id(sg_rule, ip_version)
        self.assertEqual('', match)

        sg_rule['remote_group_id'] = sg_id
        match = ovn_acl.acl_remote_group_id(sg_rule, ip_version)
        self.assertEqual(' && ip4.src == $' + addrset_name, match)

        sg_rule['direction'] = 'egress'
        match = ovn_acl.acl_remote_group_id(sg_rule, ip_version)
        self.assertEqual(' && ip4.dst == $' + addrset_name, match)
Пример #26
0
    def test_acl_remote_group_id(self):
        sg_rule = fakes.FakeSecurityGroupRule.create_one_security_group_rule({
            'direction': 'ingress',
            'remote_group_id': None
        }).info()
        ip_version = 'ip4'
        sg_id = sg_rule['security_group_id']

        addrset_name = ovn_utils.ovn_addrset_name(sg_id, ip_version)

        match = ovn_acl.acl_remote_group_id(sg_rule, ip_version)
        self.assertEqual('', match)

        sg_rule['remote_group_id'] = sg_id
        match = ovn_acl.acl_remote_group_id(sg_rule, ip_version)
        self.assertEqual(' && ip4.src == $' + addrset_name, match)

        sg_rule['direction'] = 'egress'
        match = ovn_acl.acl_remote_group_id(sg_rule, ip_version)
        self.assertEqual(' && ip4.dst == $' + addrset_name, match)
Пример #27
0
    def delete_port_postcommit(self, context):
        """Delete a port.

        :param context: PortContext instance describing the current
        state of the port, prior to the call to delete it.

        Called after the transaction completes. Call can block, though
        will block the entire process so care should be taken to not
        drastically affect performance.  Runtime errors are not
        expected, and will not prevent the resource from being
        deleted.
        """
        port = context.current
        with self._nb_ovn.transaction(check_error=True) as txn:
            txn.add(self._nb_ovn.delete_lswitch_port(port["id"], utils.ovn_name(port["network_id"])))
            txn.add(self._nb_ovn.delete_acl(utils.ovn_name(port["network_id"]), port["id"]))

            if port.get("fixed_ips"):
                addresses = ovn_acl.acl_port_ips(port)
                for sg_id in port.get("security_groups", []):
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(
                                self._nb_ovn.update_address_set(
                                    name=utils.ovn_addrset_name(sg_id, ip_version),
                                    addrs_add=None,
                                    addrs_remove=addresses[ip_version],
                                )
                            )

                # Delete the DHCP_Options row if created for this port.
                # A separate DHCP_Options row would have be created if the port
                # has extra DHCP options defined.
                for fixed_ip in port["fixed_ips"]:
                    if netaddr.IPAddress(fixed_ip["ip_address"]).version == 4:
                        lsp_dhcp_options = self._nb_ovn.get_port_dhcp_options(fixed_ip["subnet_id"], port["id"])
                        if lsp_dhcp_options:
                            txn.add(self._nb_ovn.delete_dhcp_options(lsp_dhcp_options["uuid"]))
                            break
Пример #28
0
    def create_port_in_ovn(self, port, ovn_port_info):
        external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY: port['name']}
        lswitch_name = utils.ovn_name(port['network_id'])
        admin_context = n_context.get_admin_context()
        sg_cache = {}
        subnet_cache = {}

        with self._nb_ovn.transaction(check_error=True) as txn:
            # The lport_name *must* be neutron port['id'].  It must match the
            # iface-id set in the Interfaces table of the Open_vSwitch
            # database which nova sets to be the port ID.
            txn.add(self._nb_ovn.create_lswitch_port(
                    lport_name=port['id'],
                    lswitch_name=lswitch_name,
                    addresses=ovn_port_info.addresses,
                    external_ids=external_ids,
                    parent_name=ovn_port_info.parent_name,
                    tag=ovn_port_info.tag,
                    enabled=port.get('admin_state_up'),
                    options=ovn_port_info.options,
                    type=ovn_port_info.type,
                    port_security=ovn_port_info.port_security))
            acls_new = ovn_acl.add_acls(self._plugin, admin_context,
                                        port, sg_cache, subnet_cache)
            for acl in acls_new:
                txn.add(self._nb_ovn.add_acl(**acl))

            sg_ids = port.get('security_groups', [])
            if port.get('fixed_ips') and sg_ids:
                addresses = ovn_acl.acl_port_ips(port)
                for sg_id in sg_ids:
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(self._nb_ovn.update_address_set(
                                name=utils.ovn_addrset_name(sg_id, ip_version),
                                addrs_add=addresses[ip_version],
                                addrs_remove=None))
Пример #29
0
    def _modify_resources_in_nb_db(self):
        fake_api = mock.MagicMock()
        fake_api.idl = self.monitor_nb_db_idl
        fake_api._tables = self.monitor_nb_db_idl.tables

        with self.nb_idl_transaction(fake_api, check_error=True) as txn:
            for lswitch_name in self.create_lswitches:
                external_ids = {
                    ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY: lswitch_name
                }
                txn.add(
                    cmd.AddLSwitchCommand(fake_api,
                                          lswitch_name,
                                          True,
                                          external_ids=external_ids))

            for lswitch_name in self.delete_lswitches:
                txn.add(cmd.DelLSwitchCommand(fake_api, lswitch_name, True))

            for lport_name, lswitch_name in self.create_lswitch_ports:
                external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY: lport_name}
                txn.add(
                    cmd.AddLSwitchPortCommand(fake_api,
                                              lport_name,
                                              lswitch_name,
                                              True,
                                              external_ids=external_ids))

            for lport_name, lswitch_name in self.delete_lswitch_ports:
                txn.add(
                    cmd.DelLSwitchPortCommand(fake_api, lport_name,
                                              lswitch_name, True))

            for lrouter_name in self.create_lrouters:
                external_ids = {
                    ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: lrouter_name
                }
                txn.add(
                    cmd.AddLRouterCommand(fake_api,
                                          lrouter_name,
                                          True,
                                          external_ids=external_ids))

            for lrouter_name in self.delete_lrouters:
                txn.add(cmd.DelLRouterCommand(fake_api, lrouter_name, True))

            for lrport, lrouter_name in self.create_lrouter_ports:
                txn.add(
                    cmd.AddLRouterPortCommand(fake_api, lrport, lrouter_name))

            for lrport, lrouter_name in self.delete_lrouter_ports:
                txn.add(
                    cmd.DelLRouterPortCommand(fake_api, lrport, lrouter_name,
                                              True))

            for lrouter_name, ip_prefix, nexthop in self.create_lrouter_routes:
                txn.add(
                    cmd.AddStaticRouteCommand(fake_api,
                                              lrouter_name,
                                              ip_prefix=ip_prefix,
                                              nexthop=nexthop))

            for lrouter_name, ip_prefix, nexthop in self.delete_lrouter_routes:
                txn.add(
                    cmd.DelStaticRouteCommand(fake_api, lrouter_name,
                                              ip_prefix, nexthop, True))

            for acl in self.create_acls:
                txn.add(cmd.AddACLCommand(fake_api, **acl))

            for lport_name, lswitch_name in self.delete_acls:
                txn.add(
                    cmd.DelACLCommand(fake_api, lswitch_name, lport_name,
                                      True))

            for name, ip_version in self.create_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                external_ids = {ovn_const.OVN_SG_NAME_EXT_ID_KEY: name}
                txn.add(
                    cmd.AddAddrSetCommand(fake_api,
                                          ovn_name,
                                          True,
                                          external_ids=external_ids))

            for name, ip_version in self.delete_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                txn.add(cmd.DelAddrSetCommand(fake_api, ovn_name, True))

            for name, ip_version, ip_adds, ip_dels in self.update_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                txn.add(
                    cmd.UpdateAddrSetCommand(fake_api, ovn_name, ip_adds,
                                             ip_dels, True))
Пример #30
0
    def _modify_resources_in_nb_db(self):
        fake_api = mock.MagicMock()
        fake_api.idl = self.monitor_nb_db_idl
        fake_api._tables = self.monitor_nb_db_idl.tables

        with self.nb_idl_transaction(fake_api, check_error=True) as txn:
            for lswitch_name in self.create_lswitches:
                external_ids = {ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY:
                                lswitch_name}
                txn.add(cmd.AddLSwitchCommand(fake_api, lswitch_name, True,
                                              external_ids=external_ids))

            for lswitch_name in self.delete_lswitches:
                txn.add(cmd.DelLSwitchCommand(fake_api, lswitch_name, True))

            for lport_name, lswitch_name in self.create_lswitch_ports:
                external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY:
                                lport_name}
                txn.add(cmd.AddLSwitchPortCommand(fake_api, lport_name,
                                                  lswitch_name, True,
                                                  external_ids=external_ids))

            for lport_name, lswitch_name in self.delete_lswitch_ports:
                txn.add(cmd.DelLSwitchPortCommand(fake_api, lport_name,
                                                  lswitch_name, True))

            for lrouter_name in self.create_lrouters:
                external_ids = {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY:
                                lrouter_name}
                txn.add(cmd.AddLRouterCommand(fake_api, lrouter_name, True,
                                              external_ids=external_ids))

            for lrouter_name in self.delete_lrouters:
                txn.add(cmd.DelLRouterCommand(fake_api, lrouter_name, True))

            for lrport, lrouter_name in self.create_lrouter_ports:
                txn.add(cmd.AddLRouterPortCommand(fake_api, lrport,
                                                  lrouter_name))

            for lrport, lrouter_name in self.delete_lrouter_ports:
                txn.add(cmd.DelLRouterPortCommand(fake_api, lrport,
                                                  lrouter_name, True))

            for lrouter_name, ip_prefix, nexthop in self.create_lrouter_routes:
                txn.add(cmd.AddStaticRouteCommand(fake_api, lrouter_name,
                                                  ip_prefix=ip_prefix,
                                                  nexthop=nexthop))

            for lrouter_name, ip_prefix, nexthop in self.delete_lrouter_routes:
                txn.add(cmd.DelStaticRouteCommand(fake_api, lrouter_name,
                                                  ip_prefix, nexthop, True))

            for acl in self.create_acls:
                txn.add(cmd.AddACLCommand(fake_api, **acl))

            for lport_name, lswitch_name in self.delete_acls:
                txn.add(cmd.DelACLCommand(fake_api, lswitch_name,
                                          lport_name, True))

            for name, ip_version in self.create_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                external_ids = {ovn_const.OVN_SG_NAME_EXT_ID_KEY: name}
                txn.add(cmd.AddAddrSetCommand(fake_api, ovn_name, True,
                                              external_ids=external_ids))

            for name, ip_version in self.delete_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                txn.add(cmd.DelAddrSetCommand(fake_api, ovn_name,
                                              True))

            for name, ip_version, ip_adds, ip_dels in self.update_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                txn.add(cmd.UpdateAddrSetCommand(fake_api, ovn_name,
                                                 ip_adds, ip_dels, True))
Пример #31
0
    def _update_port_in_ovn(self, original_port, port, ovn_port_info):
        external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY: port["name"]}
        admin_context = n_context.get_admin_context()
        sg_cache = {}
        subnet_cache = {}

        with self._nb_ovn.transaction(check_error=True) as txn:
            txn.add(
                self._nb_ovn.set_lswitch_port(
                    lport_name=port["id"],
                    addresses=ovn_port_info.addresses,
                    external_ids=external_ids,
                    parent_name=ovn_port_info.parent_name,
                    tag=ovn_port_info.tag,
                    type=ovn_port_info.type,
                    options=ovn_port_info.options,
                    enabled=port["admin_state_up"],
                    port_security=ovn_port_info.port_security,
                    dhcpv4_options=ovn_port_info.dhcpv4_options,
                )
            )

            # Determine if security groups or fixed IPs are updated.
            old_sg_ids = set(original_port.get("security_groups", []))
            new_sg_ids = set(port.get("security_groups", []))
            detached_sg_ids = old_sg_ids - new_sg_ids
            attached_sg_ids = new_sg_ids - old_sg_ids
            is_fixed_ips_updated = original_port.get("fixed_ips") != port.get("fixed_ips")

            # Refresh ACLs for changed security groups or fixed IPs.
            if detached_sg_ids or attached_sg_ids or is_fixed_ips_updated:
                # Note that update_acls will compare the port's ACLs to
                # ensure only the necessary ACLs are added and deleted
                # on the transaction.
                acls_new = ovn_acl.add_acls(self._plugin, admin_context, port, sg_cache, subnet_cache)
                txn.add(
                    self._nb_ovn.update_acls([port["network_id"]], [port], {port["id"]: acls_new}, need_compare=True)
                )

            # Refresh address sets for changed security groups or fixed IPs.
            if len(port.get("fixed_ips")) != 0 or len(original_port.get("fixed_ips")) != 0:
                addresses = ovn_acl.acl_port_ips(port)
                addresses_old = ovn_acl.acl_port_ips(original_port)
                # Add current addresses to attached security groups.
                for sg_id in attached_sg_ids:
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(
                                self._nb_ovn.update_address_set(
                                    name=utils.ovn_addrset_name(sg_id, ip_version),
                                    addrs_add=addresses[ip_version],
                                    addrs_remove=None,
                                )
                            )
                # Remove old addresses from detached security groups.
                for sg_id in detached_sg_ids:
                    for ip_version in addresses_old:
                        if addresses_old[ip_version]:
                            txn.add(
                                self._nb_ovn.update_address_set(
                                    name=utils.ovn_addrset_name(sg_id, ip_version),
                                    addrs_add=None,
                                    addrs_remove=addresses_old[ip_version],
                                )
                            )

                if is_fixed_ips_updated:
                    # We have refreshed address sets for attached and detached
                    # security groups, so now we only need to take care of
                    # unchanged security groups.
                    unchanged_sg_ids = new_sg_ids & old_sg_ids
                    for sg_id in unchanged_sg_ids:
                        for ip_version in addresses:
                            addr_add = (set(addresses[ip_version]) - set(addresses_old[ip_version])) or None
                            addr_remove = (set(addresses_old[ip_version]) - set(addresses[ip_version])) or None

                            if addr_add or addr_remove:
                                txn.add(
                                    self._nb_ovn.update_address_set(
                                        name=utils.ovn_addrset_name(sg_id, ip_version),
                                        addrs_add=addr_add,
                                        addrs_remove=addr_remove,
                                    )
                                )

            if not ovn_port_info.dhcpv4_options:
                # Check if the DHCP_Options row exist for this port.
                # We need to delete it as it is no longer referenced by this
                # port.
                cmd = self._get_delete_lsp_dhcpv4_options_cmd(port)
                if cmd:
                    txn.add(cmd)
Пример #32
0
    def _update_port_in_ovn(self, original_port, port, ovn_port_info):
        external_ids = {
            ovn_const.OVN_PORT_NAME_EXT_ID_KEY: port['name']}
        admin_context = n_context.get_admin_context()
        sg_cache = {}
        subnet_cache = {}

        with self._nb_ovn.transaction(check_error=True) as txn:
            txn.add(self._nb_ovn.set_lswitch_port(
                    lport_name=port['id'],
                    addresses=ovn_port_info.addresses,
                    external_ids=external_ids,
                    parent_name=ovn_port_info.parent_name,
                    tag=ovn_port_info.tag,
                    type=ovn_port_info.type,
                    options=ovn_port_info.options,
                    enabled=port['admin_state_up'],
                    port_security=ovn_port_info.port_security))

            # Determine if security groups or fixed IPs are updated.
            old_sg_ids = set(original_port.get('security_groups', []))
            new_sg_ids = set(port.get('security_groups', []))
            detached_sg_ids = old_sg_ids - new_sg_ids
            attached_sg_ids = new_sg_ids - old_sg_ids
            is_fixed_ips_updated = \
                original_port.get('fixed_ips') != port.get('fixed_ips')

            # Refresh ACLs for changed security groups or fixed IPs.
            if detached_sg_ids or attached_sg_ids or is_fixed_ips_updated:
                # Note that update_acls will compare the port's ACLs to
                # ensure only the necessary ACLs are added and deleted
                # on the transaction.
                acls_new = ovn_acl.add_acls(self._plugin,
                                            admin_context,
                                            port,
                                            sg_cache,
                                            subnet_cache)
                txn.add(self._nb_ovn.update_acls([port['network_id']],
                                                 [port],
                                                 {port['id']: acls_new},
                                                 need_compare=True))

            # Refresh address sets for changed security groups or fixed IPs.
            if (len(port.get('fixed_ips')) != 0 or
                    len(original_port.get('fixed_ips')) != 0):
                addresses = ovn_acl.acl_port_ips(port)
                addresses_old = ovn_acl.acl_port_ips(original_port)
                # Add current addresses to attached security groups.
                for sg_id in attached_sg_ids:
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(self._nb_ovn.update_address_set(
                                name=utils.ovn_addrset_name(sg_id, ip_version),
                                addrs_add=addresses[ip_version],
                                addrs_remove=None))
                # Remove old addresses from detached security groups.
                for sg_id in detached_sg_ids:
                    for ip_version in addresses_old:
                        if addresses_old[ip_version]:
                            txn.add(self._nb_ovn.update_address_set(
                                name=utils.ovn_addrset_name(sg_id, ip_version),
                                addrs_add=None,
                                addrs_remove=addresses_old[ip_version]))

                if is_fixed_ips_updated:
                    # We have refreshed address sets for attached and detached
                    # security groups, so now we only need to take care of
                    # unchanged security groups.
                    unchanged_sg_ids = new_sg_ids & old_sg_ids
                    for sg_id in unchanged_sg_ids:
                        for ip_version in addresses:
                            addr_add = (set(addresses[ip_version]) -
                                        set(addresses_old[ip_version])) or None
                            addr_remove = (set(addresses_old[ip_version]) -
                                           set(addresses[ip_version])) or None

                            if addr_add or addr_remove:
                                txn.add(self._nb_ovn.update_address_set(
                                        name=utils.ovn_addrset_name(
                                            sg_id, ip_version),
                                        addrs_add=addr_add,
                                        addrs_remove=addr_remove))
Пример #33
0
    def _modify_resources_in_nb_db(self):
        fake_api = mock.MagicMock()
        fake_api.idl = self.monitor_nb_db_idl
        fake_api._tables = self.monitor_nb_db_idl.tables

        with self.nb_idl_transaction(fake_api, check_error=True) as txn:
            for lswitch_name in self.create_lswitches:
                external_ids = {
                    ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY: lswitch_name
                }
                txn.add(
                    cmd.AddLSwitchCommand(fake_api,
                                          lswitch_name,
                                          True,
                                          external_ids=external_ids))

            for lswitch_name in self.delete_lswitches:
                txn.add(cmd.DelLSwitchCommand(fake_api, lswitch_name, True))

            for lport_name, lswitch_name in self.create_lswitch_ports:
                external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY: lport_name}
                txn.add(
                    cmd.AddLSwitchPortCommand(fake_api,
                                              lport_name,
                                              lswitch_name,
                                              True,
                                              external_ids=external_ids))

            for lport_name, lswitch_name in self.delete_lswitch_ports:
                txn.add(
                    cmd.DelLSwitchPortCommand(fake_api, lport_name,
                                              lswitch_name, True))

            for lrouter_name in self.create_lrouters:
                external_ids = {
                    ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: lrouter_name
                }
                txn.add(
                    cmd.AddLRouterCommand(fake_api,
                                          lrouter_name,
                                          True,
                                          external_ids=external_ids))

            for lrouter_name in self.delete_lrouters:
                txn.add(cmd.DelLRouterCommand(fake_api, lrouter_name, True))

            for lrport, lrouter_name in self.create_lrouter_ports:
                txn.add(
                    cmd.AddLRouterPortCommand(fake_api, lrport, lrouter_name))

            for lrport, lrouter_name, networks in self.update_lrouter_ports:
                txn.add(
                    cmd.UpdateLRouterPortCommand(fake_api, lrport,
                                                 lrouter_name, True,
                                                 **{'networks': [networks]}))

            for lrport, lrouter_name in self.delete_lrouter_ports:
                txn.add(
                    cmd.DelLRouterPortCommand(fake_api, lrport, lrouter_name,
                                              True))

            for lrouter_name, ip_prefix, nexthop in self.create_lrouter_routes:
                txn.add(
                    cmd.AddStaticRouteCommand(fake_api,
                                              lrouter_name,
                                              ip_prefix=ip_prefix,
                                              nexthop=nexthop))

            for lrouter_name, ip_prefix, nexthop in self.delete_lrouter_routes:
                txn.add(
                    cmd.DelStaticRouteCommand(fake_api, lrouter_name,
                                              ip_prefix, nexthop, True))

            for acl in self.create_acls:
                txn.add(cmd.AddACLCommand(fake_api, **acl))

            for lport_name, lswitch_name in self.delete_acls:
                txn.add(
                    cmd.DelACLCommand(fake_api, lswitch_name, lport_name,
                                      True))

            for name, ip_version in self.create_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                external_ids = {ovn_const.OVN_SG_NAME_EXT_ID_KEY: name}
                txn.add(
                    cmd.AddAddrSetCommand(fake_api,
                                          ovn_name,
                                          True,
                                          external_ids=external_ids))

            for name, ip_version in self.delete_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                txn.add(cmd.DelAddrSetCommand(fake_api, ovn_name, True))

            for name, ip_version, ip_adds, ip_dels in self.update_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                txn.add(
                    cmd.UpdateAddrSetCommand(fake_api, ovn_name, ip_adds,
                                             ip_dels, True))

            for lport_name in self.reset_lport_dhcpv4_options:
                txn.add(
                    cmd.SetLSwitchPortCommand(fake_api,
                                              lport_name,
                                              True,
                                              dhcpv4_options=[]))

            for dhcp_opts in self.stale_lport_dhcpv4_options:
                txn.add(
                    cmd.AddDHCPOptionsCommand(
                        fake_api,
                        dhcp_opts['subnet_id'],
                        port_id=dhcp_opts['port_id'],
                        cidr=dhcp_opts['cidr'],
                        options=dhcp_opts['options'],
                        external_ids=dhcp_opts['external_ids']))

            for row_uuid in self.missed_dhcpv4_options:
                txn.add(cmd.DelDHCPOptionsCommand(fake_api, row_uuid))

            for dhcp_opts in self.dirty_dhcpv4_options:
                txn.add(
                    cmd.AddDHCPOptionsCommand(fake_api,
                                              dhcp_opts['subnet_id'],
                                              port_id=dhcp_opts.get('port_id'),
                                              external_ids={
                                                  'subnet_id':
                                                  dhcp_opts['subnet_id'],
                                                  'port_id':
                                                  dhcp_opts.get('port_id')
                                              },
                                              options={'foo': 'bar'}))

            for port_id in self.lport_dhcpv4_disabled:
                txn.add(
                    cmd.SetLSwitchPortCommand(
                        fake_api,
                        port_id,
                        True,
                        dhcpv4_options=[self.lport_dhcpv4_disabled[port_id]]))

        with self.nb_idl_transaction(fake_api, check_error=True) as txn:
            for dhcp_opts in self.stale_lport_dhcpv4_options:
                if dhcp_opts['port_id'] in self.orphaned_lport_dhcpv4_options:
                    continue
                uuid = self.mech_driver._nb_ovn.get_port_dhcp_options(
                    dhcp_opts['subnet_id'], dhcp_opts['port_id'])['uuid']
                txn.add(
                    cmd.SetLSwitchPortCommand(fake_api,
                                              lport_name,
                                              True,
                                              dhcpv4_options=[uuid]))
Пример #34
0
    def _modify_resources_in_nb_db(self):
        fake_api = mock.MagicMock()
        fake_api.idl = self.monitor_nb_db_idl
        fake_api._tables = self.monitor_nb_db_idl.tables

        with self.nb_idl_transaction(fake_api, check_error=True) as txn:
            for lswitch_name in self.create_lswitches:
                external_ids = {ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY:
                                lswitch_name}
                txn.add(cmd.AddLSwitchCommand(fake_api, lswitch_name, True,
                                              external_ids=external_ids))

            for lswitch_name in self.delete_lswitches:
                txn.add(cmd.DelLSwitchCommand(fake_api, lswitch_name, True))

            for lport_name, lswitch_name in self.create_lswitch_ports:
                external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY:
                                lport_name}
                txn.add(cmd.AddLSwitchPortCommand(fake_api, lport_name,
                                                  lswitch_name, True,
                                                  external_ids=external_ids))

            for lport_name, lswitch_name in self.delete_lswitch_ports:
                txn.add(cmd.DelLSwitchPortCommand(fake_api, lport_name,
                                                  lswitch_name, True))

            for lrouter_name in self.create_lrouters:
                external_ids = {ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY:
                                lrouter_name}
                txn.add(cmd.AddLRouterCommand(fake_api, lrouter_name, True,
                                              external_ids=external_ids))

            for lrouter_name in self.delete_lrouters:
                txn.add(cmd.DelLRouterCommand(fake_api, lrouter_name, True))

            for lrport, lrouter_name in self.create_lrouter_ports:
                txn.add(cmd.AddLRouterPortCommand(fake_api, lrport,
                                                  lrouter_name))

            for lrport, lrouter_name, networks in self.update_lrouter_ports:
                txn.add(cmd.UpdateLRouterPortCommand(
                    fake_api, lrport, lrouter_name, True,
                    **{'networks': [networks]}))

            for lrport, lrouter_name in self.delete_lrouter_ports:
                txn.add(cmd.DelLRouterPortCommand(fake_api, lrport,
                                                  lrouter_name, True))

            for lrouter_name, ip_prefix, nexthop in self.create_lrouter_routes:
                txn.add(cmd.AddStaticRouteCommand(fake_api, lrouter_name,
                                                  ip_prefix=ip_prefix,
                                                  nexthop=nexthop))

            for lrouter_name, ip_prefix, nexthop in self.delete_lrouter_routes:
                txn.add(cmd.DelStaticRouteCommand(fake_api, lrouter_name,
                                                  ip_prefix, nexthop, True))

            for acl in self.create_acls:
                txn.add(cmd.AddACLCommand(fake_api, **acl))

            for lport_name, lswitch_name in self.delete_acls:
                txn.add(cmd.DelACLCommand(fake_api, lswitch_name,
                                          lport_name, True))

            for name, ip_version in self.create_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                external_ids = {ovn_const.OVN_SG_NAME_EXT_ID_KEY: name}
                txn.add(cmd.AddAddrSetCommand(fake_api, ovn_name, True,
                                              external_ids=external_ids))

            for name, ip_version in self.delete_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                txn.add(cmd.DelAddrSetCommand(fake_api, ovn_name,
                                              True))

            for name, ip_version, ip_adds, ip_dels in self.update_address_sets:
                ovn_name = utils.ovn_addrset_name(name, ip_version)
                txn.add(cmd.UpdateAddrSetCommand(fake_api, ovn_name,
                                                 ip_adds, ip_dels, True))

            for lport_name in self.reset_lport_dhcpv4_options:
                txn.add(cmd.SetLSwitchPortCommand(fake_api, lport_name, True,
                                                  dhcpv4_options=[]))

            for lport_name in self.reset_lport_dhcpv6_options:
                txn.add(cmd.SetLSwitchPortCommand(fake_api, lport_name, True,
                                                  dhcpv6_options=[]))

            for dhcp_opts in self.stale_lport_dhcpv4_options:
                dhcpv4_opts = txn.add(cmd.AddDHCPOptionsCommand(
                    fake_api, dhcp_opts['subnet_id'],
                    port_id=dhcp_opts['port_id'],
                    cidr=dhcp_opts['cidr'],
                    options=dhcp_opts['options'],
                    external_ids=dhcp_opts['external_ids'],
                    may_exists=False))
                if dhcp_opts['port_id'] in self.orphaned_lport_dhcp_options:
                    continue
                txn.add(cmd.SetLSwitchPortCommand(fake_api, lport_name, True,
                                                  dhcpv4_options=dhcpv4_opts))

            for dhcp_opts in self.stale_lport_dhcpv6_options:
                dhcpv6_opts = txn.add(cmd.AddDHCPOptionsCommand(
                    fake_api, dhcp_opts['subnet_id'],
                    port_id=dhcp_opts['port_id'],
                    cidr=dhcp_opts['cidr'],
                    options=dhcp_opts['options'],
                    external_ids=dhcp_opts['external_ids'],
                    may_exists=False))
                if dhcp_opts['port_id'] in self.orphaned_lport_dhcp_options:
                    continue
                txn.add(cmd.SetLSwitchPortCommand(fake_api, lport_name, True,
                                                  dhcpv6_options=dhcpv6_opts))

            for row_uuid in self.missed_dhcp_options:
                txn.add(cmd.DelDHCPOptionsCommand(fake_api, row_uuid))

            for dhcp_opts in self.dirty_dhcp_options:
                txn.add(cmd.AddDHCPOptionsCommand(
                    fake_api, dhcp_opts['subnet_id'],
                    port_id=dhcp_opts.get('port_id'),
                    external_ids={'subnet_id': dhcp_opts['subnet_id'],
                                  'port_id': dhcp_opts.get('port_id')},
                    options={'foo': 'bar'}))

            for port_id in self.lport_dhcpv4_disabled:
                txn.add(cmd.SetLSwitchPortCommand(
                    fake_api, port_id, True,
                    dhcpv4_options=[self.lport_dhcpv4_disabled[port_id]]))

            for port_id in self.lport_dhcpv6_disabled:
                txn.add(cmd.SetLSwitchPortCommand(
                    fake_api, port_id, True,
                    dhcpv6_options=[self.lport_dhcpv6_disabled[port_id]]))
Пример #35
0
    def _update_port_in_ovn(self, original_port, port, ovn_port_info):
        external_ids = {
            ovn_const.OVN_PORT_NAME_EXT_ID_KEY: port['name']}
        admin_context = n_context.get_admin_context()
        sg_cache = {}
        subnet_cache = {}

        with self._nb_ovn.transaction(check_error=True) as txn:
            txn.add(self._nb_ovn.set_lswitch_port(
                    lport_name=port['id'],
                    addresses=ovn_port_info.addresses,
                    external_ids=external_ids,
                    parent_name=ovn_port_info.parent_name,
                    tag=ovn_port_info.tag,
                    type=ovn_port_info.type,
                    options=ovn_port_info.options,
                    enabled=port['admin_state_up'],
                    port_security=ovn_port_info.port_security))
            # Note that the ovsdb IDL suppresses the transaction down to what
            # has actually changed.
            txn.add(self._nb_ovn.delete_acl(
                    utils.ovn_name(port['network_id']),
                    port['id']))
            acls_new = ovn_acl.add_acls(self._plugin,
                                        admin_context,
                                        port,
                                        sg_cache,
                                        subnet_cache)
            for acl in acls_new:
                txn.add(self._nb_ovn.add_acl(**acl))

            # Refresh remote security groups for changed security groups
            old_sg_ids = set(original_port.get('security_groups', []))
            new_sg_ids = set(port.get('security_groups', []))
            detached_sg_ids = old_sg_ids - new_sg_ids
            attached_sg_ids = new_sg_ids - old_sg_ids

            if (len(port.get('fixed_ips')) != 0 or
                    len(original_port.get('fixed_ips')) != 0):
                addresses = ovn_acl.acl_port_ips(port)
                addresses_old = ovn_acl.acl_port_ips(original_port)
                # Add current addresses to attached security groups.
                for sg_id in attached_sg_ids:
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(self._nb_ovn.update_address_set(
                                name=utils.ovn_addrset_name(sg_id, ip_version),
                                addrs_add=addresses[ip_version],
                                addrs_remove=None))
                # Remove old addresses from detached security groups.
                for sg_id in detached_sg_ids:
                    for ip_version in addresses_old:
                        if addresses_old[ip_version]:
                            txn.add(self._nb_ovn.update_address_set(
                                name=utils.ovn_addrset_name(sg_id, ip_version),
                                addrs_add=None,
                                addrs_remove=addresses_old[ip_version]))

                if original_port.get('fixed_ips') != port.get('fixed_ips'):
                    # We have refreshed address sets for attached and detached
                    # security groups, so now we only need to take care of
                    # unchanged security groups.
                    unchanged_sg_ids = new_sg_ids & old_sg_ids
                    for sg_id in unchanged_sg_ids:
                        for ip_version in addresses:
                            addr_add = (set(addresses[ip_version]) -
                                        set(addresses_old[ip_version])) or None
                            addr_remove = (set(addresses_old[ip_version]) -
                                           set(addresses[ip_version])) or None

                            if addr_add or addr_remove:
                                txn.add(self._nb_ovn.update_address_set(
                                        name=utils.ovn_addrset_name(
                                            sg_id, ip_version),
                                        addrs_add=addr_add,
                                        addrs_remove=addr_remove))
Пример #36
0
    def _update_port_in_ovn(self, original_port, port, ovn_port_info):
        external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY: port['name']}
        admin_context = n_context.get_admin_context()
        sg_cache = {}
        subnet_cache = {}

        with self._nb_ovn.transaction(check_error=True) as txn:
            txn.add(
                self._nb_ovn.set_lswitch_port(
                    lport_name=port['id'],
                    addresses=ovn_port_info.addresses,
                    external_ids=external_ids,
                    parent_name=ovn_port_info.parent_name,
                    tag=ovn_port_info.tag,
                    type=ovn_port_info.type,
                    options=ovn_port_info.options,
                    enabled=port['admin_state_up'],
                    port_security=ovn_port_info.port_security,
                    dhcpv4_options=ovn_port_info.dhcpv4_options))

            # Determine if security groups or fixed IPs are updated.
            old_sg_ids = set(original_port.get('security_groups', []))
            new_sg_ids = set(port.get('security_groups', []))
            detached_sg_ids = old_sg_ids - new_sg_ids
            attached_sg_ids = new_sg_ids - old_sg_ids
            is_fixed_ips_updated = \
                original_port.get('fixed_ips') != port.get('fixed_ips')

            # Refresh ACLs for changed security groups or fixed IPs.
            if detached_sg_ids or attached_sg_ids or is_fixed_ips_updated:
                # Note that update_acls will compare the port's ACLs to
                # ensure only the necessary ACLs are added and deleted
                # on the transaction.
                acls_new = ovn_acl.add_acls(self._plugin, admin_context, port,
                                            sg_cache, subnet_cache)
                txn.add(
                    self._nb_ovn.update_acls([port['network_id']], [port],
                                             {port['id']: acls_new},
                                             need_compare=True))

            # Refresh address sets for changed security groups or fixed IPs.
            if (len(port.get('fixed_ips')) != 0
                    or len(original_port.get('fixed_ips')) != 0):
                addresses = ovn_acl.acl_port_ips(port)
                addresses_old = ovn_acl.acl_port_ips(original_port)
                # Add current addresses to attached security groups.
                for sg_id in attached_sg_ids:
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(
                                self._nb_ovn.update_address_set(
                                    name=utils.ovn_addrset_name(
                                        sg_id, ip_version),
                                    addrs_add=addresses[ip_version],
                                    addrs_remove=None))
                # Remove old addresses from detached security groups.
                for sg_id in detached_sg_ids:
                    for ip_version in addresses_old:
                        if addresses_old[ip_version]:
                            txn.add(
                                self._nb_ovn.update_address_set(
                                    name=utils.ovn_addrset_name(
                                        sg_id, ip_version),
                                    addrs_add=None,
                                    addrs_remove=addresses_old[ip_version]))

                if is_fixed_ips_updated:
                    # We have refreshed address sets for attached and detached
                    # security groups, so now we only need to take care of
                    # unchanged security groups.
                    unchanged_sg_ids = new_sg_ids & old_sg_ids
                    for sg_id in unchanged_sg_ids:
                        for ip_version in addresses:
                            addr_add = (set(addresses[ip_version]) -
                                        set(addresses_old[ip_version])) or None
                            addr_remove = (set(addresses_old[ip_version]) -
                                           set(addresses[ip_version])) or None

                            if addr_add or addr_remove:
                                txn.add(
                                    self._nb_ovn.update_address_set(
                                        name=utils.ovn_addrset_name(
                                            sg_id, ip_version),
                                        addrs_add=addr_add,
                                        addrs_remove=addr_remove))

            if not ovn_port_info.dhcpv4_options:
                # Check if the DHCP_Options row exist for this port.
                # We need to delete it as it is no longer referenced by this
                # port.
                cmd = self._get_delete_lsp_dhcpv4_options_cmd(port)
                if cmd:
                    txn.add(cmd)