remove unnecessary neutron files under neutron/services/

Change-Id: I795afc55b72306507ec6717838150fc2fed7a15d
changes/11/104811/1
Isaku Yamahata 9 years ago
parent b5607354c0
commit 872cab4426

@ -1,16 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 OpenStack Foundation.
# 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.

@ -1,16 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 OpenStack Foundation.
# 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.

@ -1,85 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2013 OpenStack Foundation
# 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.
#
# @author: Sumit Naiksatam, sumitnaiksatam@gmail.com, Big Switch Networks, Inc.
# @author: Sridar Kandaswamy, skandasw@cisco.com, Cisco Systems, Inc.
# @author: Dan Florea, dflorea@cisco.com, Cisco Systems, Inc.
from oslo.config import cfg
from neutron.common import rpc_compat
from neutron.openstack.common import log as logging
LOG = logging.getLogger(__name__)
FWaaSOpts = [
cfg.StrOpt(
'driver',
default='',
help=_("Name of the FWaaS Driver")),
cfg.BoolOpt(
'enabled',
default=False,
help=_("Enable FWaaS")),
]
cfg.CONF.register_opts(FWaaSOpts, 'fwaas')
class FWaaSPluginApiMixin(rpc_compat.RpcProxy):
"""Agent side of the FWaaS agent to FWaaS Plugin RPC API."""
RPC_API_VERSION = '1.0'
def __init__(self, topic, host):
super(FWaaSPluginApiMixin,
self).__init__(topic=topic,
default_version=self.RPC_API_VERSION)
self.host = host
def set_firewall_status(self, context, firewall_id, status):
"""Make a RPC to set the status of a firewall."""
return self.call(context,
self.make_msg('set_firewall_status', host=self.host,
firewall_id=firewall_id, status=status),
topic=self.topic)
def firewall_deleted(self, context, firewall_id):
"""Make a RPC to indicate that the firewall resources are deleted."""
return self.call(context,
self.make_msg('firewall_deleted', host=self.host,
firewall_id=firewall_id),
topic=self.topic)
class FWaaSAgentRpcCallbackMixin(object):
"""Mixin for FWaaS agent Implementations."""
def __init__(self, host):
super(FWaaSAgentRpcCallbackMixin, self).__init__(host)
def create_firewall(self, context, firewall, host):
"""Handle RPC cast from plugin to create a firewall."""
pass
def update_firewall(self, context, firewall, host):
"""Handle RPC cast from plugin to update a firewall."""
pass
def delete_firewall(self, context, firewall, host):
"""Handle RPC cast from plugin to delete a firewall."""
pass

@ -1,16 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 OpenStack Foundation.
# 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.

