예제 #1
0
    def _pgs_from_log_obj(self, context, log_obj):
        """Map Neutron log_obj into affected port groups in OVN.

        :param context: current running context information
        :param log_obj: a log_object to be analyzed.

        """
        if not log_obj.resource_id and not log_obj.target_id:
            # No sg, no port: return all pgs
            return self._pgs_all()

        pgs = []
        # include special pg_drop to log DROP and ALL actions
        if not log_obj.event or log_obj.event in (log_const.DROP_EVENT,
                                                  log_const.ALL_EVENT):
            try:
                pg = self.ovn_nb.lookup("Port_Group",
                                        ovn_const.OVN_DROP_PORT_GROUP_NAME)
                pgs.append({
                    "name": pg.name,
                    "acls": [r.uuid for r in pg.acls]
                })
            except idlutils.RowNotFound:
                pass

        if log_obj.resource_id:
            try:
                pg = self.ovn_nb.lookup(
                    "Port_Group",
                    utils.ovn_port_group_name(log_obj.resource_id))
                pgs.append({
                    "name": pg.name,
                    "acls": [r.uuid for r in pg.acls]
                })
            except idlutils.RowNotFound:
                pass
            # Note: when sg is provided, it is redundant to get sgs from port,
            # because model will ensure that sg is associated with neutron port
        elif log_obj.target_id:
            sg_ids = db_api._get_sgs_attached_to_port(context,
                                                      log_obj.target_id)
            for sg_id in sg_ids:
                try:
                    pg = self.ovn_nb.lookup("Port_Group",
                                            utils.ovn_port_group_name(sg_id))
                    pgs.append({
                        "name": pg.name,
                        "acls": [r.uuid for r in pg.acls]
                    })
                except idlutils.RowNotFound:
                    pass
        return pgs
예제 #2
0
def update_acls_for_security_group(plugin,
                                   admin_context,
                                   ovn,
                                   security_group_id,
                                   security_group_rule,
                                   is_add_acl=True):

    # Skip ACLs if security groups aren't enabled
    if not is_sg_enabled():
        return

    # Check if ACL log name and severity supported or not
    keep_name_severity = _acl_columns_name_severity_supported(ovn)

    acl = _add_sg_rule_acl_for_port_group(
        utils.ovn_port_group_name(security_group_id), security_group_rule)
    # Remove ACL log name and severity if not supported
    if is_add_acl:
        if not keep_name_severity:
            acl.pop('name')
            acl.pop('severity')
        ovn.pg_acl_add(**acl, may_exist=True).execute(check_error=True)
    else:
        ovn.pg_acl_del(acl['port_group'], acl['direction'], acl['priority'],
                       acl['match']).execute(check_error=True)
예제 #3
0
 def _fake_pg(self, **kwargs):
     pg_defaults_dict = {
         "name": ovn_utils.ovn_port_group_name(uuidutils.generate_uuid()),
         "acls": []
     }
     pg_dict = {**pg_defaults_dict, **kwargs}
     return mock.Mock(**pg_dict)
예제 #4
0
def add_acls_for_sg_port_group(ovn,
                               security_group,
                               txn,
                               stateless_supported=True):
    stateful = is_sg_stateful(security_group, stateless_supported)
    for r in security_group['security_group_rules']:
        acl = _add_sg_rule_acl_for_port_group(
            utils.ovn_port_group_name(security_group['id']), stateful, r)
        txn.add(ovn.pg_acl_add(**acl, may_exist=True))
예제 #5
0
 def _find_security_group_row_by_id(self, sg_id):
     if self.nb_api.is_port_groups_supported():
         for row in self.nb_api._tables['Port_Group'].rows.values():
             if row.name == utils.ovn_port_group_name(sg_id):
                 return row
     else:
         for row in self.nb_api._tables['Address_Set'].rows.values():
             if (row.external_ids.get(
                     ovn_const.OVN_SG_EXT_ID_KEY) == sg_id):
                 return row
예제 #6
0
 def get_port_group(self, pg_name):
     if uuidutils.is_uuid_like(pg_name):
         pg_name = utils.ovn_port_group_name(pg_name)
     try:
         return self.lookup('Port_Group', pg_name, default=None)
     except KeyError:
         # TODO(dalvarez): This except block is added for backwards compat
         # with old OVN schemas (<=2.9) where Port Groups are not present.
         # This (and other conditional code around this feature) shall be
         # removed at some point.
         return
예제 #7
0
파일: acl.py 프로젝트: zhhuabj/neutron
def add_acls_for_sg_port_group(ovn,
                               security_group,
                               txn,
                               stateless_supported=True):
    if stateless_supported:
        stateful = security_group.get("stateful", True)
    else:
        stateful = True
    for r in security_group['security_group_rules']:
        acl = _add_sg_rule_acl_for_port_group(
            utils.ovn_port_group_name(security_group['id']), stateful, r)
        txn.add(ovn.pg_acl_add(**acl, may_exist=True))
예제 #8
0
 def get_port_group(self, pg_name):
     if uuidutils.is_uuid_like(pg_name):
         pg_name = utils.ovn_port_group_name(pg_name)
     try:
         for pg in self._tables['Port_Group'].rows.values():
             if pg.name == pg_name:
                 return pg
     except KeyError:
         # TODO(dalvarez): This except block is added for backwards compat
         # with old OVN schemas (<=2.9) where Port Groups are not present.
         # This (and other conditional code around this feature) shall be
         # removed at some point.
         return
