# Agent's polling interval in seconds
polling_interval = 2
+[SECURITYGROUP]
+# Firewall driver for realizing quantum security group function
+# firewall_driver = quantum.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
+
#-----------------------------------------------------------------------------
# Sample Configurations.
#-----------------------------------------------------------------------------
yield
finally:
self.filter_defer_apply_off()
+
+
+class NoopFirewallDriver(FirewallDriver):
+ """ Noop Firewall Driver.
+
+ Firewall driver which does nothing.
+ This driver is for disabling the firewall functionality.
+ """
+
+ def prepare_port_filter(self, port):
+ pass
+
+ def apply_port_filter(self, port):
+ pass
+
+ def update_port_filter(self, port):
+ pass
+
+ def remove_port_filter(self, port):
+ pass
+
+ def filter_defer_apply_on(self):
+ pass
+
+ def filter_defer_apply_off(self):
+ pass
+
+ @property
+ def ports(self):
+ return {}
import netaddr
from quantum.agent import firewall
+from quantum.agent.linux import iptables_manager
from quantum.common import constants
+from quantum.openstack.common import cfg
from quantum.openstack.common import log as logging
EGRESS_DIRECTION = 'egress'
CHAIN_NAME_PREFIX = {INGRESS_DIRECTION: 'i',
EGRESS_DIRECTION: 'o'}
-IPTABLES_DIRECTION = {INGRESS_DIRECTION: 'physdev-out',
- EGRESS_DIRECTION: 'physdev-in'}
+LINUX_DEV_LEN = 14
class IptablesFirewallDriver(firewall.FirewallDriver):
"""Driver which enforces security groups through iptables rules."""
+ IPTABLES_DIRECTION = {INGRESS_DIRECTION: 'physdev-out',
+ EGRESS_DIRECTION: 'physdev-in'}
- def __init__(self, iptables_manager):
- self.iptables = iptables_manager
-
+ def __init__(self):
+ self.iptables = iptables_manager.IptablesManager(
+ root_helper=cfg.CONF.AGENT.root_helper,
+ use_ipv6=True)
# list of port which has security group
self.filtered_ports = {}
self._add_fallback_chain_v4v6()
for rule in ipv6_rules:
self.iptables.ipv6['filter'].add_rule(chain_name, rule)
+ def _get_device_name(self, port):
+ return port['device']
+
def _add_chain(self, port, direction):
chain_name = self._port_chain_name(port, direction)
self._add_chain_by_name_v4v6(chain_name)
# We accept the packet at the end of SG_CHAIN.
# jump to the security group chain
- device = port['device']
+ device = self._get_device_name(port)
jump_rule = ['-m physdev --physdev-is-bridged --%s '
- '%s -j $%s' % (IPTABLES_DIRECTION[direction],
+ '%s -j $%s' % (self.IPTABLES_DIRECTION[direction],
device,
SG_CHAIN)]
self._add_rule_to_chain_v4v6('FORWARD', jump_rule, jump_rule)
# jump to the chain based on the device
jump_rule = ['-m physdev --physdev-is-bridged --%s '
- '%s -j $%s' % (IPTABLES_DIRECTION[direction],
+ '%s -j $%s' % (self.IPTABLES_DIRECTION[direction],
device,
chain_name)]
self._add_rule_to_chain_v4v6(SG_CHAIN, jump_rule, jump_rule)
def filter_defer_apply_off(self):
self.iptables.defer_apply_off()
+
+
+class OVSHybridIptablesFirewallDriver(IptablesFirewallDriver):
+ OVS_HYBRID_TAP_PREFIX = 'tap'
+
+ def _port_chain_name(self, port, direction):
+ #Note (nati) make chain name short less than 28 char
+ # with extra prefix
+ # ( see comment in iptables_manager )
+ return '%s%s' % (CHAIN_NAME_PREFIX[direction],
+ port['device'][0:10])
+
+ def _get_device_name(self, port):
+ return (self.OVS_HYBRID_TAP_PREFIX + port['device'])[:LINUX_DEV_LEN]
# under the License.
#
-from quantum.agent.linux import iptables_firewall
-from quantum.agent.linux import iptables_manager
from quantum.common import topics
+from quantum.openstack.common import cfg
+from quantum.openstack.common import importutils
from quantum.openstack.common import log as logging
LOG = logging.getLogger(__name__)
SG_RPC_VERSION = "1.1"
+security_group_opts = [
+ cfg.StrOpt(
+ 'firewall_driver',
+ default='quantum.agent.firewall.NoopFirewallDriver')
+]
+cfg.CONF.register_opts(security_group_opts, 'SECURITYGROUP')
+
class SecurityGroupServerRpcApiMixin(object):
"""A mix-in that enable SecurityGroup support in plugin rpc
"""A mix-in that enable SecurityGroup agent
support in agent implementations.
"""
+ #mix-in object should be have sg_agent
+ sg_agent = None
def security_groups_rule_updated(self, context, **kwargs):
""" callback for security group rule update
security_groups = kwargs.get('security_groups', [])
LOG.debug(
_("Security group rule updated on remote: %s"), security_groups)
- self.agent.security_groups_rule_updated(security_groups)
+ self.sg_agent.security_groups_rule_updated(security_groups)
def security_groups_member_updated(self, context, **kwargs):
""" callback for security group member update
security_groups = kwargs.get('security_groups', [])
LOG.debug(
_("Security group member updated on remote: %s"), security_groups)
- self.agent.security_groups_member_updated(security_groups)
+ self.sg_agent.security_groups_member_updated(security_groups)
def security_groups_provider_updated(self, context, **kwargs):
""" callback for security group provider update
"""
LOG.debug(_("Provider rule updated"))
- self.agent.security_groups_provider_updated()
+ self.sg_agent.security_groups_provider_updated()
class SecurityGroupAgentRpcMixin(object):
def init_firewall(self):
LOG.debug(_("Init firewall settings"))
- ip_manager = iptables_manager.IptablesManager(
- root_helper=self.root_helper,
- use_ipv6=True)
- self.firewall = iptables_firewall.IptablesFirewallDriver(ip_manager)
+ self.firewall = importutils.import_object(
+ cfg.CONF.SECURITYGROUP.firewall_driver)
def prepare_devices_filter(self, device_ids):
if not device_ids:
migration_for_plugins = [
'quantum.plugins.linuxbridge.lb_quantum_plugin.LinuxBridgePluginV2',
- 'quantum.plugins.nicira.nicira_nvp_plugin.QuantumPlugin.NvpPluginV2'
+ 'quantum.plugins.nicira.nicira_nvp_plugin.QuantumPlugin.NvpPluginV2',
+ 'quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPluginV2',
]
from alembic import op
import netaddr
from quantum.common import constants as q_const
+from quantum.common import utils
from quantum.db import models_v2
from quantum.db import securitygroups_db as sg_db
+from quantum.extensions import securitygroup as ext_sg
from quantum.openstack.common import log as logging
LOG = logging.getLogger(__name__)
self.notifier.security_groups_rule_updated(context,
[rule['security_group_id']])
+ def update_security_group_on_port(self, context, id, port,
+ original_port, updated_port):
+ """ update security groups on port
+
+ This method returns a flag which indicates request notification
+ is required and does not perform notification itself.
+ It is because another changes for the port may require notification.
+ """
+ need_notify = False
+ if ext_sg.SECURITYGROUPS in port['port']:
+ # delete the port binding and read it with the new rules
+ port['port'][ext_sg.SECURITYGROUPS] = (
+ self._get_security_groups_on_port(context, port))
+ self._delete_port_security_group_bindings(context, id)
+ self._process_port_create_security_group(
+ context,
+ id,
+ port['port'][ext_sg.SECURITYGROUPS])
+ need_notify = True
+ self._extend_port_dict_security_group(context, updated_port)
+ return need_notify
+
+ def is_security_group_member_updated(self, context,
+ original_port, updated_port):
+ """ check security group member updated or not
+
+ This method returns a flag which indicates request notification
+ is required and does not perform notification itself.
+ It is because another changes for the port may require notification.
+ """
+ need_notify = False
+ if (original_port['fixed_ips'] != updated_port['fixed_ips'] or
+ not utils.compare_elements(
+ original_port.get(ext_sg.SECURITYGROUPS),
+ updated_port.get(ext_sg.SECURITYGROUPS))):
+ self.notifier.security_groups_member_updated(
+ context, updated_port.get(ext_sg.SECURITYGROUPS))
+ need_notify = True
+ return need_notify
+
class SecurityGroupServerRpcCallbackMixin(object):
"""A mix-in that enable SecurityGroup agent
def __init__(self, context, agent):
self.context = context
self.agent = agent
+ self.sg_agent = agent
def network_delete(self, context, **kwargs):
LOG.debug(_("network_delete received"))
return
if 'security_groups' in port:
- self.agent.refresh_firewall()
+ self.sg_agent.refresh_firewall()
if port['admin_state_up']:
vlan_id = kwargs.get('vlan_id')
from quantum.common import exceptions as q_exc
import quantum.db.api as db
-from quantum import manager
from quantum.db import models_v2
from quantum.db import securitygroups_db as sg_db
+from quantum import manager
from quantum.openstack.common import log as logging
# NOTE (e0ne): this import is needed for config init
from quantum.plugins.linuxbridge.common import config
def update_port(self, context, id, port):
original_port = self.get_port(context, id)
session = context.session
- port_updated = False
+ need_port_update_notify = False
+
with session.begin(subtransactions=True):
- # delete the port binding and read it with the new rules
- if ext_sg.SECURITYGROUPS in port['port']:
- port['port'][ext_sg.SECURITYGROUPS] = (
- self._get_security_groups_on_port(context, port))
- self._delete_port_security_group_bindings(context, id)
- self._process_port_create_security_group(
- context,
- id,
- port['port'][ext_sg.SECURITYGROUPS])
- port_updated = True
-
- port = super(LinuxBridgePluginV2, self).update_port(
+ updated_port = super(LinuxBridgePluginV2, self).update_port(
context, id, port)
- self._extend_port_dict_security_group(context, port)
+ need_port_update_notify = self.update_security_group_on_port(
+ context, id, port, original_port, updated_port)
- if original_port['admin_state_up'] != port['admin_state_up']:
- port_updated = True
+ need_port_update_notify |= self.is_security_group_member_updated(
+ context, original_port, updated_port)
- if (original_port['fixed_ips'] != port['fixed_ips'] or
- not utils.compare_elements(
- original_port.get(ext_sg.SECURITYGROUPS),
- port.get(ext_sg.SECURITYGROUPS))):
- self.notifier.security_groups_member_updated(
- context, port.get(ext_sg.SECURITYGROUPS))
+ if original_port['admin_state_up'] != updated_port['admin_state_up']:
+ need_port_update_notify = True
- if port_updated:
- self._notify_port_updated(context, port)
-
- return self._extend_port_dict_binding(context, port)
+ if need_port_update_notify:
+ self._notify_port_updated(context, updated_port)
+ return self._extend_port_dict_binding(context, updated_port)
def delete_port(self, context, id, l3_port_check=True):
port = self.get_port(context, id)
self._delete_port_security_group_bindings(context, id)
super(LinuxBridgePluginV2, self).delete_port(context, id)
- self.notifier.security_groups_member_updated(
- context, port.get(ext_sg.SECURITYGROUPS))
+
+ self.notifier.security_groups_member_updated(
+ context, port.get(ext_sg.SECURITYGROUPS))
def _notify_port_updated(self, context, port):
binding = db.get_network_binding(context.session,
from quantum.agent.linux import ovs_lib
from quantum.agent.linux import utils
from quantum.agent import rpc as agent_rpc
+from quantum.agent import securitygroups_rpc as sg_rpc
from quantum.common import config as logging_config
from quantum.common import topics
from quantum.common import utils as q_utils
from quantum.openstack.common import log as logging
from quantum.openstack.common.rpc import dispatcher
from quantum.plugins.openvswitch.common import config
+from quantum.extensions import securitygroup as ext_sg
from quantum.plugins.openvswitch.common import constants
return hash(self.id)
-class OVSQuantumAgent(object):
+class OVSPluginApi(agent_rpc.PluginApi,
+ sg_rpc.SecurityGroupServerRpcApiMixin):
+ pass
+
+
+class OVSSecurityGroupAgent(sg_rpc.SecurityGroupAgentRpcMixin):
+ def __init__(self, context, plugin_rpc, root_helper):
+ self.context = context
+ self.plugin_rpc = plugin_rpc
+ self.root_helper = root_helper
+ self.init_firewall()
+
+
+class OVSQuantumAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin):
'''Implements OVS-based tunneling, VLANs and flat networks.
Two local bridges are created: an integration bridge (defaults to
# Upper bound on available vlans.
MAX_VLAN_TAG = 4094
- # Set RPC API version to 1.0 by default.
- RPC_API_VERSION = '1.0'
+ # history
+ # 1.0 Initial version
+ # 1.1 Support Security Group RPC
+ RPC_API_VERSION = '1.1'
def __init__(self, integ_br, tun_br, local_ip,
bridge_mappings, root_helper,
self.setup_rpc(integ_br)
+ # Security group agent supprot
+ self.sg_agent = OVSSecurityGroupAgent(self.context,
+ self.plugin_rpc,
+ root_helper)
+
def setup_rpc(self, integ_br):
mac = utils.get_interface_mac(integ_br)
self.agent_id = '%s%s' % ('ovs', (mac.replace(":", "")))
self.topic = topics.AGENT
- self.plugin_rpc = agent_rpc.PluginApi(topics.PLUGIN)
+ self.plugin_rpc = OVSPluginApi(topics.PLUGIN)
# RPC network init
self.context = context.get_admin_context_without_session()
# Define the listening consumers for the agent
consumers = [[topics.PORT, topics.UPDATE],
[topics.NETWORK, topics.DELETE],
- [constants.TUNNEL, topics.UPDATE]]
+ [constants.TUNNEL, topics.UPDATE],
+ [topics.SECURITY_GROUP, topics.UPDATE]]
self.connection = agent_rpc.create_consumers(self.dispatcher,
self.topic,
consumers)
vif_port = self.int_br.get_vif_port_by_id(port['id'])
if not vif_port:
return
+
+ if ext_sg.SECURITYGROUPS in port:
+ self.sg_agent.refresh_firewall()
network_type = kwargs.get('network_type')
segmentation_id = kwargs.get('segmentation_id')
physical_network = kwargs.get('physical_network')
def treat_devices_added(self, devices):
resync = False
+ self.sg_agent.prepare_devices_filter(devices)
for device in devices:
LOG.info(_("Port %s added"), device)
try:
def treat_devices_removed(self, devices):
resync = False
+ self.sg_agent.remove_devices_filter(devices)
for device in devices:
LOG.info(_("Attachment %s removed"), device)
try:
from quantum.common import exceptions as q_exc
import quantum.db.api as db
from quantum.db import models_v2
+from quantum.db import securitygroups_db as sg_db
+from quantum.extensions import securitygroup as ext_sg
+from quantum import manager
from quantum.openstack.common import cfg
from quantum.openstack.common import log as logging
from quantum.plugins.openvswitch.common import constants
return port
+def get_port_from_device(port_id):
+ """Get port from database"""
+ LOG.debug(_("get_port_with_securitygroups() called:port_id=%s"), port_id)
+ session = db.get_session()
+ sg_binding_port = sg_db.SecurityGroupPortBinding.port_id
+
+ query = session.query(models_v2.Port,
+ sg_db.SecurityGroupPortBinding.security_group_id)
+ query = query.outerjoin(sg_db.SecurityGroupPortBinding,
+ models_v2.Port.id == sg_binding_port)
+ query = query.filter(models_v2.Port.id == port_id)
+ port_and_sgs = query.all()
+ if not port_and_sgs:
+ return None
+ port = port_and_sgs[0][0]
+ plugin = manager.QuantumManager.get_plugin()
+ port_dict = plugin._make_port_dict(port)
+ port_dict[ext_sg.SECURITYGROUPS] = [
+ sg_id for port, sg_id in port_and_sgs if sg_id]
+ port_dict['security_group_rules'] = []
+ port_dict['security_group_source_groups'] = []
+ port_dict['fixed_ips'] = [ip['ip_address']
+ for ip in port['fixed_ips']]
+ return port_dict
+
+
def set_port_status(port_id, status):
session = db.get_session()
try:
import sys
+from quantum.agent import securitygroups_rpc as sg_rpc
from quantum.api.v2 import attributes
from quantum.common import constants as q_const
from quantum.common import exceptions as q_exc
from quantum.db import l3_rpc_base
# NOTE: quota_db cannot be removed, it is for db model
from quantum.db import quota_db
+from quantum.db import securitygroups_rpc_base as sg_db_rpc
from quantum.extensions import portbindings
from quantum.extensions import providernet as provider
+from quantum.extensions import securitygroup as ext_sg
from quantum.openstack.common import cfg
from quantum.openstack.common import log as logging
from quantum.openstack.common import rpc
class OVSRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin,
- l3_rpc_base.L3RpcCallbackMixin):
+ l3_rpc_base.L3RpcCallbackMixin,
+ sg_db_rpc.SecurityGroupServerRpcCallbackMixin):
- # Set RPC API version to 1.0 by default.
- RPC_API_VERSION = '1.0'
+ # history
+ # 1.0 Initial version
+ # 1.1 Support Security Group RPC
+
+ RPC_API_VERSION = '1.1'
def __init__(self, notifier):
self.notifier = notifier
'''
return q_rpc.PluginRpcDispatcher([self])
+ @classmethod
+ def get_port_from_device(cls, device):
+ port = ovs_db_v2.get_port_from_device(device)
+ if port:
+ port['device'] = device
+ return port
+
def get_device_details(self, rpc_context, **kwargs):
"""Agent requests device details"""
agent_id = kwargs.get('agent_id')
return entry
-class AgentNotifierApi(proxy.RpcProxy):
+class AgentNotifierApi(proxy.RpcProxy,
+ sg_rpc.SecurityGroupAgentRpcApiMixin):
'''Agent side of the openvswitch rpc API.
API version history:
class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
- l3_db.L3_NAT_db_mixin):
+ l3_db.L3_NAT_db_mixin,
+ sg_db_rpc.SecurityGroupServerRpcMixin):
"""Implement the Quantum abstractions using Open vSwitch.
Depending on whether tunneling is enabled, either a GRE tunnel or
# bulk operations. Name mangling is used in order to ensure it
# is qualified by class
__native_bulk_support = True
- supported_extension_aliases = ["provider", "router", "binding", "quotas"]
+ supported_extension_aliases = ["provider", "router",
+ "binding", "quotas", "security-group"]
network_view = "extension:provider_network:view"
network_set = "extension:provider_network:set"
network['network'])
session = context.session
+ #set up default security groups
+ tenant_id = self._get_tenant_id_for_create(
+ context, network['network'])
+ self._ensure_default_security_group(context, tenant_id)
+
with session.begin(subtransactions=True):
if not network_type:
# tenant network
def create_port(self, context, port):
# Set port status as 'DOWN'. This will be updated by agent
port['port']['status'] = q_const.PORT_STATUS_DOWN
- port = super(OVSQuantumPluginV2, self).create_port(context, port)
+ session = context.session
+ with session.begin(subtransactions=True):
+ self._ensure_default_security_group_on_port(context, port)
+ sgids = self._get_security_groups_on_port(context, port)
+ port = super(OVSQuantumPluginV2, self).create_port(context, port)
+ self._process_port_create_security_group(
+ context, port['id'], sgids)
+ self._extend_port_dict_security_group(context, port)
+ #Note(nati): In order to allow dhcp packets,
+ # changes for dhcp ip should be notifified
+ if port['device_owner'] == q_const.DEVICE_OWNER_DHCP:
+ self.notifier.security_groups_provider_updated(context)
+ else:
+ self.notifier.security_groups_member_updated(
+ context, port.get(ext_sg.SECURITYGROUPS))
return self._extend_port_dict_binding(context, port)
def get_port(self, context, id, fields=None):
- port = super(OVSQuantumPluginV2, self).get_port(context, id, fields)
- return self._fields(self._extend_port_dict_binding(context, port),
- fields)
+ with context.session.begin(subtransactions=True):
+ port = super(OVSQuantumPluginV2, self).get_port(context,
+ id, fields)
+ self._extend_port_dict_security_group(context, port)
+ self._extend_port_dict_binding(context, port)
+ return self._fields(port, fields)
def get_ports(self, context, filters=None, fields=None):
- ports = super(OVSQuantumPluginV2, self).get_ports(context, filters,
- fields)
- return [self._fields(self._extend_port_dict_binding(context, port),
- fields) for port in ports]
+ with context.session.begin(subtransactions=True):
+ ports = super(OVSQuantumPluginV2, self).get_ports(
+ context, filters, fields)
+ #TODO(nati) filter by security group
+ for port in ports:
+ self._extend_port_dict_security_group(context, port)
+ self._extend_port_dict_binding(context, port)
+ return [self._fields(port, fields) for port in ports]
def update_port(self, context, id, port):
- original_port = super(OVSQuantumPluginV2, self).get_port(context,
- id)
- port = super(OVSQuantumPluginV2, self).update_port(context, id, port)
- if original_port['admin_state_up'] != port['admin_state_up']:
+ session = context.session
+
+ need_port_update_notify = False
+ with session.begin(subtransactions=True):
+ original_port = super(OVSQuantumPluginV2, self).get_port(
+ context, id)
+ updated_port = super(OVSQuantumPluginV2, self).update_port(
+ context, id, port)
+ need_port_update_notify = self.update_security_group_on_port(
+ context, id, port, original_port, updated_port)
+
+ need_port_update_notify |= self.is_security_group_member_updated(
+ context, original_port, updated_port)
+
+ if original_port['admin_state_up'] != updated_port['admin_state_up']:
+ need_port_update_notify = True
+
+ if need_port_update_notify:
binding = ovs_db_v2.get_network_binding(None,
- port['network_id'])
- self.notifier.port_update(context, port,
+ updated_port['network_id'])
+ self.notifier.port_update(context, updated_port,
binding.network_type,
binding.segmentation_id,
binding.physical_network)
- return self._extend_port_dict_binding(context, port)
+
+ return self._extend_port_dict_binding(context, updated_port)
def delete_port(self, context, id, l3_port_check=True):
# and l3-router. If so, we should prevent deletion.
if l3_port_check:
self.prevent_l3_port_deletion(context, id)
- self.disassociate_floatingips(context, id)
- return super(OVSQuantumPluginV2, self).delete_port(context, id)
+
+ session = context.session
+ with session.begin(subtransactions=True):
+ self.disassociate_floatingips(context, id)
+ port = self.get_port(context, id)
+ self._delete_port_security_group_bindings(context, id)
+ super(OVSQuantumPluginV2, self).delete_port(context, id)
+
+ self.notifier.security_groups_member_updated(
+ context, port.get(ext_sg.SECURITYGROUPS))
from quantum.extensions import securitygroup as ext_sg
from quantum.plugins.linuxbridge.db import l2network_db_v2 as lb_db
from quantum.tests.unit import test_extension_security_group as test_sg
+from quantum.tests.unit import test_security_groups_rpc as test_sg_rpc
+
PLUGIN_NAME = ('quantum.plugins.linuxbridge.'
'lb_quantum_plugin.LinuxBridgePluginV2')
class TestLinuxBridgeSecurityGroups(LinuxBridgeSecurityGroupsTestCase,
- test_sg.TestSecurityGroups):
-
- def test_security_group_rule_updated(self):
- name = 'webservers'
- description = 'my webservers'
- with self.security_group(name, description) as sg:
- with self.security_group(name, description) as sg2:
- security_group_id = sg['security_group']['id']
- direction = "ingress"
- source_group_id = sg2['security_group']['id']
- protocol = 'tcp'
- port_range_min = 88
- port_range_max = 88
- with self.security_group_rule(security_group_id, direction,
- protocol, port_range_min,
- port_range_max,
- source_group_id=source_group_id
- ):
- pass
- self.notifier.assert_has_calls(
- [call.security_groups_rule_updated(mock.ANY,
- [security_group_id]),
- call.security_groups_rule_updated(mock.ANY,
- [security_group_id])])
-
- def test_security_group_member_updated(self):
- with self.network() as n:
- with self.subnet(n):
- with self.security_group() as sg:
- security_group_id = sg['security_group']['id']
- res = self._create_port(self.fmt, n['network']['id'])
- port = self.deserialize(self.fmt, res)
-
- data = {'port': {'fixed_ips': port['port']['fixed_ips'],
- 'name': port['port']['name'],
- ext_sg.SECURITYGROUPS:
- [security_group_id]}}
-
- req = self.new_update_request('ports', data,
- port['port']['id'])
- res = self.deserialize(self.fmt,
- req.get_response(self.api))
- self.assertEquals(res['port'][ext_sg.SECURITYGROUPS][0],
- security_group_id)
- self._delete('ports', port['port']['id'])
- self.notifier.assert_has_calls(
- [call.security_groups_member_updated(
- mock.ANY, [mock.ANY]),
- call.security_groups_member_updated(
- mock.ANY, [security_group_id])])
+ test_sg.TestSecurityGroups,
+ test_sg_rpc.SGNotificationTestMixin):
+ pass
class TestLinuxBridgeSecurityGroupsXML(TestLinuxBridgeSecurityGroups):
test_bindings.PortBindingsTestCase):
VIF_TYPE = portbindings.VIF_TYPE_OVS
- HAS_PORT_FILTER = False
+ HAS_PORT_FILTER = True
def test_update_port_status_build(self):
with self.port() as port:
from quantum.plugins.openvswitch.agent import ovs_quantum_agent
+NOTIFIER = ('quantum.plugins.openvswitch.'
+ 'ovs_quantum_plugin.AgentNotifierApi')
+
+
class CreateAgentConfigMap(unittest.TestCase):
def test_create_agent_config_map_succeeds(self):
def setUp(self):
self.addCleanup(cfg.CONF.reset)
+ self.addCleanup(mock.patch.stopall)
+ notifier_p = mock.patch(NOTIFIER)
+ notifier_cls = notifier_p.start()
+ self.notifier = mock.Mock()
+ notifier_cls.return_value = self.notifier
# Avoid rpc initialization for unit tests
cfg.CONF.set_override('rpc_backend',
'quantum.openstack.common.rpc.impl_fake')
with mock.patch('quantum.agent.linux.utils.get_interface_mac',
return_value='000000000001'):
self.agent = ovs_quantum_agent.OVSQuantumAgent(**kwargs)
- self.agent.plugin_rpc = mock.Mock()
- self.agent.context = mock.Mock()
- self.agent.agent_id = mock.Mock()
+ self.agent.sg_agent = mock.Mock()
def mock_port_bound(self, ofport=None):
port = mock.Mock()
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013, Nachi Ueno, NTT MCL, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import mock
+
+from quantum.api.v2 import attributes
+from quantum.extensions import securitygroup as ext_sg
+from quantum import manager
+from quantum.tests.unit import test_extension_security_group as test_sg
+from quantum.tests.unit import test_security_groups_rpc as test_sg_rpc
+
+PLUGIN_NAME = ('quantum.plugins.openvswitch.'
+ 'ovs_quantum_plugin.OVSQuantumPluginV2')
+AGENT_NAME = ('quantum.plugins.openvswitch.'
+ 'agent.ovs_quantum_agent.OVSQuantumAgent')
+NOTIFIER = ('quantum.plugins.openvswitch.'
+ 'ovs_quantum_plugin.AgentNotifierApi')
+
+
+class OpenvswitchSecurityGroupsTestCase(test_sg.SecurityGroupDBTestCase):
+ _plugin_name = PLUGIN_NAME
+
+ def setUp(self, plugin=None):
+ self.addCleanup(mock.patch.stopall)
+ notifier_p = mock.patch(NOTIFIER)
+ notifier_cls = notifier_p.start()
+ self.notifier = mock.Mock()
+ notifier_cls.return_value = self.notifier
+ self._attribute_map_bk_ = {}
+ for item in attributes.RESOURCE_ATTRIBUTE_MAP:
+ self._attribute_map_bk_[item] = (attributes.
+ RESOURCE_ATTRIBUTE_MAP[item].
+ copy())
+ super(OpenvswitchSecurityGroupsTestCase, self).setUp(PLUGIN_NAME)
+
+ def tearDown(self):
+ super(OpenvswitchSecurityGroupsTestCase, self).tearDown()
+ attributes.RESOURCE_ATTRIBUTE_MAP = self._attribute_map_bk_
+
+
+class TestOpenvswitchSecurityGroups(OpenvswitchSecurityGroupsTestCase,
+ test_sg.TestSecurityGroups,
+ test_sg_rpc.SGNotificationTestMixin):
+ def test_security_group_get_port_from_device(self):
+ with self.network() as n:
+ with self.subnet(n):
+ with self.security_group() as sg:
+ security_group_id = sg['security_group']['id']
+ res = self._create_port(self.fmt, n['network']['id'])
+ port = self.deserialize(self.fmt, res)
+ fixed_ips = port['port']['fixed_ips']
+ data = {'port': {'fixed_ips': fixed_ips,
+ 'name': port['port']['name'],
+ ext_sg.SECURITYGROUPS:
+ [security_group_id]}}
+
+ req = self.new_update_request('ports', data,
+ port['port']['id'])
+ res = self.deserialize(self.fmt,
+ req.get_response(self.api))
+ port_id = res['port']['id']
+ plugin = manager.QuantumManager.get_plugin()
+ port_dict = plugin.callbacks.get_port_from_device(port_id)
+ self.assertEqual(port_id, port_dict['id'])
+ self.assertEqual([security_group_id],
+ port_dict[ext_sg.SECURITYGROUPS])
+ self.assertEqual([], port_dict['security_group_rules'])
+ self.assertEqual([fixed_ips[0]['ip_address']],
+ port_dict['fixed_ips'])
+ self._delete('ports', port_id)
+
+ def test_security_group_get_port_from_device_with_no_port(self):
+ plugin = manager.QuantumManager.get_plugin()
+ port_dict = plugin.callbacks.get_port_from_device('bad_device_id')
+ self.assertEqual(None, port_dict)
+
+
+class TestOpenvswitchSecurityGroupsXML(TestOpenvswitchSecurityGroups):
+ fmt = 'xml'
self.iptables_inst.ipv6 = {'filter': self.v6filter_inst}
iptables_cls.return_value = self.iptables_inst
- self.firewall = IptablesFirewallDriver(self.iptables_inst)
+ self.firewall = IptablesFirewallDriver()
+ self.firewall.iptables = self.iptables_inst
def tearDown(self):
self.iptables_cls_p.stop()
from quantum.agent import securitygroups_rpc as sg_rpc
from quantum import context
from quantum.db import securitygroups_rpc_base as sg_db_rpc
+from quantum.extensions import securitygroup as ext_sg
+from quantum.openstack.common import cfg
from quantum.openstack.common.rpc import proxy
from quantum.tests.unit import test_extension_security_group as test_sg
from quantum.tests.unit import test_iptables_firewall as test_fw
class SGAgentRpcCallBackMixinTestCase(unittest.TestCase):
def setUp(self):
self.rpc = sg_rpc.SecurityGroupAgentRpcCallbackMixin()
- self.rpc.agent = mock.Mock()
+ self.rpc.sg_agent = mock.Mock()
def test_security_groups_rule_updated(self):
self.rpc.security_groups_rule_updated(None,
security_groups=['fake_sgid'])
- self.rpc.agent.assert_has_calls(
+ self.rpc.sg_agent.assert_has_calls(
[call.security_groups_rule_updated(['fake_sgid'])])
def test_security_groups_member_updated(self):
self.rpc.security_groups_member_updated(None,
security_groups=['fake_sgid'])
- self.rpc.agent.assert_has_calls(
+ self.rpc.sg_agent.assert_has_calls(
[call.security_groups_member_updated(['fake_sgid'])])
def test_security_groups_provider_updated(self):
self.rpc.security_groups_provider_updated(None)
- self.rpc.agent.assert_has_calls(
+ self.rpc.sg_agent.assert_has_calls(
[call.security_groups_provider_updated()])
-A OUTPUT -j %(bn)s-OUTPUT
-A FORWARD -j %(bn)s-FORWARD
-A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port1 -j %(bn)s-i_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
-A %(bn)s-i_port1 -m state --state INVALID -j DROP
-A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port1 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
-A %(bn)s-i_port1 -j RETURN -p tcp --dport 22
-A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
-A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
-A %(bn)s-o_port1 -p udp --sport 68 --dport 67 -j RETURN
-A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
-A OUTPUT -j %(bn)s-OUTPUT
-A FORWARD -j %(bn)s-FORWARD
-A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port1 -j %(bn)s-i_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
-A %(bn)s-i_port1 -m state --state INVALID -j DROP
-A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port1 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
-A %(bn)s-i_port1 -j RETURN -p tcp --dport 22
-A %(bn)s-i_port1 -j RETURN -s 10.0.0.4
-A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
-A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
-A %(bn)s-o_port1 -p udp --sport 68 --dport 67 -j RETURN
-A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
-A OUTPUT -j %(bn)s-OUTPUT
-A FORWARD -j %(bn)s-FORWARD
-A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port1 -j %(bn)s-i_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
-A %(bn)s-i_port1 -m state --state INVALID -j DROP
-A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port1 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
-A %(bn)s-i_port1 -j RETURN -p tcp --dport 22
-A %(bn)s-i_port1 -j RETURN -s 10.0.0.4
-A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
-A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
-A %(bn)s-o_port1 -p udp --sport 68 --dport 67 -j RETURN
-A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
-A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-o_port1 -j RETURN
-A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port2 -j %(bn)s-i_port2
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-i_port2
-A %(bn)s-i_port2 -m state --state INVALID -j DROP
-A %(bn)s-i_port2 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port2 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
-A %(bn)s-i_port2 -j RETURN -p tcp --dport 22
-A %(bn)s-i_port2 -j RETURN -s 10.0.0.3
-A %(bn)s-i_port2 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port2 -j %(bn)s-o_port2
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port2 -j %(bn)s-o_port2
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
-A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
-A %(bn)s-o_port2 -p udp --sport 68 --dport 67 -j RETURN
-A %(bn)s-o_port2 ! -s 10.0.0.4 -j DROP
-A OUTPUT -j %(bn)s-OUTPUT
-A FORWARD -j %(bn)s-FORWARD
-A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port1 -j %(bn)s-i_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
-A %(bn)s-i_port1 -m state --state INVALID -j DROP
-A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port1 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
-A %(bn)s-i_port1 -j RETURN -p tcp --dport 22
-A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
-A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
-A %(bn)s-o_port1 -p udp --sport 68 --dport 67 -j RETURN
-A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
-A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-o_port1 -j RETURN
-A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port2 -j %(bn)s-i_port2
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-i_port2
-A %(bn)s-i_port2 -m state --state INVALID -j DROP
-A %(bn)s-i_port2 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port2 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
-A %(bn)s-i_port2 -j RETURN -p tcp --dport 22
-A %(bn)s-i_port2 -j RETURN -s 10.0.0.3
-A %(bn)s-i_port2 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port2 -j %(bn)s-o_port2
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port2 -j %(bn)s-o_port2
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
-A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
-A %(bn)s-o_port2 -p udp --sport 68 --dport 67 -j RETURN
-A %(bn)s-o_port2 ! -s 10.0.0.4 -j DROP
-A OUTPUT -j %(bn)s-OUTPUT
-A FORWARD -j %(bn)s-FORWARD
-A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port1 -j %(bn)s-i_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
-A %(bn)s-i_port1 -m state --state INVALID -j DROP
-A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port1 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
-A %(bn)s-i_port1 -j RETURN -s 10.0.0.4
-A %(bn)s-i_port1 -j RETURN -p icmp
-A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
-A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
-A %(bn)s-o_port1 -p udp --sport 68 --dport 67 -j RETURN
-A %(bn)s-o_port1 ! -s 10.0.0.3 -j DROP
-A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-o_port1 -j RETURN
-A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port2 -j %(bn)s-i_port2
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-i_port2
-A %(bn)s-i_port2 -m state --state INVALID -j DROP
-A %(bn)s-i_port2 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port2 -j RETURN -p udp --dport 68 --sport 67 -s 10.0.0.2
-A %(bn)s-i_port2 -j RETURN -s 10.0.0.3
-A %(bn)s-i_port2 -j RETURN -p icmp
-A %(bn)s-i_port2 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port2 -j %(bn)s-o_port2
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port2 -j %(bn)s-o_port2
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
-A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
-A %(bn)s-o_port2 -p udp --sport 68 --dport 67 -j RETURN
-A %(bn)s-o_port2 ! -s 10.0.0.4 -j DROP
-A OUTPUT -j %(bn)s-OUTPUT
-A FORWARD -j %(bn)s-FORWARD
-A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port1 -j %(bn)s-i_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
-A %(bn)s-i_port1 -m state --state INVALID -j DROP
-A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
-A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
-A %(bn)s-o_port1 -p icmpv6 -j RETURN
-A %(bn)s-o_port1 -m state --state INVALID -j DROP
-A OUTPUT -j %(bn)s-OUTPUT
-A FORWARD -j %(bn)s-FORWARD
-A %(bn)s-sg-fallback -j DROP
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port1 -j %(bn)s-i_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port1 -j %(bn)s-i_port1
-A %(bn)s-i_port1 -m state --state INVALID -j DROP
-A %(bn)s-i_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port1 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port1 -j %(bn)s-o_port1
-A %(bn)s-o_port1 -m mac ! --mac-source 12:34:56:78:9a:bc -j DROP
-A %(bn)s-o_port1 -p icmpv6 -j RETURN
-A %(bn)s-o_port1 -m state --state INVALID -j DROP
-A %(bn)s-o_port1 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-o_port1 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-out tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-out tap_port2 -j %(bn)s-i_port2
+-A %(bn)s-FORWARD %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-INGRESS tap_port2 -j %(bn)s-i_port2
-A %(bn)s-i_port2 -m state --state INVALID -j DROP
-A %(bn)s-i_port2 -m state --state ESTABLISHED,RELATED -j RETURN
-A %(bn)s-i_port2 -j %(bn)s-sg-fallback
--A %(bn)s-FORWARD %(physdev)s --physdev-in tap_port2 -j %(bn)s-sg-chain
--A %(bn)s-sg-chain %(physdev)s --physdev-in tap_port2 -j %(bn)s-o_port2
--A %(bn)s-INPUT %(physdev)s --physdev-in tap_port2 -j %(bn)s-o_port2
+-A %(bn)s-FORWARD %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-sg-chain
+-A %(bn)s-sg-chain %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
+-A %(bn)s-INPUT %(physdev)s --physdev-EGRESS tap_port2 -j %(bn)s-o_port2
-A %(bn)s-o_port2 -m mac ! --mac-source 12:34:56:78:9a:bd -j DROP
-A %(bn)s-o_port2 -p icmpv6 -j RETURN
-A %(bn)s-o_port2 -m state --state INVALID -j DROP
-A %(bn)s-sg-fallback -j DROP
""" % IPTABLES_ARG
+FIREWALL_BASE_PACKAGE = 'quantum.agent.linux.iptables_firewall.'
+
class TestSecurityGroupAgentWithIptables(unittest.TestCase):
+ FIREWALL_DRIVER = FIREWALL_BASE_PACKAGE + 'IptablesFirewallDriver'
+ PHYSDEV_INGRESS = 'physdev-out'
+ PHYSDEV_EGRESS = 'physdev-in'
+
def setUp(self):
self.mox = mox.Mox()
-
+ agent_opts = [
+ cfg.StrOpt('root_helper', default='sudo'),
+ ]
+
+ cfg.CONF.register_opts(agent_opts, "AGENT")
+ cfg.CONF.set_override(
+ 'firewall_driver',
+ self.FIREWALL_DRIVER,
+ group='SECURITYGROUP')
self.addCleanup(mock.patch.stopall)
self.addCleanup(self.mox.UnsetStubs)
'security_group1']}
def _regex(self, value):
+ value = value.replace('physdev-INGRESS', self.PHYSDEV_INGRESS)
+ value = value.replace('physdev-EGRESS', self.PHYSDEV_EGRESS)
value = value.replace('\n', '\\n')
value = value.replace('[', '\[')
value = value.replace(']', '\]')
self.agent.security_groups_rule_updated(['security_group1'])
self.mox.VerifyAll()
+
+
+class SGNotificationTestMixin():
+ def test_security_group_rule_updated(self):
+ name = 'webservers'
+ description = 'my webservers'
+ with self.security_group(name, description) as sg:
+ with self.security_group(name, description) as sg2:
+ security_group_id = sg['security_group']['id']
+ direction = "ingress"
+ source_group_id = sg2['security_group']['id']
+ protocol = 'tcp'
+ port_range_min = 88
+ port_range_max = 88
+ with self.security_group_rule(security_group_id, direction,
+ protocol, port_range_min,
+ port_range_max,
+ source_group_id=source_group_id
+ ):
+ pass
+ self.notifier.assert_has_calls(
+ [call.security_groups_rule_updated(mock.ANY,
+ [security_group_id]),
+ call.security_groups_rule_updated(mock.ANY,
+ [security_group_id])])
+
+ def test_security_group_member_updated(self):
+ with self.network() as n:
+ with self.subnet(n):
+ with self.security_group() as sg:
+ security_group_id = sg['security_group']['id']
+ res = self._create_port(self.fmt, n['network']['id'])
+ port = self.deserialize(self.fmt, res)
+
+ data = {'port': {'fixed_ips': port['port']['fixed_ips'],
+ 'name': port['port']['name'],
+ ext_sg.SECURITYGROUPS:
+ [security_group_id]}}
+
+ req = self.new_update_request('ports', data,
+ port['port']['id'])
+ res = self.deserialize(self.fmt,
+ req.get_response(self.api))
+ self.assertEquals(res['port'][ext_sg.SECURITYGROUPS][0],
+ security_group_id)
+ self._delete('ports', port['port']['id'])
+ self.notifier.assert_has_calls(
+ [call.security_groups_member_updated(
+ mock.ANY, [mock.ANY]),
+ call.security_groups_member_updated(
+ mock.ANY, [security_group_id])])
+
+
+class TestSecurityGroupAgentWithOVSIptables(
+ TestSecurityGroupAgentWithIptables):
+
+ FIREWALL_DRIVER = FIREWALL_BASE_PACKAGE + 'OVSHybridIptablesFirewallDriver'
+
+ def _regex(self, value):
+ #Note(nati): tap is prefixed on the device
+ # in the OVSHybridIptablesFirewallDriver
+
+ value = value.replace('tap_port', 'taptap_port')
+ value = value.replace('o_port', 'otap_port')
+ value = value.replace('i_port', 'itap_port')
+ return super(
+ TestSecurityGroupAgentWithOVSIptables,
+ self)._regex(value)