@ -1,295 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2013 OpenStack Foundation.
# 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.
#
# @author: Sumit Naiksatam, sumitnaiksatam@gmail.com, Big Switch Networks, Inc.
# @author: Sridar Kandaswamy, skandasw@cisco.com, Cisco Systems, Inc.
# @author: Dan Florea, dflorea@cisco.com, Cisco Systems, Inc.
from oslo.config import cfg
from neutron.agent.common import config
from neutron.agent.linux import ip_lib
from neutron.common import topics
from neutron import context
from neutron.extensions import firewall as fw_ext
from neutron.openstack.common import importutils
from neutron.openstack.common import log as logging
from neutron.plugins.common import constants
from neutron.services.firewall.agents import firewall_agent_api as api
LOG = logging.getLogger(__name__)
class FWaaSL3PluginApi(api.FWaaSPluginApiMixin):
"""Agent side of the FWaaS agent to FWaaS Plugin RPC API."""
def __init__(self, topic, host):
super(FWaaSL3PluginApi, self).__init__(topic, host)
def get_firewalls_for_tenant(self, context, **kwargs):
"""Get the Firewalls with rules from the Plugin to send to driver."""
LOG.debug(_("Retrieve Firewall with rules from Plugin"))
return self.call(context,
self.make_msg('get_firewalls_for_tenant',
host=self.host),
topic=self.topic)
def get_tenants_with_firewalls(self, context, **kwargs):
"""Get all Tenants that have Firewalls configured from plugin."""
LOG.debug(_("Retrieve Tenants with Firewalls configured from Plugin"))
return self.call(context,
self.make_msg('get_tenants_with_firewalls',
host=self.host),
topic=self.topic)
class FWaaSL3AgentRpcCallback(api.FWaaSAgentRpcCallbackMixin):
"""FWaaS Agent support to be used by Neutron L3 agent."""
def __init__(self, conf):
LOG.debug(_("Initializing firewall agent"))
self.conf = conf
fwaas_driver_class_path = cfg.CONF.fwaas.driver
self.fwaas_enabled = cfg.CONF.fwaas.enabled
if self.fwaas_enabled:
try:
self.fwaas_driver = importutils.import_object(
fwaas_driver_class_path)
LOG.debug(_("FWaaS Driver Loaded: '%s'"),
fwaas_driver_class_path)
except ImportError:
msg = _('Error importing FWaaS device driver: %s')
raise ImportError(msg % fwaas_driver_class_path)
self.services_sync = False
self.root_helper = config.get_root_helper(conf)
# setup RPC to msg fwaas plugin
self.fwplugin_rpc = FWaaSL3PluginApi(topics.FIREWALL_PLUGIN,
conf.host)
super(FWaaSL3AgentRpcCallback, self).__init__(host=conf.host)
def _get_router_info_list_for_tenant(self, routers, tenant_id):
"""Returns the list of router info objects on which to apply the fw."""
root_ip = ip_lib.IPWrapper(self.root_helper)
# Get the routers for the tenant
router_ids = [
router['id']
for router in routers
if router['tenant_id'] == tenant_id]
local_ns_list = root_ip.get_namespaces(
self.root_helper) if self.conf.use_namespaces else []
router_info_list = []
# Pick up namespaces for Tenant Routers
for rid in router_ids:
# for routers without an interface - get_routers returns
# the router - but this is not yet populated in router_info
if rid not in self.router_info:
continue
if self.router_info[rid].use_namespaces:
router_ns = self.router_info[rid].ns_name
if router_ns in local_ns_list:
router_info_list.append(self.router_info[rid])
else:
router_info_list.append(self.router_info[rid])
return router_info_list
def _invoke_driver_for_plugin_api(self, context, fw, func_name):
"""Invoke driver method for plugin API and provide status back."""
LOG.debug(_("%(func_name)s from agent for fw: %(fwid)s"),
{'func_name': func_name, 'fwid': fw['id']})
try:
routers = self.plugin_rpc.get_routers(context)
router_info_list = self._get_router_info_list_for_tenant(
routers,
fw['tenant_id'])
if not router_info_list:
LOG.debug(_('No Routers on tenant: %s'), fw['tenant_id'])
# fw was created before any routers were added, and if a
# delete is sent then we need to ack so that plugin can
# cleanup.
if func_name == 'delete_firewall':
self.fwplugin_rpc.firewall_deleted(context, fw['id'])
return
LOG.debug(_("Apply fw on Router List: '%s'"),
[ri.router['id'] for ri in router_info_list])
# call into the driver
try:
self.fwaas_driver.__getattribute__(func_name)(
router_info_list,
fw)
if fw['admin_state_up']:
status = constants.ACTIVE
else:
status = constants.DOWN
except fw_ext.FirewallInternalDriverError:
LOG.error(_("Firewall Driver Error for %(func_name)s "
"for fw: %(fwid)s"),
{'func_name': func_name, 'fwid': fw['id']})
status = constants.ERROR
# delete needs different handling
if func_name == 'delete_firewall':
if status in [constants.ACTIVE, constants.DOWN]:
self.fwplugin_rpc.firewall_deleted(context, fw['id'])
else:
self.fwplugin_rpc.set_firewall_status(
context,
fw['id'],
status)
except Exception:
LOG.exception(
_("FWaaS RPC failure in %(func_name)s for fw: %(fwid)s"),
{'func_name': func_name, 'fwid': fw['id']})
self.services_sync = True
return
def _invoke_driver_for_sync_from_plugin(self, ctx, router_info_list, fw):
"""Invoke the delete driver method for status of PENDING_DELETE and
update method for all other status to (re)apply on driver which is
Idempotent.
"""
if fw['status'] == constants.PENDING_DELETE:
try:
self.fwaas_driver.delete_firewall(router_info_list, fw)
self.fwplugin_rpc.firewall_deleted(
ctx,
fw['id'])
except fw_ext.FirewallInternalDriverError:
LOG.error(_("Firewall Driver Error on fw state %(fwmsg)s "
"for fw: %(fwid)s"),
{'fwmsg': fw['status'], 'fwid': fw['id']})
self.fwplugin_rpc.set_firewall_status(
ctx,
fw['id'],
constants.ERROR)
else:
# PENDING_UPDATE, PENDING_CREATE, ...
try:
self.fwaas_driver.update_firewall(router_info_list, fw)
if fw['admin_state_up']:
status = constants.ACTIVE
else:
status = constants.DOWN
except fw_ext.FirewallInternalDriverError:
LOG.error(_("Firewall Driver Error on fw state %(fwmsg)s "
"for fw: %(fwid)s"),
{'fwmsg': fw['status'], 'fwid': fw['id']})
status = constants.ERROR
self.fwplugin_rpc.set_firewall_status(
ctx,
fw['id'],
status)
def _process_router_add(self, ri):
"""On router add, get fw with rules from plugin and update driver."""
LOG.debug(_("Process router add, router_id: '%s'"), ri.router['id'])
routers = []
routers.append(ri.router)
router_info_list = self._get_router_info_list_for_tenant(
routers,
ri.router['tenant_id'])
if router_info_list:
# Get the firewall with rules
# for the tenant the router is on.
ctx = context.Context('', ri.router['tenant_id'])
fw_list = self.fwplugin_rpc.get_firewalls_for_tenant(ctx)
LOG.debug(_("Process router add, fw_list: '%s'"),
[fw['id'] for fw in fw_list])
for fw in fw_list:
self._invoke_driver_for_sync_from_plugin(
ctx,
router_info_list,
fw)
def process_router_add(self, ri):
"""On router add, get fw with rules from plugin and update driver."""
# avoid msg to plugin when fwaas is not configured
if not self.fwaas_enabled:
return
try:
self._process_router_add(ri)
except Exception:
LOG.exception(
_("FWaaS RPC info call failed for '%s'."),
ri.router['id'])
self.services_sync = True
def process_services_sync(self, ctx):
"""On RPC issues sync with plugin and apply the sync data."""
# avoid msg to plugin when fwaas is not configured
if not self.fwaas_enabled:
return
try:
# get all routers
routers = self.plugin_rpc.get_routers(ctx)
# get the list of tenants with firewalls configured
# from the plugin
tenant_ids = self.fwplugin_rpc.get_tenants_with_firewalls(ctx)
LOG.debug(_("Tenants with Firewalls: '%s'"), tenant_ids)
for tenant_id in tenant_ids:
ctx = context.Context('', tenant_id)
fw_list = self.fwplugin_rpc.get_firewalls_for_tenant(ctx)
if fw_list:
# if fw present on tenant
router_info_list = self._get_router_info_list_for_tenant(
routers,
tenant_id)
if router_info_list:
LOG.debug(_("Router List: '%s'"),
[ri.router['id'] for ri in router_info_list])
LOG.debug(_("fw_list: '%s'"),
[fw['id'] for fw in fw_list])
# apply sync data on fw for this tenant
for fw in fw_list:
# fw, routers present on this host for tenant
# install
LOG.debug(_("Apply fw on Router List: '%s'"),
[ri.router['id']
for ri in router_info_list])
# no need to apply sync data for ACTIVE fw
if fw['status'] != constants.ACTIVE:
self._invoke_driver_for_sync_from_plugin(
ctx,
router_info_list,
fw)
self.services_sync = False
except Exception:
LOG.exception(_("Failed fwaas process services sync"))
self.services_sync = True
def create_firewall(self, context, firewall, host):
"""Handle Rpc from plugin to create a firewall."""
return self._invoke_driver_for_plugin_api(
context,
firewall,
'create_firewall')
def update_firewall(self, context, firewall, host):
"""Handle Rpc from plugin to update a firewall."""
return self._invoke_driver_for_plugin_api(
context,
firewall,
'update_firewall')
def delete_firewall(self, context, firewall, host):
"""Handle Rpc from plugin to delete a firewall."""
return self._invoke_driver_for_plugin_api(
context,
firewall,
'delete_firewall')