예제 #9
0
 def test__pgs_from_log_obj_pg(self):
     with mock.patch.object(self._log_driver, '_pgs_all',
                            return_value=[]) as mock_pgs_all:
         pg = self._fake_pg()
         self._nb_ovn.lookup.return_value = pg
         log_obj = self._fake_log_obj(resource_id='resource_id',
                                      target_id='target_id',
                                      event=log_const.ACCEPT_EVENT)
         pgs = self._log_driver._pgs_from_log_obj(self.context, log_obj)
         mock_pgs_all.assert_not_called()
         self._nb_ovn.lookup.assert_called_once_with(
             "Port_Group", ovn_utils.ovn_port_group_name('resource_id'))
         self.assertEqual([{'acls': [], 'name': pg.name}], pgs)
예제 #10
0
 def test__pgs_from_log_obj_port(self):
     with mock.patch.object(self._log_driver, '_pgs_all',
                            return_value=[]) as mock_pgs_all:
         sg_id = uuidutils.generate_uuid()
         pg_name = ovn_utils.ovn_port_group_name(sg_id)
         pg = self._fake_pg(name=pg_name)
         self._nb_ovn.lookup.return_value = pg
         log_obj = self._fake_log_obj(target_id='target_id',
                                      event=log_const.ACCEPT_EVENT)
         self.fake_get_sgs_attached_to_port.return_value = [sg_id]
         pgs = self._log_driver._pgs_from_log_obj(self.context, log_obj)
         mock_pgs_all.assert_not_called()
         self._nb_ovn.lookup.assert_called_once_with("Port_Group", pg_name)
         self.fake_get_sgs_attached_to_port.assert_called_once_with(
             self.context, 'target_id')
         self.assertEqual([{'acls': [], 'name': pg.name}], pgs)
예제 #11
0
def add_acls_for_sg_port_group(ovn, security_group, txn):
    for r in security_group['security_group_rules']:
        acl = _add_sg_rule_acl_for_port_group(
            utils.ovn_port_group_name(security_group['id']), r)
        txn.add(ovn.pg_acl_add(**acl, may_exist=True))
 def _find_security_group_row_by_id(self, sg_id):
     for row in self.nb_api._tables['Port_Group'].rows.values():
         if row.name == utils.ovn_port_group_name(sg_id):
             return row
예제 #13
0
def update_acls_for_security_group(plugin,
                                   admin_context,
                                   ovn,
                                   security_group_id,
                                   security_group_rule,
                                   sg_ports_cache=None,
                                   is_add_acl=True):

    # Skip ACLs if security groups aren't enabled
    if not is_sg_enabled():
        return

    # Check if ACL log name and severity supported or not
    keep_name_severity = _acl_columns_name_severity_supported(ovn)

    # If we're using a Port Group for this SG, just update it.
    # Otherwise, keep the old behavior.
    if (ovn.is_port_groups_supported() and
            not ovn.get_address_set(security_group_id)):
        acl = _add_sg_rule_acl_for_port_group(
            utils.ovn_port_group_name(security_group_id),
            security_group_rule, ovn)
        # Remove ACL log name and severity if not supported
        if is_add_acl:
            if not keep_name_severity:
                acl.pop('name')
                acl.pop('severity')
            ovn.pg_acl_add(**acl).execute(check_error=True)
        else:
            ovn.pg_acl_del(acl['port_group'], acl['direction'],
                           acl['priority'], acl['match']).execute(
                check_error=True)
        return

    # Get the security group ports.
    sg_ports_cache = sg_ports_cache or {}
    sg_ports = _get_sg_ports_from_cache(plugin,
                                        admin_context,
                                        sg_ports_cache,
                                        security_group_id)

    # ACLs associated with a security group may span logical switches
    sg_port_ids = [binding['port_id'] for binding in sg_ports]
    sg_port_ids = list(set(sg_port_ids))
    port_list = plugin.get_ports(admin_context,
                                 filters={'id': sg_port_ids})
    if not port_list:
        return

    acl_new_values_dict = {}
    update_port_list = []

    # NOTE(lizk): We can directly locate the affected acl records,
    # so no need to compare new acl values with existing acl objects.
    for port in port_list:
        # Skip trusted port
        if utils.is_lsp_trusted(port):
            continue

        update_port_list.append(port)
        acl = _add_sg_rule_acl_for_port(port, security_group_rule)
        # Remove lport and lswitch since we don't need them
        acl.pop('lport')
        acl.pop('lswitch')
        # Remove ACL log name and severity if not supported,
        if not keep_name_severity:
            acl.pop('name')
            acl.pop('severity')
        acl_new_values_dict[port['id']] = acl

    if not update_port_list:
        return
    lswitch_names = {p['network_id'] for p in update_port_list}

    ovn.update_acls(list(lswitch_names),
                    iter(update_port_list),
                    acl_new_values_dict,
                    need_compare=False,
                    is_add_acl=is_add_acl).execute(check_error=True)
예제 #14
0
 def get_port_group(self, pg_name):
     if uuidutils.is_uuid_like(pg_name):
         pg_name = utils.ovn_port_group_name(pg_name)
     return self.lookup('Port_Group', pg_name, default=None)
예제 #15
0
 def _find_security_group_row_by_id(self, sg_id):
     return self.nb_api.lookup('Port_Group',
                               utils.ovn_port_group_name(sg_id),
                               default=None)