@ -1,16 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 OpenStack Foundation.
# 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.

@ -1,147 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2013 vArmour Networks 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.
#
# @author: Gary Duan, gduan@varmour.com, vArmour Networks
import base64
import httplib2
from oslo.config import cfg
from neutron.openstack.common import jsonutils as json
from neutron.openstack.common import log as logging
from neutron.services.firewall.agents.varmour import varmour_utils as va_utils
OPTS = [
cfg.StrOpt('director', default='localhost',
help=_("vArmour director ip")),
cfg.StrOpt('director_port', default='443',
help=_("vArmour director port")),
cfg.StrOpt('username', default='varmour',
help=_("vArmour director username")),
cfg.StrOpt('password', default='varmour', secret=True,
help=_("vArmour director password")), ]
cfg.CONF.register_opts(OPTS, "vArmour")
LOG = logging.getLogger(__name__)
REST_URL_PREFIX = '/api/v1.0'
class vArmourAPIException(Exception):
message = _("An unknown exception.")
def __init__(self, **kwargs):
try:
self.err = self.message % kwargs
except Exception:
self.err = self.message
def __str__(self):
return self.err
class AuthenticationFailure(vArmourAPIException):
message = _("Invalid login credential.")
class vArmourRestAPI(object):
def __init__(self):
LOG.debug(_('vArmourRestAPI: started'))
self.user = cfg.CONF.vArmour.username
self.passwd = cfg.CONF.vArmour.password
self.server = cfg.CONF.vArmour.director
self.port = cfg.CONF.vArmour.director_port
self.timeout = 3
self.key = ''
def auth(self):
headers = {}
enc = base64.b64encode(self.user + ':' + self.passwd)
headers['Authorization'] = 'Basic ' + enc
resp = self.rest_api('POST', va_utils.REST_URL_AUTH, None, headers)
if resp and resp['status'] == 200:
self.key = resp['body']['auth']
return True
else:
raise AuthenticationFailure()
def commit(self):
self.rest_api('POST', va_utils.REST_URL_COMMIT)
def rest_api(self, method, url, body=None, headers=None):
url = REST_URL_PREFIX + url
if body:
body_data = json.dumps(body)
else:
body_data = ''
if not headers:
headers = {}
enc = base64.b64encode('%s:%s' % (self.user, self.key))
headers['Authorization'] = 'Basic ' + enc
LOG.debug(_("vArmourRestAPI: %(server)s %(port)s"),
{'server': self.server, 'port': self.port})
try:
action = "https://" + self.server + ":" + self.port + url
LOG.debug(_("vArmourRestAPI Sending: "
"%(method)s %(action)s %(headers)s %(body_data)s"),
{'method': method, 'action': action,
'headers': headers, 'body_data': body_data})
h = httplib2.Http(timeout=3,
disable_ssl_certificate_validation=True)
resp, resp_str = h.request(action, method,
body=body_data,
headers=headers)
LOG.debug(_("vArmourRestAPI Response: %(status)s %(resp_str)s"),
{'status': resp.status, 'resp_str': resp_str})
if resp.status == 200:
return {'status': resp.status,
'reason': resp.reason,
'body': json.loads(resp_str)}
except Exception:
LOG.error(_('vArmourRestAPI: Could not establish HTTP connection'))
def del_cfg_objs(self, url, prefix):
resp = self.rest_api('GET', url)
if resp and resp['status'] == 200:
olist = resp['body']['response']
if not olist:
return
for o in olist:
if o.startswith(prefix):
self.rest_api('DELETE', url + '/"name:%s"' % o)
self.commit()
def count_cfg_objs(self, url, prefix):
count = 0
resp = self.rest_api('GET', url)
if resp and resp['status'] == 200:
for o in resp['body']['response']:
if o.startswith(prefix):
count += 1
return count

@ -1,351 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2013 vArmour Networks 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.
#
# @author: Gary Duan, vArmour Networks Inc.
#
import sys
import eventlet
eventlet.monkey_patch()
import netaddr
from oslo.config import cfg
from neutron.agent.common import config
from neutron.agent import l3_agent
from neutron.agent.linux import external_process
from neutron.agent.linux import interface
from neutron.agent.linux import ip_lib
from neutron.common import config as common_config
from neutron.common import constants as l3_constants
from neutron.common import topics
from neutron.openstack.common import log as logging
from neutron.openstack.common import service
from neutron import service as neutron_service
from neutron.services.firewall.agents.l3reference import firewall_l3_agent
from neutron.services.firewall.agents.varmour import varmour_api
from neutron.services.firewall.agents.varmour import varmour_utils as va_utils
LOG = logging.getLogger(__name__)
class vArmourL3NATAgent(l3_agent.L3NATAgent,
firewall_l3_agent.FWaaSL3AgentRpcCallback):
def __init__(self, host, conf=None):
LOG.debug(_('vArmourL3NATAgent: __init__'))
self.rest = varmour_api.vArmourRestAPI()
super(vArmourL3NATAgent, self).__init__(host, conf)
def _destroy_router_namespaces(self, only_router_id=None):
return
def _destroy_router_namespace(self, namespace):
return
def _create_router_namespace(self, ri):
return
def _router_added(self, router_id, router):
LOG.debug(_("_router_added: %s"), router_id)
ri = l3_agent.RouterInfo(router_id, self.root_helper,
self.conf.use_namespaces, router)
self.router_info[router_id] = ri
super(vArmourL3NATAgent, self).process_router_add(ri)
def _router_removed(self, router_id):
LOG.debug(_("_router_removed: %s"), router_id)
ri = self.router_info[router_id]
if ri:
ri.router['gw_port'] = None
ri.router[l3_constants.INTERFACE_KEY] = []
ri.router[l3_constants.FLOATINGIP_KEY] = []
self.process_router(ri)
name = va_utils.get_snat_rule_name(ri)
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_NAT_RULE, name)
name = va_utils.get_dnat_rule_name(ri)
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_NAT_RULE, name)
name = va_utils.get_trusted_zone_name(ri)
self._va_unset_zone_interfaces(name, True)
name = va_utils.get_untrusted_zone_name(ri)
self._va_unset_zone_interfaces(name, True)
del self.router_info[router_id]
def _spawn_metadata_proxy(self, router_id, ns_name):
return
def _destroy_metadata_proxy(self, router_id, ns_name):
return
def _set_subnet_info(self, port):
ips = port['fixed_ips']
if not ips:
raise Exception(_("Router port %s has no IP address") % port['id'])
return
if len(ips) > 1:
LOG.warn(_("Ignoring multiple IPs on router port %s"), port['id'])
prefixlen = netaddr.IPNetwork(port['subnet']['cidr']).prefixlen
port['ip_cidr'] = "%s/%s" % (ips[0]['ip_address'], prefixlen)
def _va_unset_zone_interfaces(self, zone_name, remove_zone=False):
# return True if zone exists; otherwise, return False
LOG.debug(_("_va_unset_zone_interfaces: %s"), zone_name)
resp = self.rest.rest_api('GET', va_utils.REST_URL_CONF_ZONE)
if resp and resp['status'] == 200:
zlist = resp['body']['response']
for zn in zlist:
if zn == zone_name:
commit = False
if 'interface' in zlist[zn]:
for intf in zlist[zn]['interface']:
self.rest.rest_api('DELETE',
va_utils.REST_URL_CONF +
va_utils.REST_ZONE_NAME % zn +
va_utils.REST_INTF_NAME % intf)
commit = True
if remove_zone:
self.rest.rest_api('DELETE',
va_utils.REST_URL_CONF +
va_utils.REST_ZONE_NAME % zn)
commit = True
if commit:
self.rest.commit()
return True
return False
def _va_pif_2_lif(self, pif):
return pif + '.0'
def _va_set_interface_ip(self, pif, cidr):
LOG.debug(_("_va_set_interface_ip: %(pif)s %(cidr)s"),
{'pif': pif, 'cidr': cidr})
lif = self._va_pif_2_lif(pif)
obj = va_utils.REST_INTF_NAME % pif + va_utils.REST_LOGIC_NAME % lif
body = {
'name': lif,
'family': 'ipv4',
'address': cidr
}
self.rest.rest_api('PUT', va_utils.REST_URL_CONF + obj, body)
def _va_get_port_name(self, port_list, name):
if name:
for p in port_list:
if p['VM name'] == name:
return p['name']
def _va_config_trusted_zone(self, ri, plist):
zone = va_utils.get_trusted_zone_name(ri)
LOG.debug(_("_va_config_trusted_zone: %s"), zone)
body = {
'name': zone,
'type': 'L3',
'interface': []
}
if not self._va_unset_zone_interfaces(zone):
# if zone doesn't exist, create it
self.rest.rest_api('POST', va_utils.REST_URL_CONF_ZONE, body)
self.rest.commit()
# add new internal ports to trusted zone
for p in ri.internal_ports:
if p['admin_state_up']:
dev = self.get_internal_device_name(p['id'])
pif = self._va_get_port_name(plist, dev)
if pif:
lif = self._va_pif_2_lif(pif)
if lif not in body['interface']:
body['interface'].append(lif)
self._va_set_interface_ip(pif, p['ip_cidr'])
if body['interface']:
self.rest.rest_api('PUT', va_utils.REST_URL_CONF_ZONE, body)
self.rest.commit()
def _va_config_untrusted_zone(self, ri, plist):
zone = va_utils.get_untrusted_zone_name(ri)
LOG.debug(_("_va_config_untrusted_zone: %s"), zone)
body = {
'name': zone,
'type': 'L3',
'interface': []
}
if not self._va_unset_zone_interfaces(zone):
# if zone doesn't exist, create it
self.rest.rest_api('POST', va_utils.REST_URL_CONF_ZONE, body)
self.rest.commit()
# add new gateway ports to untrusted zone
if ri.ex_gw_port:
LOG.debug(_("_va_config_untrusted_zone: gw=%r"), ri.ex_gw_port)
dev = self.get_external_device_name(ri.ex_gw_port['id'])
pif = self._va_get_port_name(plist, dev)
if pif:
lif = self._va_pif_2_lif(pif)
self._va_set_interface_ip(pif, ri.ex_gw_port['ip_cidr'])
body['interface'].append(lif)
self.rest.rest_api('PUT', va_utils.REST_URL_CONF_ZONE, body)
self.rest.commit()
def _va_config_router_snat_rules(self, ri, plist):
LOG.debug(_('_va_config_router_snat_rules: %s'), ri.router['id'])
prefix = va_utils.get_snat_rule_name(ri)
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_NAT_RULE, prefix)
if not ri.enable_snat:
return
for idx, p in enumerate(ri.internal_ports):
if p['admin_state_up']:
dev = self.get_internal_device_name(p['id'])
pif = self._va_get_port_name(plist, dev)
if pif:
net = netaddr.IPNetwork(p['ip_cidr'])
body = {
'name': '%s_%d' % (prefix, idx),
'ingress-context-type': 'interface',
'ingress-index': self._va_pif_2_lif(pif),
'source-address': [
[str(netaddr.IPAddress(net.first + 2)),
str(netaddr.IPAddress(net.last - 1))]
],
'flag': 'interface translate-source'
}
self.rest.rest_api('POST',
va_utils.REST_URL_CONF_NAT_RULE,
body)
if ri.internal_ports:
self.rest.commit()
def _va_config_floating_ips(self, ri):
LOG.debug(_('_va_config_floating_ips: %s'), ri.router['id'])
prefix = va_utils.get_dnat_rule_name(ri)
self.rest.del_cfg_objs(va_utils.REST_URL_CONF_NAT_RULE, prefix)
# add new dnat rules
for idx, fip in enumerate(ri.floating_ips):
body = {
'name': '%s_%d' % (prefix, idx),
'ingress-context-type': 'zone',
'ingress-index': va_utils.get_untrusted_zone_name(ri),
'destination-address': [[fip['floating_ip_address'],
fip['floating_ip_address']]],
'static': [fip['fixed_ip_address'], fip['fixed_ip_address']],
'flag': 'translate-destination'
}
self.rest.rest_api('POST', va_utils.REST_URL_CONF_NAT_RULE, body)
if ri.floating_ips:
self.rest.commit()
def process_router(self, ri):
LOG.debug(_("process_router: %s"), ri.router['id'])
super(vArmourL3NATAgent, self).process_router(ri)
self.rest.auth()
# read internal port name and configuration port name map
resp = self.rest.rest_api('GET', va_utils.REST_URL_INTF_MAP)
if resp and resp['status'] == 200:
try:
plist = resp['body']['response']
except ValueError:
LOG.warn(_("Unable to parse interface mapping."))
return
else:
LOG.warn(_("Unable to read interface mapping."))
return
if ri.ex_gw_port:
self._set_subnet_info(ri.ex_gw_port)
self._va_config_trusted_zone(ri, plist)
self._va_config_untrusted_zone(ri, plist)
self._va_config_router_snat_rules(ri, plist)
self._va_config_floating_ips(ri)
def _handle_router_snat_rules(self, ri, ex_gw_port, internal_cidrs,
interface_name, action):
return
def _send_gratuitous_arp_packet(self, ri, interface_name, ip_address):
return
def external_gateway_added(self, ri, ex_gw_port,
interface_name, internal_cidrs):
LOG.debug(_("external_gateway_added: %s"), ri.router['id'])
if not ip_lib.device_exists(interface_name,
root_helper=self.root_helper,
namespace=ri.ns_name):
self.driver.plug(ex_gw_port['network_id'],
ex_gw_port['id'], interface_name,
ex_gw_port['mac_address'],
bridge=self.conf.external_network_bridge,
namespace=ri.ns_name,
prefix=l3_agent.EXTERNAL_DEV_PREFIX)
self.driver.init_l3(interface_name, [ex_gw_port['ip_cidr']],
namespace=ri.ns_name)
def _update_routing_table(self, ri, operation, route):
return
class vArmourL3NATAgentWithStateReport(vArmourL3NATAgent,
l3_agent.L3NATAgentWithStateReport):
pass
def main():
conf = cfg.CONF
conf.register_opts(vArmourL3NATAgent.OPTS)
config.register_interface_driver_opts_helper(conf)
config.register_use_namespaces_opts_helper(conf)
config.register_agent_state_opts_helper(conf)
config.register_root_helper(conf)
conf.register_opts(interface.OPTS)
conf.register_opts(external_process.OPTS)
common_config.init(sys.argv[1:])
config.setup_logging(conf)
server = neutron_service.Service.create(
binary='neutron-l3-agent',
topic=topics.L3_AGENT,
report_interval=cfg.CONF.AGENT.report_interval,
manager='neutron.services.firewall.agents.varmour.varmour_router.'
'vArmourL3NATAgentWithStateReport')
service.launch(server).wait()

@ -1,74 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2013 vArmour Networks 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.
#
# @author: Gary Duan, gduan@varmour.com, vArmour Networks
ROUTER_OBJ_PREFIX = 'r-'
OBJ_PREFIX_LEN = 8
TRUST_ZONE = '_z_trust'
UNTRUST_ZONE = '_z_untrust'
SNAT_RULE = '_snat'
DNAT_RULE = '_dnat'
ROUTER_POLICY = '_p'
REST_URL_CONF = '/config'
REST_URL_AUTH = '/auth'
REST_URL_COMMIT = '/commit'
REST_URL_INTF_MAP = '/operation/interface/mapping'
REST_URL_CONF_NAT_RULE = REST_URL_CONF + '/nat/rule'
REST_URL_CONF_ZONE = REST_URL_CONF + '/zone'
REST_URL_CONF_POLICY = REST_URL_CONF + '/policy'
REST_URL_CONF_ADDR = REST_URL_CONF + '/address'
REST_URL_CONF_SERVICE = REST_URL_CONF + '/service'
REST_ZONE_NAME = '/zone/"name:%s"'
REST_INTF_NAME = '/interface/"name:%s"'
REST_LOGIC_NAME = '/logical/"name:%s"'
REST_SERVICE_NAME = '/service/"name:%s"/rule'
def get_router_object_prefix(ri):
return ROUTER_OBJ_PREFIX + ri.router['id'][:OBJ_PREFIX_LEN]
def get_firewall_object_prefix(ri, fw):
return get_router_object_prefix(ri) + '-' + fw['id'][:OBJ_PREFIX_LEN]
def get_trusted_zone_name(ri):
return get_router_object_prefix(ri) + TRUST_ZONE
def get_untrusted_zone_name(ri):
return get_router_object_prefix(ri) + UNTRUST_ZONE
def get_snat_rule_name(ri):
return get_router_object_prefix(ri) + SNAT_RULE
def get_dnat_rule_name(ri):
return get_router_object_prefix(ri) + DNAT_RULE
def get_router_policy_name(ri):
return get_router_object_prefix(ri) + ROUTER_POLICY
def get_firewall_policy_name(ri, fw, rule):
return get_firewall_object_prefix(ri, fw) + rule['id'][:OBJ_PREFIX_LEN]

@ -1,16 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 OpenStack Foundation.
# 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.

@ -1,100 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2013 Dell 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.
#
# @author: Rajesh Mohan, Rajesh_Mohan3@Dell.com, DELL Inc.
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class FwaasDriverBase(object):
"""Firewall as a Service Driver base class.
Using FwaasDriver Class, an instance of L3 perimeter Firewall
can be created. The firewall co-exists with the L3 agent.
One instance is created for each tenant. One firewall policy
is associated with each tenant (in the Havana release).
The Firewall can be visualized as having two zones (in Havana
release), trusted and untrusted.
All the 'internal' interfaces of Neutron Router is treated as trusted. The
interface connected to 'external network' is treated as untrusted.
The policy is applied on traffic ingressing/egressing interfaces on
the trusted zone. This implies that policy will be applied for traffic
passing from
- trusted to untrusted zones
- untrusted to trusted zones
- trusted to trusted zones
Policy WILL NOT be applied for traffic from untrusted to untrusted zones.
This is not a problem in Havana release as there is only one interface
connected to external network.
Since the policy is applied on the internal interfaces, the traffic
will be not be NATed to floating IP. For incoming traffic, the
traffic will get NATed to internal IP address before it hits
the firewall rules. So, while writing the rules, care should be
taken if using rules based on floating IP.
The firewall rule addition/deletion/insertion/update are done by the
management console. When the policy is sent to the driver, the complete
policy is sent and the whole policy has to be applied atomically. The
firewall rules will not get updated individually. This is to avoid problems
related to out-of-order notifications or inconsistent behaviour by partial
application of rules.
"""
@abc.abstractmethod
def create_firewall(self, apply_list, firewall):
"""Create the Firewall with default (drop all) policy.
The default policy will be applied on all the interfaces of
trusted zone.
"""
pass
@abc.abstractmethod
def delete_firewall(self, apply_list, firewall):
"""Delete firewall.
Removes all policies created by this instance and frees up
all the resources.
"""
pass
@abc.abstractmethod
def update_firewall(self, apply_list, firewall):
"""Apply the policy on all trusted interfaces.
Remove previous policy and apply the new policy on all trusted
interfaces.
"""
pass
@abc.abstractmethod
def apply_default_policy(self, apply_list, firewall):
"""Apply the default policy on all trusted interfaces.
Remove current policy and apply the default policy on all trusted
interfaces.
"""
pass

@ -1,16 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 OpenStack Foundation.
# 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.

@ -1,275 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2013 Dell 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.
#
# @author: Rajesh Mohan, Rajesh_Mohan3@Dell.com, DELL Inc.
from neutron.agent.linux import iptables_manager
from neutron.extensions import firewall as fw_ext
from neutron.openstack.common import log as logging
from neutron.services.firewall.drivers import fwaas_base
LOG = logging.getLogger(__name__)
FWAAS_DRIVER_NAME = 'Fwaas iptables driver'
FWAAS_DEFAULT_CHAIN = 'fwaas-default-policy'
INGRESS_DIRECTION = 'ingress'
EGRESS_DIRECTION = 'egress'
CHAIN_NAME_PREFIX = {INGRESS_DIRECTION: 'i',
EGRESS_DIRECTION: 'o'}
""" Firewall rules are applied on internal-interfaces of Neutron router.
The packets ingressing tenant's network will be on the output
direction on internal-interfaces.
"""
IPTABLES_DIR = {INGRESS_DIRECTION: '-o',
EGRESS_DIRECTION: '-i'}
IPV4 = 'ipv4'
IPV6 = 'ipv6'
IP_VER_TAG = {IPV4: 'v4',
IPV6: 'v6'}
class IptablesFwaasDriver(fwaas_base.FwaasDriverBase):
"""IPTables driver for Firewall As A Service."""
def __init__(self):
LOG.debug(_("Initializing fwaas iptables driver"))
def create_firewall(self, apply_list, firewall):
LOG.debug(_('Creating firewall %(fw_id)s for tenant %(tid)s)'),
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
try:
if firewall['admin_state_up']:
self._setup_firewall(apply_list, firewall)
else:
self.apply_default_policy(apply_list, firewall)
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception(_("Failed to create firewall: %s"), firewall['id'])
raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def delete_firewall(self, apply_list, firewall):
LOG.debug(_('Deleting firewall %(fw_id)s for tenant %(tid)s)'),
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
fwid = firewall['id']
try:
for router_info in apply_list:
ipt_mgr = router_info.iptables_manager
self._remove_chains(fwid, ipt_mgr)
self._remove_default_chains(ipt_mgr)
# apply the changes immediately (no defer in firewall path)
ipt_mgr.defer_apply_off()
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception(_("Failed to delete firewall: %s"), fwid)
raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def update_firewall(self, apply_list, firewall):
LOG.debug(_('Updating firewall %(fw_id)s for tenant %(tid)s)'),
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
try:
if firewall['admin_state_up']:
self._setup_firewall(apply_list, firewall)
else:
self.apply_default_policy(apply_list, firewall)
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception(_("Failed to update firewall: %s"), firewall['id'])
raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def apply_default_policy(self, apply_list, firewall):
LOG.debug(_('Applying firewall %(fw_id)s for tenant %(tid)s)'),
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
fwid = firewall['id']
try:
for router_info in apply_list:
ipt_mgr = router_info.iptables_manager
# the following only updates local memory; no hole in FW
self._remove_chains(fwid, ipt_mgr)
self._remove_default_chains(ipt_mgr)
# create default 'DROP ALL' policy chain
self._add_default_policy_chain_v4v6(ipt_mgr)
self._enable_policy_chain(fwid, ipt_mgr)
# apply the changes immediately (no defer in firewall path)
ipt_mgr.defer_apply_off()
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception(_("Failed to apply default policy on firewall: %s"),
fwid)
raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def _setup_firewall(self, apply_list, firewall):
fwid = firewall['id']
for router_info in apply_list:
ipt_mgr = router_info.iptables_manager
# the following only updates local memory; no hole in FW
self._remove_chains(fwid, ipt_mgr)
self._remove_default_chains(ipt_mgr)
# create default 'DROP ALL' policy chain
self._add_default_policy_chain_v4v6(ipt_mgr)
#create chain based on configured policy
self._setup_chains(firewall, ipt_mgr)
# apply the changes immediately (no defer in firewall path)
ipt_mgr.defer_apply_off()
def _get_chain_name(self, fwid, ver, direction):
return '%s%s%s' % (CHAIN_NAME_PREFIX[direction],
IP_VER_TAG[ver],
fwid)
def _setup_chains(self, firewall, ipt_mgr):
"""Create Fwaas chain using the rules in the policy
"""
fw_rules_list = firewall['firewall_rule_list']
fwid = firewall['id']
#default rules for invalid packets and established sessions
invalid_rule = self._drop_invalid_packets_rule()
est_rule = self._allow_established_rule()
for ver in [IPV4, IPV6]:
if ver == IPV4:
table = ipt_mgr.ipv4['filter']
else:
table = ipt_mgr.ipv6['filter']
ichain_name = self._get_chain_name(fwid, ver, INGRESS_DIRECTION)
ochain_name = self._get_chain_name(fwid, ver, EGRESS_DIRECTION)
for name in [ichain_name, ochain_name]:
table.add_chain(name)
table.add_rule(name, invalid_rule)
table.add_rule(name, est_rule)
for rule in fw_rules_list:
if not rule['enabled']:
continue
iptbl_rule = self._convert_fwaas_to_iptables_rule(rule)
if rule['ip_version'] == 4:
ver = IPV4
table = ipt_mgr.ipv4['filter']
else:
ver = IPV6
table = ipt_mgr.ipv6['filter']
ichain_name = self._get_chain_name(fwid, ver, INGRESS_DIRECTION)
ochain_name = self._get_chain_name(fwid, ver, EGRESS_DIRECTION)
table.add_rule(ichain_name, iptbl_rule)
table.add_rule(ochain_name, iptbl_rule)
self._enable_policy_chain(fwid, ipt_mgr)
def _remove_default_chains(self, nsid):
"""Remove fwaas default policy chain."""
self._remove_chain_by_name(IPV4, FWAAS_DEFAULT_CHAIN, nsid)
self._remove_chain_by_name(IPV6, FWAAS_DEFAULT_CHAIN, nsid)
def _remove_chains(self, fwid, ipt_mgr):
"""Remove fwaas policy chain."""
for ver in [IPV4, IPV6]:
for direction in [INGRESS_DIRECTION, EGRESS_DIRECTION]:
chain_name = self._get_chain_name(fwid, ver, direction)
self._remove_chain_by_name(ver, chain_name, ipt_mgr)
def _add_default_policy_chain_v4v6(self, ipt_mgr):
ipt_mgr.ipv4['filter'].add_chain(FWAAS_DEFAULT_CHAIN)
ipt_mgr.ipv4['filter'].add_rule(FWAAS_DEFAULT_CHAIN, '-j DROP')
ipt_mgr.ipv6['filter'].add_chain(FWAAS_DEFAULT_CHAIN)
ipt_mgr.ipv6['filter'].add_rule(FWAAS_DEFAULT_CHAIN, '-j DROP')
def _remove_chain_by_name(self, ver, chain_name, ipt_mgr):
if ver == IPV4:
ipt_mgr.ipv4['filter'].ensure_remove_chain(chain_name)
else:
ipt_mgr.ipv6['filter'].ensure_remove_chain(chain_name)
def _add_rules_to_chain(self, ipt_mgr, ver, chain_name, rules):
if ver == IPV4:
table = ipt_mgr.ipv4['filter']
else:
table = ipt_mgr.ipv6['filter']
for rule in rules:
table.add_rule(chain_name, rule)
def _enable_policy_chain(self, fwid, ipt_mgr):
bname = iptables_manager.binary_name
for (ver, tbl) in [(IPV4, ipt_mgr.ipv4['filter']),
(IPV6, ipt_mgr.ipv6['filter'])]:
for direction in [INGRESS_DIRECTION, EGRESS_DIRECTION]:
chain_name = self._get_chain_name(fwid, ver, direction)
chain_name = iptables_manager.get_chain_name(chain_name)
if chain_name in tbl.chains:
jump_rule = ['%s qr-+ -j %s-%s' % (IPTABLES_DIR[direction],
bname, chain_name)]
self._add_rules_to_chain(ipt_mgr, ver, 'FORWARD',
jump_rule)
#jump to DROP_ALL policy
chain_name = iptables_manager.get_chain_name(FWAAS_DEFAULT_CHAIN)
jump_rule = ['-o qr-+ -j %s-%s' % (bname, chain_name)]
self._add_rules_to_chain(ipt_mgr, IPV4, 'FORWARD', jump_rule)
self._add_rules_to_chain(ipt_mgr, IPV6, 'FORWARD', jump_rule)
#jump to DROP_ALL policy
chain_name = iptables_manager.get_chain_name(FWAAS_DEFAULT_CHAIN)
jump_rule = ['-i qr-+ -j %s-%s' % (bname, chain_name)]
self._add_rules_to_chain(ipt_mgr, IPV4, 'FORWARD', jump_rule)
self._add_rules_to_chain(ipt_mgr, IPV6, 'FORWARD', jump_rule)
def _convert_fwaas_to_iptables_rule(self, rule):
action = rule.get('action') == 'allow' and 'ACCEPT' or 'DROP'
args = [self._protocol_arg(rule.get('protocol')),
self._port_arg('dport',
rule.get('protocol'),
rule.get('destination_port')),
self._port_arg('sport',
rule.get('protocol'),
rule.get('source_port')),
self._ip_prefix_arg('s', rule.get('source_ip_address')),
self._ip_prefix_arg('d', rule.get('destination_ip_address')),
self._action_arg(action)]
iptables_rule = ' '.join(args)
return iptables_rule
def _drop_invalid_packets_rule(self):
return '-m state --state INVALID -j DROP