neutron-fwaas-8.0.0/0000775000567000056710000000000012701410073015444 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/etc/0000775000567000056710000000000012701410073016217 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/etc/oslo-config-generator/0000775000567000056710000000000012701410073022422 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/etc/oslo-config-generator/fwaas_driver.ini0000664000567000056710000000014012701407720025577 0ustar jenkinsjenkins00000000000000[DEFAULT] output_file = etc/fwaas_driver.ini.sample wrap_width = 79 namespace = firewall.agent neutron-fwaas-8.0.0/etc/README.txt0000664000567000056710000000047512701407720017730 0ustar jenkinsjenkins00000000000000To generate the sample neutron-fwaas configuration files, run the following command from the top level of the neutron-fwaas directory: tox -e genconfig If a 'tox' environment is unavailable, then you can run the following script instead to generate the configuration files: ./tools/generate_config_file_samples.sh neutron-fwaas-8.0.0/babel.cfg0000664000567000056710000000002112701407720017170 0ustar jenkinsjenkins00000000000000[python: **.py] neutron-fwaas-8.0.0/.coveragerc0000664000567000056710000000015112701407720017567 0ustar jenkinsjenkins00000000000000[run] branch = True source = neutron_fwaas # omit = neutron_fwaas/tests/* [report] ignore_errors = True neutron-fwaas-8.0.0/setup.cfg0000664000567000056710000000345412701410073017273 0ustar jenkinsjenkins00000000000000[metadata] name = neutron-fwaas summary = OpenStack Networking FWaaS description-file = README.rst author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = http://www.openstack.org/ classifier = Environment :: OpenStack Intended Audience :: Information Technology Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 [files] packages = neutron_fwaas [global] setup-hooks = pbr.hooks.setup_hook [entry_points] firewall_drivers = # These are for backwards compat with Juno firewall service provider configuration values neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver neutron.services.firewall.drivers.varmour.varmour_fwaas.vArmourFwaasDriver = neutron_fwaas.services.firewall.drivers.varmour.varmour_fwaas:vArmourFwaasDriver neutron.db.alembic_migrations = neutron-fwaas = neutron_fwaas.db.migration:alembic_migrations tempest.test_plugins = neutron-fwaas = neutron_fwaas.tests.tempest_plugin.plugin:NeutronFWaaSPlugin oslo.config.opts = firewall.agent = neutron_fwaas.opts:list_agent_opts [build_sphinx] all_files = 1 build-dir = doc/build source-dir = doc/source [extract_messages] keywords = _ gettext ngettext l_ lazy_gettext mapping_file = babel.cfg output_file = neutron_fwaas/locale/neutron_fwaas.pot [compile_catalog] directory = neutron_fwaas/locale domain = neutron_fwaas [update_catalog] domain = neutron_fwaas output_dir = neutron_fwaas/locale input_file = neutron_fwaas/locale/neutron_fwaas.pot [wheel] universal = 1 [egg_info] tag_date = 0 tag_build = tag_svn_revision = 0 neutron-fwaas-8.0.0/tools/0000775000567000056710000000000012701410073016604 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/tools/pretty_tox.sh0000775000567000056710000000030512701407720021367 0ustar jenkinsjenkins00000000000000#! /bin/sh TESTRARGS=$1 exec 3>&1 status=$(exec 4>&1 >&3; (python setup.py testr --slowest --testr-args="--subunit $TESTRARGS"; echo $? >&4 ) | $(dirname $0)/subunit-trace.py -f) && exit $status neutron-fwaas-8.0.0/tools/check_i18n.py0000664000567000056710000001243412701407720021103 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # # 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. from __future__ import print_function import compiler import imp import os.path import sys def is_localized(node): """Check message wrapped by _()""" if isinstance(node.parent, compiler.ast.CallFunc): if isinstance(node.parent.node, compiler.ast.Name): if node.parent.node.name == '_': return True return False class ASTWalker(compiler.visitor.ASTVisitor): def default(self, node, *args): for child in node.getChildNodes(): child.parent = node compiler.visitor.ASTVisitor.default(self, node, *args) class Visitor(object): def __init__(self, filename, i18n_msg_predicates, msg_format_checkers, debug): self.filename = filename self.debug = debug self.error = 0 self.i18n_msg_predicates = i18n_msg_predicates self.msg_format_checkers = msg_format_checkers with open(filename) as f: self.lines = f.readlines() def visitConst(self, node): if not isinstance(node.value, str): return if is_localized(node): for (checker, msg) in self.msg_format_checkers: if checker(node): print('%s:%d %s: %s Error: %s' % (self.filename, node.lineno, self.lines[node.lineno - 1][:-1], checker.__name__, msg), file=sys.stderr) self.error = 1 return if debug: print('%s:%d %s: %s' % (self.filename, node.lineno, self.lines[node.lineno - 1][:-1], "Pass")) else: for (predicate, action, msg) in self.i18n_msg_predicates: if predicate(node): if action == 'skip': if debug: print('%s:%d %s: %s' % (self.filename, node.lineno, self.lines[node.lineno - 1][:-1], "Pass")) return elif action == 'error': print('%s:%d %s: %s Error: %s' % (self.filename, node.lineno, self.lines[node.lineno - 1][:-1], predicate.__name__, msg), file=sys.stderr) self.error = 1 return elif action == 'warn': print('%s:%d %s: %s' % (self.filename, node.lineno, self.lines[node.lineno - 1][:-1], "Warn: %s" % msg)) return print('Predicate with wrong action!', file=sys.stderr) def is_file_in_black_list(black_list, f): for f in black_list: if os.path.abspath(input_file).startswith( os.path.abspath(f)): return True return False def check_i18n(input_file, i18n_msg_predicates, msg_format_checkers, debug): input_mod = compiler.parseFile(input_file) v = compiler.visitor.walk(input_mod, Visitor(input_file, i18n_msg_predicates, msg_format_checkers, debug), ASTWalker()) return v.error if __name__ == '__main__': input_path = sys.argv[1] cfg_path = sys.argv[2] try: cfg_mod = imp.load_source('', cfg_path) except Exception: print("Load cfg module failed", file=sys.stderr) sys.exit(1) i18n_msg_predicates = cfg_mod.i18n_msg_predicates msg_format_checkers = cfg_mod.msg_format_checkers black_list = cfg_mod.file_black_list debug = False if len(sys.argv) > 3: if sys.argv[3] == '-d': debug = True if os.path.isfile(input_path): sys.exit(check_i18n(input_path, i18n_msg_predicates, msg_format_checkers, debug)) error = 0 for dirpath, dirs, files in os.walk(input_path): for f in files: if not f.endswith('.py'): continue input_file = os.path.join(dirpath, f) if is_file_in_black_list(black_list, input_file): continue if check_i18n(input_file, i18n_msg_predicates, msg_format_checkers, debug): error = 1 sys.exit(error) neutron-fwaas-8.0.0/tools/subunit-trace.py0000775000567000056710000002454412701407720021764 0ustar jenkinsjenkins00000000000000#!/usr/bin/env python # Copyright 2014 Hewlett-Packard Development Company, L.P. # Copyright 2014 Samsung Electronics # 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. """Trace a subunit stream in reasonable detail and high accuracy.""" import argparse import functools import os import re import sys import mimeparse import subunit import testtools DAY_SECONDS = 60 * 60 * 24 FAILS = [] RESULTS = {} class Starts(testtools.StreamResult): def __init__(self, output): super(Starts, self).__init__() self._output = output def startTestRun(self): self._neednewline = False self._emitted = set() def status(self, test_id=None, test_status=None, test_tags=None, runnable=True, file_name=None, file_bytes=None, eof=False, mime_type=None, route_code=None, timestamp=None): super(Starts, self).status( test_id, test_status, test_tags=test_tags, runnable=runnable, file_name=file_name, file_bytes=file_bytes, eof=eof, mime_type=mime_type, route_code=route_code, timestamp=timestamp) if not test_id: if not file_bytes: return if not mime_type or mime_type == 'test/plain;charset=utf8': mime_type = 'text/plain; charset=utf-8' primary, sub, parameters = mimeparse.parse_mime_type(mime_type) content_type = testtools.content_type.ContentType( primary, sub, parameters) content = testtools.content.Content( content_type, lambda: [file_bytes]) text = content.as_text() if text and text[-1] not in '\r\n': self._neednewline = True self._output.write(text) elif test_status == 'inprogress' and test_id not in self._emitted: if self._neednewline: self._neednewline = False self._output.write('\n') worker = '' for tag in test_tags or (): if tag.startswith('worker-'): worker = '(' + tag[7:] + ') ' if timestamp: timestr = timestamp.isoformat() else: timestr = '' self._output.write('%s: %s%s [start]\n' % (timestr, worker, test_id)) self._emitted.add(test_id) def cleanup_test_name(name, strip_tags=True, strip_scenarios=False): """Clean up the test name for display. By default we strip out the tags in the test because they don't help us in identifying the test that is run to it's result. Make it possible to strip out the test scenarios information (not to be confused with tempest scenarios) however that's often needed to identify generated negative tests. """ if strip_tags: tags_start = name.find('[') tags_end = name.find(']') if tags_start > 0 and tags_end > tags_start: newname = name[:tags_start] newname += name[tags_end + 1:] name = newname if strip_scenarios: tags_start = name.find('(') tags_end = name.find(')') if tags_start > 0 and tags_end > tags_start: newname = name[:tags_start] newname += name[tags_end + 1:] name = newname return name def get_duration(timestamps): start, end = timestamps if not start or not end: duration = '' else: delta = end - start duration = '%d.%06ds' % ( delta.days * DAY_SECONDS + delta.seconds, delta.microseconds) return duration def find_worker(test): for tag in test['tags']: if tag.startswith('worker-'): return int(tag[7:]) return 'NaN' # Print out stdout/stderr if it exists, always def print_attachments(stream, test, all_channels=False): """Print out subunit attachments. Print out subunit attachments that contain content. This runs in 2 modes, one for successes where we print out just stdout and stderr, and an override that dumps all the attachments. """ channels = ('stdout', 'stderr') for name, detail in test['details'].items(): # NOTE(sdague): the subunit names are a little crazy, and actually # are in the form pythonlogging:'' (with the colon and quotes) name = name.split(':')[0] if detail.content_type.type == 'test': detail.content_type.type = 'text' if (all_channels or name in channels) and detail.as_text(): title = "Captured %s:" % name stream.write("\n%s\n%s\n" % (title, ('~' * len(title)))) # indent attachment lines 4 spaces to make them visually # offset for line in detail.as_text().split('\n'): stream.write(" %s\n" % line) def show_outcome(stream, test, print_failures=False, failonly=False): global RESULTS status = test['status'] # TODO(sdague): ask lifeless why on this? if status == 'exists': return worker = find_worker(test) name = cleanup_test_name(test['id']) duration = get_duration(test['timestamps']) if worker not in RESULTS: RESULTS[worker] = [] RESULTS[worker].append(test) # don't count the end of the return code as a fail if name == 'process-returncode': return if status == 'fail': FAILS.append(test) stream.write('{%s} %s [%s] ... FAILED\n' % ( worker, name, duration)) if not print_failures: print_attachments(stream, test, all_channels=True) elif not failonly: if status == 'success': stream.write('{%s} %s [%s] ... ok\n' % ( worker, name, duration)) print_attachments(stream, test) elif status == 'skip': stream.write('{%s} %s ... SKIPPED: %s\n' % ( worker, name, test['details']['reason'].as_text())) else: stream.write('{%s} %s [%s] ... %s\n' % ( worker, name, duration, test['status'])) if not print_failures: print_attachments(stream, test, all_channels=True) stream.flush() def print_fails(stream): """Print summary failure report. Currently unused, however there remains debate on inline vs. at end reporting, so leave the utility function for later use. """ if not FAILS: return stream.write("\n==============================\n") stream.write("Failed %s tests - output below:" % len(FAILS)) stream.write("\n==============================\n") for f in FAILS: stream.write("\n%s\n" % f['id']) stream.write("%s\n" % ('-' * len(f['id']))) print_attachments(stream, f, all_channels=True) stream.write('\n') def count_tests(key, value): count = 0 for k, v in RESULTS.items(): for item in v: if key in item: if re.search(value, item[key]): count += 1 return count def run_time(): runtime = 0.0 for k, v in RESULTS.items(): for test in v: runtime += float(get_duration(test['timestamps']).strip('s')) return runtime def worker_stats(worker): tests = RESULTS[worker] num_tests = len(tests) delta = tests[-1]['timestamps'][1] - tests[0]['timestamps'][0] return num_tests, delta def print_summary(stream): stream.write("\n======\nTotals\n======\n") stream.write("Run: %s in %s sec.\n" % (count_tests('status', '.*'), run_time())) stream.write(" - Passed: %s\n" % count_tests('status', 'success')) stream.write(" - Skipped: %s\n" % count_tests('status', 'skip')) stream.write(" - Failed: %s\n" % count_tests('status', 'fail')) # we could have no results, especially as we filter out the process-codes if RESULTS: stream.write("\n==============\nWorker Balance\n==============\n") for w in range(max(RESULTS.keys()) + 1): if w not in RESULTS: stream.write( " - WARNING: missing Worker %s! " "Race in testr accounting.\n" % w) else: num, time = worker_stats(w) stream.write(" - Worker %s (%s tests) => %ss\n" % (w, num, time)) def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('--no-failure-debug', '-n', action='store_true', dest='print_failures', help='Disable printing failure ' 'debug information in realtime') parser.add_argument('--fails', '-f', action='store_true', dest='post_fails', help='Print failure debug ' 'information after the stream is proccesed') parser.add_argument('--failonly', action='store_true', dest='failonly', help="Don't print success items", default=( os.environ.get('TRACE_FAILONLY', False) is not False)) return parser.parse_args() def main(): args = parse_args() stream = subunit.ByteStreamToStreamResult( sys.stdin, non_subunit_name='stdout') starts = Starts(sys.stdout) outcomes = testtools.StreamToDict( functools.partial(show_outcome, sys.stdout, print_failures=args.print_failures, failonly=args.failonly )) summary = testtools.StreamSummary() result = testtools.CopyStreamResult([starts, outcomes, summary]) result.startTestRun() try: stream.run(result) finally: result.stopTestRun() if count_tests('status', '.*') == 0: print("The test run didn't actually run any tests") return 1 if args.post_fails: print_fails(sys.stdout) print_summary(sys.stdout) return (0 if summary.wasSuccessful() else 1) if __name__ == '__main__': sys.exit(main()) neutron-fwaas-8.0.0/tools/generate_config_file_samples.sh0000775000567000056710000000144012701407720025011 0ustar jenkinsjenkins00000000000000#!/bin/sh # # 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. set -e GEN_CMD=oslo-config-generator if ! type "$GEN_CMD" > /dev/null; then echo "ERROR: $GEN_CMD not installed on the system." exit 1 fi for file in `ls etc/oslo-config-generator/*`; do $GEN_CMD --config-file=$file done set -x neutron-fwaas-8.0.0/tools/check_i18n_test_case.txt0000664000567000056710000000264512701407720023327 0ustar jenkinsjenkins00000000000000# test-case for check_i18n.py # python check_i18n.py check_i18n.txt -d # message format checking # capital checking msg = _("hello world, error") msg = _("hello world_var, error") msg = _('file_list xyz, pass') msg = _("Hello world, pass") # format specifier checking msg = _("Hello %s world %d, error") msg = _("Hello %s world, pass") msg = _("Hello %(var1)s world %(var2)s, pass") # message has been localized # is_localized msg = _("Hello world, pass") msg = _("Hello world, pass") % var LOG.debug(_('Hello world, pass')) LOG.info(_('Hello world, pass')) raise x.y.Exception(_('Hello world, pass')) raise Exception(_('Hello world, pass')) # message need be localized # is_log_callfunc LOG.debug('hello world, error') LOG.debug('hello world, error' % xyz) sys.append('hello world, warn') # is_log_i18n_msg_with_mod LOG.debug(_('Hello world, error') % xyz) # default warn msg = 'hello world, warn' msg = 'hello world, warn' % var # message needn't be localized # skip only one word msg = '' msg = "hello,pass" # skip dict msg = {'hello world, pass': 1} # skip list msg = ["hello world, pass"] # skip subscript msg['hello world, pass'] # skip xml marker msg = ", pass" # skip sql statement msg = "SELECT * FROM xyz WHERE hello=1, pass" msg = "select * from xyz, pass" # skip add statement msg = 'hello world' + e + 'world hello, pass' # skip doc string """ Hello world, pass """ class Msg: pass neutron-fwaas-8.0.0/tools/install_venv_common.py0000664000567000056710000001350712701407720023245 0ustar jenkinsjenkins00000000000000# Copyright 2013 OpenStack Foundation # Copyright 2013 IBM Corp. # # 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. """Provides methods needed by installation script for OpenStack development virtual environments. Since this script is used to bootstrap a virtualenv from the system's Python environment, it should be kept strictly compatible with Python 2.6. Synced in from openstack-common """ from __future__ import print_function import optparse import os import subprocess import sys class InstallVenv(object): def __init__(self, root, venv, requirements, test_requirements, py_version, project): self.root = root self.venv = venv self.requirements = requirements self.test_requirements = test_requirements self.py_version = py_version self.project = project def die(self, message, *args): print(message % args, file=sys.stderr) sys.exit(1) def check_python_version(self): if sys.version_info < (2, 6): self.die("Need Python Version >= 2.6") def run_command_with_code(self, cmd, redirect_output=True, check_exit_code=True): """Runs a command in an out-of-process shell. Returns the output of that command. Working directory is self.root. """ if redirect_output: stdout = subprocess.PIPE else: stdout = None proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout) output = proc.communicate()[0] if check_exit_code and proc.returncode != 0: self.die('Command "%s" failed.\n%s', ' '.join(cmd), output) return (output, proc.returncode) def run_command(self, cmd, redirect_output=True, check_exit_code=True): return self.run_command_with_code(cmd, redirect_output, check_exit_code)[0] def get_distro(self): if (os.path.exists('/etc/fedora-release') or os.path.exists('/etc/redhat-release')): return Fedora( self.root, self.venv, self.requirements, self.test_requirements, self.py_version, self.project) else: return Distro( self.root, self.venv, self.requirements, self.test_requirements, self.py_version, self.project) def check_dependencies(self): self.get_distro().install_virtualenv() def create_virtualenv(self, no_site_packages=True): """Creates the virtual environment and installs PIP. Creates the virtual environment and installs PIP only into the virtual environment. """ if not os.path.isdir(self.venv): print('Creating venv...', end=' ') if no_site_packages: self.run_command(['virtualenv', '-q', '--no-site-packages', self.venv]) else: self.run_command(['virtualenv', '-q', self.venv]) print('done.') else: print("venv already exists...") pass def pip_install(self, *args): self.run_command(['tools/with_venv.sh', 'pip', 'install', '--upgrade'] + list(args), redirect_output=False) def install_dependencies(self): print('Installing dependencies with pip (this can take a while)...') # First things first, make sure our venv has the latest pip and # setuptools and pbr self.pip_install('pip>=1.4') self.pip_install('setuptools') self.pip_install('pbr') self.pip_install('-r', self.requirements, '-r', self.test_requirements) def parse_args(self, argv): """Parses command-line arguments.""" parser = optparse.OptionParser() parser.add_option('-n', '--no-site-packages', action='store_true', help="Do not inherit packages from global Python " "install.") return parser.parse_args(argv[1:])[0] class Distro(InstallVenv): def check_cmd(self, cmd): return bool(self.run_command(['which', cmd], check_exit_code=False).strip()) def install_virtualenv(self): if self.check_cmd('virtualenv'): return if self.check_cmd('easy_install'): print('Installing virtualenv via easy_install...', end=' ') if self.run_command(['easy_install', 'virtualenv']): print('Succeeded') return else: print('Failed') self.die('ERROR: virtualenv not found.\n\n%s development' ' requires virtualenv, please install it using your' ' favorite package management tool' % self.project) class Fedora(Distro): """This covers all Fedora-based distributions. Includes: Fedora, RHEL, CentOS, Scientific Linux """ def check_pkg(self, pkg): return self.run_command_with_code(['rpm', '-q', pkg], check_exit_code=False)[1] == 0 def install_virtualenv(self): if self.check_cmd('virtualenv'): return if not self.check_pkg('python-virtualenv'): self.die("Please install 'python-virtualenv'.") super(Fedora, self).install_virtualenv() neutron-fwaas-8.0.0/tools/install_venv.py0000664000567000056710000000440012701407720021665 0ustar jenkinsjenkins00000000000000#!/usr/bin/env python # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # Copyright 2010 OpenStack Foundation. # Copyright 2013 IBM Corp. # # 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. """ Installation script for Neutron's development virtualenv """ from __future__ import print_function import os import sys import install_venv_common as install_venv def print_help(): help = """ Neutron development environment setup is complete. Neutron development uses virtualenv to track and manage Python dependencies while in development and testing. To activate the Neutron virtualenv for the extent of your current shell session you can run: $ source .venv/bin/activate Or, if you prefer, you can run commands in the virtualenv on a case by case basis by running: $ tools/with_venv.sh Also, make test will automatically use the virtualenv. """ print(help) def main(argv): root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) venv = os.path.join(root, '.venv') pip_requires = os.path.join(root, 'requirements.txt') test_requires = os.path.join(root, 'test-requirements.txt') py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1]) project = 'Neutron' install = install_venv.InstallVenv(root, venv, pip_requires, test_requires, py_version, project) options = install.parse_args(argv) install.check_python_version() install.check_dependencies() install.create_virtualenv(no_site_packages=options.no_site_packages) install.install_dependencies() print_help() if __name__ == '__main__': main(sys.argv) neutron-fwaas-8.0.0/tools/with_venv.sh0000775000567000056710000000133312701407720021161 0ustar jenkinsjenkins00000000000000#!/usr/bin/env bash # Copyright 2011 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. TOOLS=`dirname $0` VENV=$TOOLS/../.venv source $VENV/bin/activate && "$@" neutron-fwaas-8.0.0/tools/i18n_cfg.py0000664000567000056710000000664312701407720020572 0ustar jenkinsjenkins00000000000000import compiler import re def is_log_callfunc(n): """LOG.xxx('hello %s' % xyz) and LOG('hello')""" if isinstance(n.parent, compiler.ast.Mod): n = n.parent if isinstance(n.parent, compiler.ast.CallFunc): if isinstance(n.parent.node, compiler.ast.Getattr): if isinstance(n.parent.node.getChildNodes()[0], compiler.ast.Name): if n.parent.node.getChildNodes()[0].name == 'LOG': return True return False def is_log_i18n_msg_with_mod(n): """LOG.xxx("Hello %s" % xyz) should be LOG.xxx("Hello %s", xyz)""" if not isinstance(n.parent.parent, compiler.ast.Mod): return False n = n.parent.parent if isinstance(n.parent, compiler.ast.CallFunc): if isinstance(n.parent.node, compiler.ast.Getattr): if isinstance(n.parent.node.getChildNodes()[0], compiler.ast.Name): if n.parent.node.getChildNodes()[0].name == 'LOG': return True return False def is_wrong_i18n_format(n): """Check _('hello %s' % xyz)""" if isinstance(n.parent, compiler.ast.Mod): n = n.parent if isinstance(n.parent, compiler.ast.CallFunc): if isinstance(n.parent.node, compiler.ast.Name): if n.parent.node.name == '_': return True return False """ Used for check message need be localized or not. (predicate_func, action, message) """ i18n_msg_predicates = [ # Skip ['hello world', 1] (lambda n: isinstance(n.parent, compiler.ast.List), 'skip', ''), # Skip {'hellow world', 1} (lambda n: isinstance(n.parent, compiler.ast.Dict), 'skip', ''), # Skip msg['hello world'] (lambda n: isinstance(n.parent, compiler.ast.Subscript), 'skip', ''), # Skip doc string (lambda n: isinstance(n.parent, compiler.ast.Discard), 'skip', ''), # Skip msg = "hello", in normal, message should more than one word (lambda n: len(n.value.strip().split(' ')) <= 1, 'skip', ''), # Skip msg = 'hello world' + vars + 'world hello' (lambda n: isinstance(n.parent, compiler.ast.Add), 'skip', ''), # Skip xml markers msg = "" (lambda n: len(re.compile("").findall(n.value)) > 0, 'skip', ''), # Skip sql statement (lambda n: len( re.compile("^SELECT.*FROM", flags=re.I).findall(n.value)) > 0, 'skip', ''), # LOG.xxx() (is_log_callfunc, 'error', 'Message must be localized'), # _('hello %s' % xyz) should be _('hello %s') % xyz (is_wrong_i18n_format, 'error', ("Message format was wrong, _('hello %s' % xyz) " "should be _('hello %s') % xyz")), # default (lambda n: True, 'warn', 'Message might need localized') ] """ Used for checking message format. (checker_func, message) """ msg_format_checkers = [ # If message contain more than on format specifier, it should use # mapping key (lambda n: len(re.compile("%[bcdeEfFgGnosxX]").findall(n.value)) > 1, "The message shouldn't contain more than one format specifier"), # Check capital (lambda n: n.value.split(' ')[0].count('_') == 0 and n.value[0].isalpha() and n.value[0].islower(), "First letter must be capital"), (is_log_i18n_msg_with_mod, 'LOG.xxx("Hello %s" % xyz) should be LOG.xxx("Hello %s", xyz)') ] file_black_list = ["./neutron/tests/unit", "./neutron/openstack", "./neutron/plugins/bigswitch/tests"] neutron-fwaas-8.0.0/tools/clean.sh0000775000567000056710000000030412701407720020227 0ustar jenkinsjenkins00000000000000#!/usr/bin/env bash rm -rf ./*.deb ./*.tar.gz ./*.dsc ./*.changes rm -rf */*.deb rm -rf ./plugins/**/build/ ./plugins/**/dist rm -rf ./plugins/**/lib/neutron_*_plugin.egg-info ./plugins/neutron-* neutron-fwaas-8.0.0/tools/tox_install.sh0000775000567000056710000000247012701407721021514 0ustar jenkinsjenkins00000000000000#!/bin/sh # Many of neutron's repos suffer from the problem of depending on neutron, # but it not existing on pypi. # This wrapper for tox's package installer will use the existing package # if it exists, else use zuul-cloner if that program exists, else grab it # from neutron master via a hard-coded URL. That last case should only # happen with devs running unit tests locally. ZUUL_CLONER=/usr/zuul-env/bin/zuul-cloner neutron_installed=$(echo "import neutron" | python 2>/dev/null ; echo $?) BRANCH_NAME=stable/mitaka set -e CONSTRAINTS_FILE=$1 shift install_cmd="pip install" if [ $CONSTRAINTS_FILE != "unconstrained" ]; then install_cmd="$install_cmd -c$CONSTRAINTS_FILE" fi if [ $neutron_installed -eq 0 ]; then echo "ALREADY INSTALLED" > /tmp/tox_install.txt echo "Neutron already installed; using existing package" elif [ -x "$ZUUL_CLONER" ]; then echo "ZUUL CLONER" > /tmp/tox_install.txt cwd=$(/bin/pwd) cd /tmp $ZUUL_CLONER --cache-dir \ /opt/git \ --branch $BRANCH_NAME \ git://git.openstack.org \ openstack/neutron cd openstack/neutron $install_cmd -e . cd "$cwd" else echo "PIP HARDCODE" > /tmp/tox_install.txt $install_cmd -U -egit+https://git.openstack.org/openstack/neutron@$BRANCH_NAME#egg=neutron fi $install_cmd -U $* exit $? neutron-fwaas-8.0.0/tools/check_unit_test_structure.sh0000775000567000056710000000307512701407720024450 0ustar jenkinsjenkins00000000000000#!/usr/bin/env bash # This script identifies the unit test modules that do not correspond # directly with a module in the code tree. See TESTING.rst for the # intended structure. neutron_path=$(cd "$(dirname "$0")/.." && pwd) base_test_path=neutron_fwaas/tests/unit test_path=$neutron_path/$base_test_path test_files=$(find ${test_path} -iname 'test_*.py') ignore_regexes=( "^plugins.*$" ) error_count=0 ignore_count=0 total_count=0 for test_file in ${test_files[@]}; do relative_path=${test_file#$test_path/} expected_path=$(dirname $neutron_path/neutron_fwaas/$relative_path) test_filename=$(basename "$test_file") expected_filename=${test_filename#test_} # Module filename (e.g. foo/bar.py -> foo/test_bar.py) filename=$expected_path/$expected_filename # Package dir (e.g. foo/ -> test_foo.py) package_dir=${filename%.py} if [ ! -f "$filename" ] && [ ! -d "$package_dir" ]; then for ignore_regex in ${ignore_regexes[@]}; do if [[ "$relative_path" =~ $ignore_regex ]]; then ((ignore_count++)) continue 2 fi done echo "Unexpected test file: $base_test_path/$relative_path" ((error_count++)) fi ((total_count++)) done if [ "$ignore_count" -ne 0 ]; then echo "$ignore_count unmatched test modules were ignored" fi if [ "$error_count" -eq 0 ]; then echo 'Success! All test modules match targets in the code tree.' exit 0 else echo "Failure! $error_count of $total_count test modules do not match targets in the code tree." exit 1 fi neutron-fwaas-8.0.0/doc/0000775000567000056710000000000012701410073016211 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/doc/source/0000775000567000056710000000000012701410073017511 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/doc/source/index.rst0000664000567000056710000000025312701407720021357 0ustar jenkinsjenkins00000000000000.. documentation master file ==== Main ==== .. toctree:: :glob: :maxdepth: 1 main/* ================== Indices and tables ================== * :ref:`search` neutron-fwaas-8.0.0/doc/source/conf.py0000664000567000056710000001753512701407720021030 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2010 OpenStack Foundation. # # 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. # # Keystone documentation build configuration file, created by # sphinx-quickstart on Tue May 18 13:50:15 2010. # # This file is execfile()'d with the current directory set to it's containing # dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import os import subprocess import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. BASE_DIR = os.path.dirname(os.path.abspath(__file__)) ROOT_DIR = os.path.abspath(os.path.join(BASE_DIR, "..", "..")) sys.path.insert(0, ROOT_DIR) # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig', 'sphinx.ext.graphviz', 'sphinx.ext.todo', 'oslosphinx'] todo_include_todos = True # Add any paths that contain templates here, relative to this directory. templates_path = [] if os.getenv('HUDSON_PUBLISH_DOCS'): templates_path = ['_ga', '_templates'] else: templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Neutron FWaaS' copyright = u'2011-present, OpenStack Foundation.' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # Version info from neutron_fwaas.version import version_info as neutron_fwaas_version release = neutron_fwaas_version.release_string() # The short X.Y version. version = neutron_fwaas_version.version_string() # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. # unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = [] # The reST default role (for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. show_authors = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. modindex_common_prefix = ['neutron_fwaas.'] # -- Options for man page output -------------------------------------------- # Grouping the document tree for man pages. # List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual' #man_pages = [ # ('man/neutron-server', 'neutron-server', u'Neutron Server', # [u'OpenStack'], 1) #] # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. # html_theme_path = ["."] # html_theme = '_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = ['_theme'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' git_cmd = ["git", "log", "--pretty=format:'%ad, commit %h'", "--date=local", "-n1"] html_last_updated_fmt = subprocess.Popen( git_cmd, stdout=subprocess.PIPE).communicate()[0] # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_use_modindex = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. #htmlhelp_basename = 'neutrondoc' # -- Options for LaTeX output ------------------------------------------------ # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, # documentclass [howto/manual]). #latex_documents = [ # ('index', 'Neutron.tex', u'Neutron Documentation', # u'Neutron development team', 'manual'), #] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_use_modindex = True neutron-fwaas-8.0.0/neutron_fwaas/0000775000567000056710000000000012701410073020317 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/0000775000567000056710000000000012701410073021461 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/__init__.py0000664000567000056710000000000012701407720023565 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/contrib/0000775000567000056710000000000012701410073023121 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/contrib/README0000664000567000056710000000022612701407720024006 0ustar jenkinsjenkins00000000000000The files in this directory are intended for use by the infra jobs that run the various functional test suite in the gate for the neutron-fwaas repo. neutron-fwaas-8.0.0/neutron_fwaas/tests/contrib/filters.template0000664000567000056710000000137412701407720026340 0ustar jenkinsjenkins00000000000000# neutron-rootwrap command filters to support functional testing. It # is NOT intended to be used outside of a test environment. # # This file should be owned by (and only-writeable by) the root user [Filters] # '$BASE_PATH' is intended to be replaced with the expected tox path # (e.g. /opt/stack/new/neutron/.tox/dsvm-functional) by the neutron # functional jenkins job. This ensures that tests can kill the # processes that they launch with their containing tox environment's # python. kill_tox_python: KillFilter, root, $BASE_PATH/bin/python, -9 # enable ping from namespace ping_filter: CommandFilter, ping, root # enable curl from namespace curl_filter: CommandFilter, curl, root tee_filter: CommandFilter, tee, root tee_kill: KillFilter, root, tee, -9 neutron-fwaas-8.0.0/neutron_fwaas/tests/contrib/gate_hook.sh0000775000567000056710000000516012701407720025427 0ustar jenkinsjenkins00000000000000#!/bin/bash set -ex # Below variables are set to exceute this script IS_GATE=${IS_GATE:-False} INSTALL_MYSQL_ONLY=${INSTALL_MYSQL_ONLY:-True} CONTRIB_DIR="$BASE/new/neutron-fwaas/neutron_fwaas/tests/contrib" $BASE/new/devstack-gate/devstack-vm-gate.sh # Add a rootwrap filter to support test-only # configuration (e.g. a KillFilter for processes that # use the python installed in a tox env). FUNC_FILTER=$CONTRIB_DIR/filters.template sed -e "s+\$BASE_PATH+$BASE/new/neutron-fwaas/.tox/dsvm-functional+" \ $FUNC_FILTER | sudo tee /etc/neutron/rootwrap.d/functional.filters > /dev/null # Use devstack functions to install mysql and psql servers TOP_DIR=$BASE/new/devstack source $TOP_DIR/functions source $TOP_DIR/inc/meta-config source $TOP_DIR/stackrc source $TOP_DIR/lib/database source $TOP_DIR/localrc # Install_databases [install_pg] # Tweak the script accordingly if we need psql in future function _install_databases { local install_pg=${1:-True} echo_summary "Installing databases" # Avoid attempting to configure the db if it appears to already # have run. The setup as currently defined is not idempotent. if mysql openstack_citest > /dev/null 2>&1 < /dev/null; then echo_summary "DB config appears to be complete, skipping." return 0 fi enable_service mysql initialize_database_backends install_database configure_database_mysql if [[ "$install_pg" == "True" ]]; then enable_service postgresql initialize_database_backends install_database configure_database_postgresql fi # Set up the 'openstack_citest' user and database in each backend tmp_dir=$(mktemp -d) trap "rm -rf $tmp_dir" EXIT cat << EOF > $tmp_dir/mysql.sql CREATE DATABASE openstack_citest; CREATE USER 'openstack_citest'@'localhost' IDENTIFIED BY 'openstack_citest'; CREATE USER 'openstack_citest' IDENTIFIED BY 'openstack_citest'; GRANT ALL PRIVILEGES ON *.* TO 'openstack_citest'@'localhost'; GRANT ALL PRIVILEGES ON *.* TO 'openstack_citest'; FLUSH PRIVILEGES; EOF /usr/bin/mysql -u root < $tmp_dir/mysql.sql if [[ "$install_pg" == "True" ]]; then cat << EOF > $tmp_dir/postgresql.sql CREATE USER openstack_citest WITH CREATEDB LOGIN PASSWORD 'openstack_citest'; CREATE DATABASE openstack_citest WITH OWNER openstack_citest; EOF # User/group postgres needs to be given access to tmp_dir setfacl -m g:postgres:rwx $tmp_dir sudo -u postgres /usr/bin/psql --file=$tmp_dir/postgresql.sql fi } if [[ "$IS_GATE" != "True" ]]; then if [[ "$INSTALL_MYSQL_ONLY" == "True" ]]; then _install_databases nopg fi fineutron-fwaas-8.0.0/neutron_fwaas/tests/contrib/post_test_hook.sh0000775000567000056710000000214612701407720026534 0ustar jenkinsjenkins00000000000000#!/bin/bash set -xe NEUTRON_DIR="$BASE/new/neutron-fwaas" TEMPEST_DIR="$BASE/new/tempest" SCRIPTS_DIR="/usr/os-testr-env/bin" function generate_testr_results { # Give job user rights to access tox logs sudo -H -u $owner chmod o+rw . sudo -H -u $owner chmod o+rw -R .testrepository if [ -f ".testrepository/0" ] ; then .tox/dsvm-functional/bin/subunit-1to2 < .testrepository/0 > ./testrepository.subunit $SCRIPTS_DIR/subunit2html ./testrepository.subunit testr_results.html gzip -9 ./testrepository.subunit gzip -9 ./testr_results.html sudo mv ./*.gz /opt/stack/logs/ fi } function dsvm_functional_prep_func { : } owner=stack prep_func="dsvm_functional_prep_func" # Set owner permissions according to job's requirements. cd $NEUTRON_DIR sudo chown -R $owner:stack $NEUTRON_DIR # Prep the environment according to job's requirements. $prep_func # Run tests echo "Running neutron dsvm-functional test suite" set +e sudo -H -u $owner tox -e dsvm-functional testr_exit_code=$? set -e # Collect and parse results generate_testr_results exit $testr_exit_code neutron-fwaas-8.0.0/neutron_fwaas/tests/base.py0000664000567000056710000000157512701407720022762 0ustar jenkinsjenkins00000000000000# Copyright 2014 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. # from neutron.tests import base as n_base from neutron.tests.unit.db import test_db_base_plugin_v2 as test_db_plugin class BaseTestCase(n_base.BaseTestCase): pass class NeutronDbPluginV2TestCase(test_db_plugin.NeutronDbPluginV2TestCase): pass neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/0000775000567000056710000000000012701410073024520 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/plugin.py0000664000567000056710000000231612701407720026377 0ustar jenkinsjenkins00000000000000# Copyright (c) 2015 Midokura SARL # 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 os from tempest.test_discover import plugins class NeutronFWaaSPlugin(plugins.TempestPlugin): def get_opt_lists(self): return [] def load_tests(self): this_dir = os.path.dirname(os.path.abspath(__file__)) # top_level_dir = $(this_dir)/../../.. d = os.path.split(this_dir)[0] d = os.path.split(d)[0] top_level_dir = os.path.split(d)[0] test_dir = os.path.join(top_level_dir, 'neutron_fwaas/tests/tempest_plugin/tests') return (test_dir, top_level_dir) def register_opts(self, conf): return neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/0000775000567000056710000000000012701410073025662 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/__init__.py0000664000567000056710000000000012701407720027766 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/fwaas_client.py0000664000567000056710000001134512701407720030704 0ustar jenkinsjenkins00000000000000# Copyright (c) 2015 Midokura SARL # 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 time from tempest import config from tempest import exceptions from tempest.lib.common.utils import data_utils from tempest.lib import exceptions as lib_exc from neutron.plugins.common import constants as p_const from neutron_fwaas.tests.tempest_plugin.services import client CONF = config.CONF class FWaaSClientMixin(object): @classmethod def resource_setup(cls): super(FWaaSClientMixin, cls).resource_setup() manager = cls.manager cls.firewalls_client = client.FirewallsClient( manager.auth_provider, CONF.network.catalog_type, CONF.network.region or CONF.identity.region, endpoint_type=CONF.network.endpoint_type, build_interval=CONF.network.build_interval, build_timeout=CONF.network.build_timeout, **manager.default_params) cls.firewall_policies_client = client.FirewallPoliciesClient( manager.auth_provider, CONF.network.catalog_type, CONF.network.region or CONF.identity.region, endpoint_type=CONF.network.endpoint_type, build_interval=CONF.network.build_interval, build_timeout=CONF.network.build_timeout, **manager.default_params) cls.firewall_rules_client = client.FirewallRulesClient( manager.auth_provider, CONF.network.catalog_type, CONF.network.region or CONF.identity.region, endpoint_type=CONF.network.endpoint_type, build_interval=CONF.network.build_interval, build_timeout=CONF.network.build_timeout, **manager.default_params) def create_firewall_rule(self, **kwargs): body = self.firewall_rules_client.create_firewall_rule( name=data_utils.rand_name("fw-rule"), **kwargs) fw_rule = body['firewall_rule'] self.addCleanup(self._delete_wrapper, self.firewall_rules_client.delete_firewall_rule, fw_rule['id']) return fw_rule def create_firewall_policy(self, **kwargs): body = self.firewall_policies_client.create_firewall_policy( name=data_utils.rand_name("fw-policy"), **kwargs) fw_policy = body['firewall_policy'] self.addCleanup(self._delete_wrapper, self.firewall_policies_client.delete_firewall_policy, fw_policy['id']) return fw_policy def create_firewall(self, **kwargs): body = self.firewalls_client.create_firewall( name=data_utils.rand_name("fw"), **kwargs) fw = body['firewall'] self.addCleanup(self._delete_wrapper, self.delete_firewall_and_wait, fw['id']) return fw def delete_firewall_and_wait(self, firewall_id): self.firewalls_client.delete_firewall(firewall_id) self._wait_firewall_while(firewall_id, [p_const.PENDING_DELETE], not_found_ok=True) def _wait_firewall_ready(self, firewall_id): self._wait_firewall_while(firewall_id, [p_const.PENDING_CREATE, p_const.PENDING_UPDATE]) def _wait_firewall_while(self, firewall_id, statuses, not_found_ok=False): start = int(time.time()) if not_found_ok: expected_exceptions = (lib_exc.NotFound) else: expected_exceptions = () while True: try: fw = self.firewalls_client.show_firewall(firewall_id) except expected_exceptions: break status = fw['firewall']['status'] if status not in statuses: break if int(time.time()) - start >= self.firewalls_client.build_timeout: msg = ("Firewall %(firewall)s failed to reach " "non PENDING status (current %(status)s)") % { "firewall": firewall_id, "status": status, } raise exceptions.TimeoutException(msg) time.sleep(1) neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/api/0000775000567000056710000000000012701410073026433 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/api/test_fwaas_extensions.py0000664000567000056710000004053212701407720033435 0ustar jenkinsjenkins00000000000000# Copyright 2014 NEC Corporation. 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 six from tempest import config from tempest import exceptions from tempest.lib.common.utils import data_utils from tempest.lib import exceptions as lib_exc from tempest import test from neutron_fwaas.tests.tempest_plugin.tests.api import base CONF = config.CONF class FWaaSExtensionTestJSON(base.BaseFWaaSTest): """ Tests the following operations in the Neutron API using the REST client for Neutron: List firewall rules Create firewall rule Update firewall rule Delete firewall rule Show firewall rule List firewall policies Create firewall policy Update firewall policy Insert firewall rule to policy Remove firewall rule from policy Insert firewall rule after/before rule in policy Update firewall policy audited attribute Delete firewall policy Show firewall policy List firewall Create firewall Update firewall Delete firewall Show firewall """ @classmethod def resource_setup(cls): super(FWaaSExtensionTestJSON, cls).resource_setup() if not test.is_extension_enabled('fwaas', 'network'): msg = "FWaaS Extension not enabled." raise cls.skipException(msg) def setUp(self): super(FWaaSExtensionTestJSON, self).setUp() self.fw_rule = self.create_firewall_rule(action="allow", protocol="tcp") self.fw_policy = self.create_firewall_policy() def _try_delete_policy(self, policy_id): # delete policy, if it exists try: self.firewall_policies_client.delete_firewall_policy(policy_id) # if policy is not found, this means it was deleted in the test except lib_exc.NotFound: pass def _try_delete_rule(self, rule_id): # delete rule, if it exists try: self.firewall_rules_client.delete_firewall_rule(rule_id) # if rule is not found, this means it was deleted in the test except lib_exc.NotFound: pass def _try_delete_firewall(self, fw_id): # delete firewall, if it exists try: self.firewalls_client.delete_firewall(fw_id) # if firewall is not found, this means it was deleted in the test except lib_exc.NotFound: pass self.firewalls_client.wait_for_resource_deletion(fw_id) def _wait_until_ready(self, fw_id): target_states = ('ACTIVE', 'CREATED') def _wait(): firewall = self.firewalls_client.show_firewall(fw_id) firewall = firewall['firewall'] return firewall['status'] in target_states if not test.call_until_true(_wait, CONF.network.build_timeout, CONF.network.build_interval): m = ("Timed out waiting for firewall %s to reach %s state(s)" % (fw_id, target_states)) raise exceptions.TimeoutException(m) @test.idempotent_id('1b84cf01-9c09-4ce7-bc72-b15e39076468') def test_list_firewall_rules(self): # List firewall rules fw_rules = self.firewall_rules_client.list_firewall_rules() fw_rules = fw_rules['firewall_rules'] self.assertIn((self.fw_rule['id'], self.fw_rule['name'], self.fw_rule['action'], self.fw_rule['protocol'], self.fw_rule['ip_version'], self.fw_rule['enabled']), [(m['id'], m['name'], m['action'], m['protocol'], m['ip_version'], m['enabled']) for m in fw_rules]) @test.idempotent_id('563564f7-7077-4f5e-8cdc-51f37ae5a2b9') def test_create_update_delete_firewall_rule(self): # Create firewall rule body = self.firewall_rules_client.create_firewall_rule( name=data_utils.rand_name("fw-rule"), action="allow", protocol="tcp") fw_rule_id = body['firewall_rule']['id'] # Update firewall rule body = self.firewall_rules_client.update_firewall_rule(fw_rule_id, shared=True) self.assertTrue(body["firewall_rule"]['shared']) # Delete firewall rule self.firewall_rules_client.delete_firewall_rule(fw_rule_id) # Confirm deletion fw_rules = self.firewall_rules_client.list_firewall_rules() self.assertNotIn(fw_rule_id, [m['id'] for m in fw_rules['firewall_rules']]) @test.idempotent_id('3ff8c08e-26ff-4034-ae48-810ed213a998') def test_show_firewall_rule(self): # show a created firewall rule fw_rule = self.firewall_rules_client.show_firewall_rule( self.fw_rule['id']) for key, value in six.iteritems(fw_rule['firewall_rule']): self.assertEqual(self.fw_rule[key], value) @test.idempotent_id('1086dd93-a4c0-4bbb-a1bd-6d4bc62c199f') def test_list_firewall_policies(self): fw_policies = self.firewall_policies_client.list_firewall_policies() fw_policies = fw_policies['firewall_policies'] self.assertIn((self.fw_policy['id'], self.fw_policy['name'], self.fw_policy['firewall_rules']), [(m['id'], m['name'], m['firewall_rules']) for m in fw_policies]) @test.idempotent_id('bbf37b6c-498c-421e-9c95-45897d3ed775') def test_create_update_delete_firewall_policy(self): # Create firewall policy body = self.firewall_policies_client.create_firewall_policy( name=data_utils.rand_name("fw-policy")) fw_policy_id = body['firewall_policy']['id'] self.addCleanup(self._try_delete_policy, fw_policy_id) # Update firewall policy body = self.firewall_policies_client.update_firewall_policy( fw_policy_id, shared=True, name="updated_policy") updated_fw_policy = body["firewall_policy"] self.assertTrue(updated_fw_policy['shared']) self.assertEqual("updated_policy", updated_fw_policy['name']) # Delete firewall policy self.firewall_policies_client.delete_firewall_policy(fw_policy_id) # Confirm deletion fw_policies = self.firewall_policies_client.list_firewall_policies() fw_policies = fw_policies['firewall_policies'] self.assertNotIn(fw_policy_id, [m['id'] for m in fw_policies]) @test.idempotent_id('1df59b3a-517e-41d4-96f6-fc31cf4ecff2') def test_show_firewall_policy(self): # show a created firewall policy fw_policy = self.firewall_policies_client.show_firewall_policy( self.fw_policy['id']) fw_policy = fw_policy['firewall_policy'] for key, value in six.iteritems(fw_policy): self.assertEqual(self.fw_policy[key], value) @test.idempotent_id('02082a03-3cdd-4789-986a-1327dd80bfb7') def test_create_show_delete_firewall(self): # Create tenant network resources required for an ACTIVE firewall network = self.create_network() subnet = self.create_subnet(network) router = self.create_router( data_utils.rand_name('router-'), admin_state_up=True) self.routers_client.add_router_interface(router['id'], subnet_id=subnet['id']) # Create firewall body = self.firewalls_client.create_firewall( name=data_utils.rand_name("firewall"), firewall_policy_id=self.fw_policy['id']) created_firewall = body['firewall'] firewall_id = created_firewall['id'] self.addCleanup(self._try_delete_firewall, firewall_id) # Wait for the firewall resource to become ready self._wait_until_ready(firewall_id) # show a created firewall firewall = self.firewalls_client.show_firewall(firewall_id) firewall = firewall['firewall'] for key, value in six.iteritems(firewall): if key == 'status': continue self.assertEqual(created_firewall[key], value) # list firewall firewalls = self.firewalls_client.list_firewalls() firewalls = firewalls['firewalls'] self.assertIn((created_firewall['id'], created_firewall['name'], created_firewall['firewall_policy_id']), [(m['id'], m['name'], m['firewall_policy_id']) for m in firewalls]) # Delete firewall self.firewalls_client.delete_firewall(firewall_id) @test.idempotent_id('1355cf5c-77d4-4bb9-87d7-e50c194d08b5') def test_firewall_insertion_mode_add_remove_router(self): # Create routers router1 = self.create_router( data_utils.rand_name('router-'), admin_state_up=True) router2 = self.create_router( data_utils.rand_name('router-'), admin_state_up=True) # Create firewall on a router1 body = self.firewalls_client.create_firewall( name=data_utils.rand_name("firewall"), firewall_policy_id=self.fw_policy['id'], router_ids=[router1['id']]) created_firewall = body['firewall'] firewall_id = created_firewall['id'] self.addCleanup(self._try_delete_firewall, firewall_id) self.assertEqual([router1['id']], created_firewall['router_ids']) # Wait for the firewall resource to become ready self._wait_until_ready(firewall_id) # Add router2 to the firewall body = self.firewalls_client.update_firewall( firewall_id, router_ids=[router1['id'], router2['id']]) updated_firewall = body['firewall'] self.assertIn(router2['id'], updated_firewall['router_ids']) self.assertEqual(2, len(updated_firewall['router_ids'])) # Wait for the firewall resource to become ready self._wait_until_ready(firewall_id) # Remove router1 from the firewall body = self.firewalls_client.update_firewall( firewall_id, router_ids=[router2['id']]) updated_firewall = body['firewall'] self.assertNotIn(router1['id'], updated_firewall['router_ids']) self.assertEqual(1, len(updated_firewall['router_ids'])) @test.idempotent_id('c60ceff5-d51f-451d-b6e6-cb983d16ab6b') def test_firewall_insertion_mode_one_firewall_per_router(self): # Create router required for an ACTIVE firewall router = self.create_router( data_utils.rand_name('router1-'), admin_state_up=True) # Create firewall body = self.firewalls_client.create_firewall( name=data_utils.rand_name("firewall"), firewall_policy_id=self.fw_policy['id'], router_ids=[router['id']]) created_firewall = body['firewall'] self.addCleanup(self._try_delete_firewall, created_firewall['id']) # Try to create firewall with the same router self.assertRaisesRegexp( lib_exc.Conflict, "An object with that identifier already exists", self.firewalls_client.create_firewall, name=data_utils.rand_name("firewall"), firewall_policy_id=self.fw_policy['id'], router_ids=[router['id']]) @test.attr(type='smoke') @test.idempotent_id('53305b4b-9897-4e01-87c0-2ae386083180') def test_firewall_rule_insertion_position_removal_rule_from_policy(self): # Create firewall rule body = self.firewall_rules_client.create_firewall_rule( name=data_utils.rand_name("fw-rule"), action="allow", protocol="tcp") fw_rule_id1 = body['firewall_rule']['id'] self.addCleanup(self._try_delete_rule, fw_rule_id1) # Create firewall policy body = self.firewall_policies_client.create_firewall_policy( name=data_utils.rand_name("fw-policy")) fw_policy_id = body['firewall_policy']['id'] self.addCleanup(self._try_delete_policy, fw_policy_id) # Insert rule to firewall policy self.firewall_policies_client.insert_firewall_rule_in_policy( fw_policy_id, fw_rule_id1, '', '') # Verify insertion of rule in policy self.assertIn(fw_rule_id1, self._get_list_fw_rule_ids(fw_policy_id)) # Create another firewall rule body = self.firewall_rules_client.create_firewall_rule( name=data_utils.rand_name("fw-rule"), action="allow", protocol="icmp") fw_rule_id2 = body['firewall_rule']['id'] self.addCleanup(self._try_delete_rule, fw_rule_id2) # Insert rule to firewall policy after the first rule self.firewall_policies_client.insert_firewall_rule_in_policy( fw_policy_id, fw_rule_id2, fw_rule_id1, '') # Verify the position of rule after insertion fw_rule = self.firewall_rules_client.show_firewall_rule( fw_rule_id2) self.assertEqual(int(fw_rule['firewall_rule']['position']), 2) # Remove rule from the firewall policy self.firewall_policies_client.remove_firewall_rule_from_policy( fw_policy_id, fw_rule_id2) # Insert rule to firewall policy before the first rule self.firewall_policies_client.insert_firewall_rule_in_policy( fw_policy_id, fw_rule_id2, '', fw_rule_id1) # Verify the position of rule after insertion fw_rule = self.firewall_rules_client.show_firewall_rule( fw_rule_id2) self.assertEqual(int(fw_rule['firewall_rule']['position']), 1) # Remove rule from the firewall policy self.firewall_policies_client.remove_firewall_rule_from_policy( fw_policy_id, fw_rule_id2) # Verify removal of rule from firewall policy self.assertNotIn(fw_rule_id2, self._get_list_fw_rule_ids(fw_policy_id)) # Remove rule from the firewall policy self.firewall_policies_client.remove_firewall_rule_from_policy( fw_policy_id, fw_rule_id1) # Verify removal of rule from firewall policy self.assertNotIn(fw_rule_id1, self._get_list_fw_rule_ids(fw_policy_id)) def _get_list_fw_rule_ids(self, fw_policy_id): fw_policy = self.firewall_policies_client.show_firewall_policy( fw_policy_id) return [ruleid for ruleid in fw_policy['firewall_policy'] ['firewall_rules']] @test.idempotent_id('8515ca8a-0d2f-4298-b5ff-6f924e4587ca') def test_update_firewall_policy_audited_attribute(self): # Create firewall rule body = self.firewall_rules_client.create_firewall_rule( name=data_utils.rand_name("fw-rule"), action="allow", protocol="icmp") fw_rule_id = body['firewall_rule']['id'] self.addCleanup(self._try_delete_rule, fw_rule_id) # Create firewall policy body = self.firewall_policies_client.create_firewall_policy( name=data_utils.rand_name('fw-policy')) fw_policy_id = body['firewall_policy']['id'] self.addCleanup(self._try_delete_policy, fw_policy_id) self.assertFalse(body['firewall_policy']['audited']) # Update firewall policy audited attribute to true self.firewall_policies_client.update_firewall_policy(fw_policy_id, audited=True) # Insert Firewall rule to firewall policy self.firewall_policies_client.insert_firewall_rule_in_policy( fw_policy_id, fw_rule_id, '', '') body = self.firewall_policies_client.show_firewall_policy( fw_policy_id) self.assertFalse(body['firewall_policy']['audited']) neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/api/__init__.py0000664000567000056710000000000012701407720030537 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/api/base.py0000664000567000056710000000155512701407720027732 0ustar jenkinsjenkins00000000000000# Copyright (c) 2015 Midokura SARL # 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. from tempest.api.network import base from neutron_fwaas.tests.tempest_plugin.tests import fwaas_client class BaseFWaaSTest(fwaas_client.FWaaSClientMixin, base.BaseNetworkTest): _delete_wrapper = base.BaseNetworkTest._try_delete_resource neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/scenario/0000775000567000056710000000000012701410073027465 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/scenario/__init__.py0000664000567000056710000000000012701407720031571 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/scenario/base.py0000664000567000056710000000542312701407720030762 0ustar jenkinsjenkins00000000000000# Copyright (c) 2015 Midokura SARL # 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. from tempest import config from tempest.lib.common import ssh from tempest.lib import exceptions as lib_exc from tempest.scenario import manager from neutron_fwaas.tests.tempest_plugin.tests import fwaas_client CONF = config.CONF class FWaaSScenarioTest(fwaas_client.FWaaSClientMixin, manager.NetworkScenarioTest): _delete_wrapper = manager.NetworkScenarioTest.delete_wrapper def check_connectivity(self, ip_address, username=None, private_key=None, should_connect=True, check_icmp=True, check_ssh=True, check_reverse_icmp_ip=None, should_reverse_connect=True): if should_connect: msg = "Timed out waiting for %s to become reachable" % ip_address else: msg = "ip address %s is reachable" % ip_address if check_icmp: ok = self.ping_ip_address(ip_address, should_succeed=should_connect) self.assertTrue(ok, msg=msg) if check_ssh: connect_timeout = CONF.validation.connect_timeout kwargs = {} if not should_connect: # Use a shorter timeout for negative case kwargs['timeout'] = 1 try: client = ssh.Client(ip_address, username, pkey=private_key, channel_timeout=connect_timeout, **kwargs) client.test_connection_auth() self.assertTrue(should_connect, "Unexpectedly reachable") if check_reverse_icmp_ip: cmd = 'ping -c1 -w1 %s' % check_reverse_icmp_ip try: client.exec_command(cmd) self.assertTrue(should_reverse_connect, "Unexpectedly reachable (reverse)") except lib_exc.SSHExecCommandFailed: if should_reverse_connect: raise except lib_exc.SSHTimeout: if should_connect: raise neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/tests/scenario/test_fwaas.py0000664000567000056710000003707612701407720032221 0ustar jenkinsjenkins00000000000000# Copyright (c) 2015 Midokura SARL # 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 testscenarios from tempest import config from tempest import test from neutron_fwaas.tests.tempest_plugin.tests.scenario import base CONF = config.CONF load_tests = testscenarios.load_tests_apply_scenarios class TestFWaaS(base.FWaaSScenarioTest): scenarios = [ ('without router insersion', { 'router_insertion': False, }), ('with router insersion', { 'router_insertion': True, }), ] def setUp(self): super(TestFWaaS, self).setUp() required_exts = ['fwaas', 'security-group', 'router'] if self.router_insertion: required_exts.append('fwaasrouterinsertion') for ext in required_exts: if not test.is_extension_enabled(ext, 'network'): msg = "%s Extension not enabled." % ext raise self.skipException(msg) self._router_ids = None def _create_server(self, network, security_group=None): keys = self.create_keypair() kwargs = {} if security_group is not None: kwargs['security_groups'] = [{'name': security_group['name']}] server = self.create_server( key_name=keys['name'], networks=[{'uuid': network['id']}], wait_until='ACTIVE', **kwargs) return server, keys def _create_firewall(self, **kwargs): if self._router_ids is not None: kwargs['router_ids'] = self._router_ids return self.create_firewall(**kwargs) def _empty_policy(self, **kwargs): # NOTE(yamamoto): an empty policy would deny all fw_policy = self.create_firewall_policy(firewall_rules=[]) fw = self._create_firewall(firewall_policy_id=fw_policy['id']) self._wait_firewall_ready(fw['id']) return { 'fw': fw, 'fw_policy': fw_policy, } def _all_disabled_rules(self, **kwargs): # NOTE(yamamoto): a policy whose rules are all disabled would deny all fw_rule = self.create_firewall_rule(action="allow", enabled=False) fw_policy = self.create_firewall_policy(firewall_rules=[fw_rule['id']]) fw = self._create_firewall(firewall_policy_id=fw_policy['id']) self._wait_firewall_ready(fw['id']) return { 'fw': fw, 'fw_policy': fw_policy, 'fw_rule': fw_rule, } def _block_ip(self, server1_fixed_ip, server2_fixed_ip, **kwargs): rules = [ # NOTE(yamamoto): The filtering is taken place after # destination ip is rewritten to fixed-ip. self.create_firewall_rule(destination_ip_address=server1_fixed_ip, action="deny"), self.create_firewall_rule(destination_ip_address=server2_fixed_ip, action="deny"), self.create_firewall_rule(action="allow"), ] rule_ids = [r['id'] for r in rules] fw_policy = self.create_firewall_policy(firewall_rules=rule_ids) fw = self._create_firewall(firewall_policy_id=fw_policy['id']) self._wait_firewall_ready(fw['id']) return { 'fw': fw, 'fw_policy': fw_policy, 'server1_fixed_ip': server1_fixed_ip, 'server2_fixed_ip': server2_fixed_ip, } def _block_icmp(self, **kwargs): fw_rule = self.create_firewall_rule( protocol="icmp", action="deny") fw_rule_allow = self.create_firewall_rule( action="allow") fw_policy = self.create_firewall_policy( firewall_rules=[fw_rule['id'], fw_rule_allow['id']]) fw = self._create_firewall(firewall_policy_id=fw_policy['id']) self._wait_firewall_ready(fw['id']) return { 'fw': fw, 'fw_policy': fw_policy, 'fw_rule': fw_rule, } def _block_all_with_default_allow(self, **kwargs): fw_rule = self.create_firewall_rule( action="deny") fw_rule_allow = self.create_firewall_rule( action="allow") fw_policy = self.create_firewall_policy( firewall_rules=[fw_rule['id'], fw_rule_allow['id']]) fw = self._create_firewall(firewall_policy_id=fw_policy['id']) self._wait_firewall_ready(fw['id']) return { 'fw': fw, 'fw_policy': fw_policy, 'fw_rule': fw_rule, } def _admin_disable(self, **kwargs): # NOTE(yamamoto): A firewall with admin_state_up=False would block all fw_rule = self.create_firewall_rule(action="allow") fw_policy = self.create_firewall_policy(firewall_rules=[fw_rule['id']]) fw = self._create_firewall(firewall_policy_id=fw_policy['id'], admin_state_up=False) self._wait_firewall_ready(fw['id']) return { 'fw': fw, 'fw_policy': fw_policy, 'fw_rule': fw_rule, } def _allow_ssh_and_icmp(self, ctx): fw_ssh_rule = self.create_firewall_rule( protocol="tcp", destination_port=22, action="allow") fw_icmp_rule = self.create_firewall_rule( protocol="icmp", action="allow") for rule in [fw_ssh_rule, fw_icmp_rule]: self.firewall_policies_client.insert_firewall_rule_in_policy( firewall_policy_id=ctx['fw_policy']['id'], firewall_rule_id=rule['id'], insert_before=ctx['fw_rule']['id']) self.addCleanup( self._remove_rule_and_wait, firewall_id=ctx['fw']['id'], firewall_policy_id=ctx['fw_policy']['id'], firewall_rule_id=rule['id']) self._wait_firewall_ready(ctx['fw']['id']) def _remove_rule_and_wait(self, firewall_id, firewall_policy_id, firewall_rule_id): self.firewall_policies_client.remove_firewall_rule_from_policy( firewall_policy_id=firewall_policy_id, firewall_rule_id=firewall_rule_id) self._wait_firewall_ready(firewall_id) def _delete_fw(self, ctx): self.delete_firewall_and_wait(ctx['fw']['id']) def _set_admin_up(self, firewall_id, up): self.firewalls_client.update_firewall(firewall_id=firewall_id, admin_state_up=up) self._wait_firewall_ready(firewall_id=firewall_id) def _admin_enable(self, ctx): self._set_admin_up(ctx['fw']['id'], up=True) def _remove_rule(self, ctx): self._remove_rule_and_wait( firewall_id=ctx['fw']['id'], firewall_policy_id=ctx['fw_policy']['id'], firewall_rule_id=ctx['fw_rule']['id']) def _disable_rule(self, ctx): self.firewall_rules_client.update_firewall_rule( firewall_rule_id=ctx['fw_rule']['id'], enabled=False) self._wait_firewall_ready(ctx['fw']['id']) def _allow_ip(self, ctx): self._delete_fw(ctx) server1_fixed_ip = ctx['server1_fixed_ip'] server2_fixed_ip = ctx['server2_fixed_ip'] rules = [ # NOTE(yamamoto): The filtering is taken place after # destination ip is rewritten to fixed-ip. # The return traffic should be allowed regardless # of firewall rules. self.create_firewall_rule( destination_ip_address=server1_fixed_ip, action="allow"), self.create_firewall_rule( destination_ip_address=server2_fixed_ip, action="allow"), ] rule_ids = [r['id'] for r in rules] fw_policy = self.create_firewall_policy(firewall_rules=rule_ids) fw = self._create_firewall(firewall_policy_id=fw_policy['id']) self._wait_firewall_ready(fw['id']) def _confirm_allowed(self, **kwargs): self.check_connectivity(check_reverse_icmp_ip=self._public_gateway_ip, **kwargs) def _confirm_allowed_oneway(self, **kwargs): # Can ping and ssh, but can't ping back to the public gateway. # Same as _confirm_allowed if _public_gateway_ip is None. self.check_connectivity(check_reverse_icmp_ip=self._public_gateway_ip, should_reverse_connect=False, **kwargs) def _confirm_blocked(self, **kwargs): self.check_connectivity(should_connect=False, **kwargs) def _confirm_icmp_blocked_but_tcp(self, **kwargs): self.check_connectivity(should_connect=False, check_ssh=False, **kwargs) self.check_connectivity(check_icmp=False, **kwargs) def _create_topology(self): """Create a topology for testing +--------+ +-----------+ |"server"| | "subnet" | | VM +-------------+ "network" | +--------+ +----+------+ | | router interface port +----+-----+ | "router" | +----+-----+ | router gateway port | | +----+------------------+ | existing network | | ("public_network_id") | +-----------------------+ """ public_network_id = CONF.network.public_network_id network, subnet, router = self.create_networks() security_group = self._create_security_group() server, keys = self._create_server(network, security_group=security_group) private_key = keys['private_key'] server_floating_ip = self.create_floating_ip(server, public_network_id) fixed_ip = server['addresses'].values()[0][0]['addr'] floating_ip = server_floating_ip.floating_ip_address return fixed_ip, floating_ip, private_key, router def _get_public_gateway_ip(self): self._public_gateway_ip = None router = self._get_router() ext_gw_info = router['external_gateway_info'] ext_fixed_ips = ext_gw_info['external_fixed_ips'] for ip in ext_fixed_ips: subnet_id = ip['subnet_id'] res = self.admin_manager.subnets_client.show_subnet(subnet_id) subnet = res['subnet'] # REVISIT(yamamoto): IPv4 assumption if subnet['ip_version'] == 4: self._public_gateway_ip = subnet['gateway_ip'] return def _test_firewall_basic(self, block, allow=None, confirm_allowed=None, confirm_blocked=None): if allow is None: allow = self._delete_fw if confirm_allowed is None: confirm_allowed = self._confirm_allowed if confirm_blocked is None: confirm_blocked = self._confirm_blocked ssh_login = CONF.validation.image_ssh_user if self.router_insertion and CONF.network.public_router_id: # NOTE(yamamoto): If public_router_id is configured # router1 and router2 will be the same router. msg = "This test assumes no public_router_id configured" raise self.skipException(msg) server1_fixed_ip, server1_floating_ip, private_key1, router1 = \ self._create_topology() server2_fixed_ip, server2_floating_ip, private_key2, router2 = \ self._create_topology() self._get_public_gateway_ip() if self.router_insertion: # Specify the router when creating a firewall and ensures that # the other router (router2) is not affected by the firewall self._router_ids = [router1['id']] confirm_allowed2 = self.check_connectivity confirm_blocked2 = self.check_connectivity else: # Without router insertion, all routers should be affected # equally confirm_allowed2 = confirm_allowed confirm_blocked2 = confirm_blocked self.check_connectivity(ip_address=server1_floating_ip, username=ssh_login, private_key=private_key1) self.check_connectivity(ip_address=server2_floating_ip, username=ssh_login, private_key=private_key2) ctx = block(server1_fixed_ip=server1_fixed_ip, server1_floating_ip=server1_floating_ip, server2_fixed_ip=server2_fixed_ip, server2_floating_ip=server2_floating_ip) confirm_blocked(ip_address=server1_floating_ip, username=ssh_login, private_key=private_key1) confirm_blocked2(ip_address=server2_floating_ip, username=ssh_login, private_key=private_key2) allow(ctx) confirm_allowed(ip_address=server1_floating_ip, username=ssh_login, private_key=private_key1) confirm_allowed2(ip_address=server2_floating_ip, username=ssh_login, private_key=private_key2) @test.idempotent_id('f970f6b3-6541-47ac-a9ea-f769be1e21a8') def test_firewall_block_ip(self): self._test_firewall_basic(block=self._block_ip, allow=self._allow_ip, confirm_allowed=self._confirm_allowed_oneway) @test.idempotent_id('b985d010-994a-4055-bd5c-9e961464ccde') def test_firewall_block_icmp(self): self._test_firewall_basic( block=self._block_icmp, confirm_blocked=self._confirm_icmp_blocked_but_tcp) @test.idempotent_id('ca473af0-26f9-4fad-9550-1c34371c900e') def test_firewall_insert_rule(self): self._test_firewall_basic( block=self._block_icmp, allow=self._allow_ssh_and_icmp, confirm_blocked=self._confirm_icmp_blocked_but_tcp) @test.idempotent_id('54a937a6-cecf-444c-b3f9-b67a1c1b7411') def test_firewall_remove_rule(self): self._test_firewall_basic(block=self._block_all_with_default_allow, allow=self._remove_rule) @test.idempotent_id('12a18776-9b60-4479-9988-f45971c96a92') def test_firewall_disable_rule(self): self._test_firewall_basic(block=self._block_all_with_default_allow, allow=self._disable_rule) @test.idempotent_id('a2a58c1f-49ad-4b5f-9463-e746b9efe08a') def test_firewall_empty_policy(self): self._test_firewall_basic(block=self._empty_policy) @test.idempotent_id('477a47e0-5156-4784-9417-f77970d85c36') def test_firewall_all_disabled_rules(self): self._test_firewall_basic(block=self._all_disabled_rules) @test.idempotent_id('a83f51c5-1a18-4d2a-a778-c368e4d95c29') def test_firewall_admin_disable(self): self._test_firewall_basic(block=self._admin_disable, allow=self._admin_enable) neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/__init__.py0000664000567000056710000000000012701407720026624 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/services/0000775000567000056710000000000012701410073026343 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/services/__init__.py0000664000567000056710000000000012701407720030447 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/tempest_plugin/services/client.py0000664000567000056710000001064712701407720030210 0ustar jenkinsjenkins00000000000000# Copyright (c) 2015 Midokura SARL # 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. from tempest.lib import exceptions as lib_exc from tempest.lib.services.network import base class FirewallsClient(base.BaseNetworkClient): def create_firewall(self, **kwargs): uri = '/fw/firewalls' post_data = {'firewall': kwargs} return self.create_resource(uri, post_data) def update_firewall(self, firewall_id, **kwargs): uri = '/fw/firewalls/%s' % firewall_id post_data = {'firewall': kwargs} return self.update_resource(uri, post_data) def show_firewall(self, firewall_id, **fields): uri = '/fw/firewalls/%s' % firewall_id return self.show_resource(uri, **fields) def delete_firewall(self, firewall_id): uri = '/fw/firewalls/%s' % firewall_id return self.delete_resource(uri) def list_firewalls(self, **filters): uri = '/fw/firewalls' return self.list_resources(uri, **filters) def is_resource_deleted(self, id): try: self.show_firewall(id) except lib_exc.NotFound: return True return False @property def resource_type(self): """Returns the primary type of resource this client works with.""" return 'firewall' class FirewallRulesClient(base.BaseNetworkClient): def create_firewall_rule(self, **kwargs): uri = '/fw/firewall_rules' post_data = {'firewall_rule': kwargs} return self.create_resource(uri, post_data) def update_firewall_rule(self, firewall_rule_id, **kwargs): uri = '/fw/firewall_rules/%s' % firewall_rule_id post_data = {'firewall_rule': kwargs} return self.update_resource(uri, post_data) def show_firewall_rule(self, firewall_rule_id, **fields): uri = '/fw/firewall_rules/%s' % firewall_rule_id return self.show_resource(uri, **fields) def delete_firewall_rule(self, firewall_rule_id): uri = '/fw/firewall_rules/%s' % firewall_rule_id return self.delete_resource(uri) def list_firewall_rules(self, **filters): uri = '/fw/firewall_rules' return self.list_resources(uri, **filters) class FirewallPoliciesClient(base.BaseNetworkClient): def create_firewall_policy(self, **kwargs): uri = '/fw/firewall_policies' post_data = {'firewall_policy': kwargs} return self.create_resource(uri, post_data) def update_firewall_policy(self, firewall_policy_id, **kwargs): uri = '/fw/firewall_policies/%s' % firewall_policy_id post_data = {'firewall_policy': kwargs} return self.update_resource(uri, post_data) def show_firewall_policy(self, firewall_policy_id, **fields): uri = '/fw/firewall_policies/%s' % firewall_policy_id return self.show_resource(uri, **fields) def delete_firewall_policy(self, firewall_policy_id): uri = '/fw/firewall_policies/%s' % firewall_policy_id return self.delete_resource(uri) def list_firewall_policies(self, **filters): uri = '/fw/firewall_policies' return self.list_resources(uri, **filters) def insert_firewall_rule_in_policy(self, firewall_policy_id, firewall_rule_id, insert_after='', insert_before=''): uri = '/fw/firewall_policies/%s/insert_rule' % firewall_policy_id data = { 'firewall_rule_id': firewall_rule_id, 'insert_after': insert_after, 'insert_before': insert_before, } return self.update_resource(uri, data) def remove_firewall_rule_from_policy(self, firewall_policy_id, firewall_rule_id): uri = '/fw/firewall_policies/%s/remove_rule' % firewall_policy_id data = { 'firewall_rule_id': firewall_rule_id, } return self.update_resource(uri, data) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/0000775000567000056710000000000012701410073022440 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/__init__.py0000664000567000056710000000000012701407720024544 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/0000775000567000056710000000000012701410073024263 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/0000775000567000056710000000000012701410073026070 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/__init__.py0000664000567000056710000000000012701407720030174 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/plugins/0000775000567000056710000000000012701410073027551 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/plugins/cisco/0000775000567000056710000000000012701410073030651 5ustar jenkinsjenkins00000000000000././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/plugins/cisco/test_cisco_fwaas_plugin.pyneutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/plugins/cisco/test_cisco_fwaas_plugin0000664000567000056710000004260612701407720035507 0ustar jenkinsjenkins00000000000000# Copyright 2015 Cisco Systems, 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 neutron.api.v2 import attributes as attr from neutron import context from neutron import manager from neutron.plugins.common import constants as const from neutron.tests.unit.extensions import test_l3 as test_l3_plugin import six import neutron_fwaas from neutron_fwaas.db.cisco import cisco_fwaas_db as csrfw_db from neutron_fwaas.extensions.cisco import csr_firewall_insertion from neutron_fwaas.extensions import firewall from neutron_fwaas.services.firewall.plugins.cisco import cisco_fwaas_plugin from neutron_fwaas.tests.unit.db.firewall import ( test_firewall_db as test_db_firewall) from oslo_config import cfg # We need the test_l3_plugin to ensure we have a valid port_id corresponding # to a router interface. CORE_PLUGIN_KLASS = 'neutron.tests.unit.extensions.test_l3.TestNoL3NatPlugin' L3_PLUGIN_KLASS = ( 'neutron.tests.unit.extensions.test_l3.TestL3NatServicePlugin') # the plugin under test CSR_FW_PLUGIN_KLASS = ( "neutron_fwaas.services.firewall.plugins.cisco.cisco_fwaas_plugin." "CSRFirewallPlugin" ) extensions_path = neutron_fwaas.extensions.__path__[0] + '/cisco' class CSR1kvFirewallTestExtensionManager( test_l3_plugin.L3TestExtensionManager): def get_resources(self): res = super(CSR1kvFirewallTestExtensionManager, self).get_resources() firewall.RESOURCE_ATTRIBUTE_MAP['firewalls'].update( csr_firewall_insertion.EXTENDED_ATTRIBUTES_2_0['firewalls']) return res + firewall.Firewall.get_resources() def get_actions(self): return [] def get_request_extensions(self): return [] class CSR1kvFirewallTestCaseBase(test_db_firewall.FirewallPluginDbTestCase, test_l3_plugin.L3NatTestCaseMixin): def setUp(self, core_plugin=None, l3_plugin=None, fw_plugin=None, ext_mgr=None): self.agentapi_delf_p = mock.patch(test_db_firewall.DELETEFW_PATH, create=True, new=test_db_firewall.FakeAgentApi().delete_firewall) self.agentapi_delf_p.start() cfg.CONF.set_override('api_extensions_path', extensions_path) # for these tests we need to enable overlapping ips cfg.CONF.set_default('allow_overlapping_ips', True) cfg.CONF.set_default('max_routes', 3) self.saved_attr_map = {} for resource, attrs in six.iteritems(attr.RESOURCE_ATTRIBUTE_MAP): self.saved_attr_map[resource] = attrs.copy() if not core_plugin: core_plugin = CORE_PLUGIN_KLASS if l3_plugin is None: l3_plugin = L3_PLUGIN_KLASS if not fw_plugin: fw_plugin = CSR_FW_PLUGIN_KLASS service_plugins = {'l3_plugin_name': l3_plugin, 'fw_plugin_name': fw_plugin} if not ext_mgr: ext_mgr = CSR1kvFirewallTestExtensionManager() super(test_db_firewall.FirewallPluginDbTestCase, self).setUp( plugin=core_plugin, service_plugins=service_plugins, ext_mgr=ext_mgr) self.core_plugin = manager.NeutronManager.get_plugin() self.l3_plugin = manager.NeutronManager.get_service_plugins().get( const.L3_ROUTER_NAT) self.plugin = manager.NeutronManager.get_service_plugins().get( const.FIREWALL) self.callbacks = self.plugin.endpoints[0] self.setup_notification_driver() def restore_attribute_map(self): # Remove the csrfirewallinsertion extension firewall.RESOURCE_ATTRIBUTE_MAP['firewalls'].pop('port_id') firewall.RESOURCE_ATTRIBUTE_MAP['firewalls'].pop('direction') # Restore the original RESOURCE_ATTRIBUTE_MAP attr.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map def tearDown(self): self.restore_attribute_map() super(CSR1kvFirewallTestCaseBase, self).tearDown() def _create_firewall(self, fmt, name, description, firewall_policy_id=None, admin_state_up=True, expected_res_status=None, **kwargs): tenant_id = kwargs.get('tenant_id', self._tenant_id) port_id = kwargs.get('port_id') direction = kwargs.get('direction') if firewall_policy_id is None: res = self._create_firewall_policy(fmt, 'fwp', description="firewall_policy", shared=True, firewall_rules=[], audited=True) firewall_policy = self.deserialize(fmt or self.fmt, res) firewall_policy_id = firewall_policy["firewall_policy"]["id"] data = {'firewall': {'name': name, 'description': description, 'firewall_policy_id': firewall_policy_id, 'admin_state_up': admin_state_up, 'tenant_id': tenant_id}} if port_id: data['firewall']['port_id'] = port_id if direction: data['firewall']['direction'] = direction firewall_req = self.new_create_request('firewalls', data, fmt) firewall_res = firewall_req.get_response(self.ext_api) if expected_res_status: self.assertEqual(expected_res_status, firewall_res.status_int) return firewall_res class TestCiscoFirewallCallbacks(test_db_firewall.FirewallPluginDbTestCase): def setUp(self): super(TestCiscoFirewallCallbacks, self).setUp() self.plugin = cisco_fwaas_plugin.CSRFirewallPlugin() self.callbacks = self.plugin.endpoints[0] def test_firewall_deleted(self): ctx = context.get_admin_context() with self.firewall_policy(do_delete=False) as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP, do_delete=False) as fw: fw_id = fw['firewall']['id'] with ctx.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(ctx, fw_id) fw_db['status'] = const.PENDING_DELETE ctx.session.flush() res = self.callbacks.firewall_deleted(ctx, fw_id, host='dummy') self.assertTrue(res) self.assertRaises(firewall.FirewallNotFound, self.plugin.get_firewall, ctx, fw_id) class TestCiscoFirewallPlugin(CSR1kvFirewallTestCaseBase, csrfw_db.CiscoFirewall_db_mixin): def setUp(self): super(TestCiscoFirewallPlugin, self).setUp() self.fake_vendor_ext = { 'host_mngt_ip': '1.2.3.4', 'host_usr_nm': 'admin', 'host_usr_pw': 'cisco', 'if_list': {'port': {'id': 0, 'hosting_info': 'csr'}, 'direction': 'default'} } self.mock_get_hosting_info = mock.patch.object( self.plugin, '_get_hosting_info').start() def test_create_csr_firewall(self): with self.router(tenant_id=self._tenant_id) as r,\ self.subnet() as s: body = self._router_interface_action( 'add', r['router']['id'], s['subnet']['id'], None) port_id = body['port_id'] self.fake_vendor_ext['if_list']['port']['id'] = port_id self.fake_vendor_ext['if_list']['direction'] = 'inside' self.mock_get_hosting_info.return_value = self.fake_vendor_ext with self.firewall(port_id=body['port_id'], direction='inside') as fw: ctx = context.get_admin_context() fw_id = fw['firewall']['id'] csrfw = self.lookup_firewall_csr_association( ctx, fw_id) # cant be in PENDING_XXX state for delete clean up with ctx.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(ctx, fw_id) fw_db['status'] = const.ACTIVE ctx.session.flush() self._router_interface_action( 'remove', r['router']['id'], s['subnet']['id'], None) self.assertEqual('firewall_1', fw['firewall']['name']) self.assertEqual(port_id, csrfw['port_id']) self.assertEqual('inside', csrfw['direction']) def test_create_csr_firewall_only_port_id_specified(self): with self.router(tenant_id=self._tenant_id) as r, \ self.subnet() as s: body = self._router_interface_action( 'add', r['router']['id'], s['subnet']['id'], None) port_id = body['port_id'] self.fake_vendor_ext['if_list']['port']['id'] = port_id self.fake_vendor_ext['if_list']['direction'] = None self.mock_get_hosting_info.return_value = self.fake_vendor_ext with self.firewall(port_id=body['port_id']) as fw: ctx = context.get_admin_context() fw_id = fw['firewall']['id'] csrfw = self.lookup_firewall_csr_association( ctx, fw_id) # cant be in PENDING_XXX state for delete clean up with ctx.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(ctx, fw_id) fw_db['status'] = const.ACTIVE ctx.session.flush() self._router_interface_action( 'remove', r['router']['id'], s['subnet']['id'], None) self.assertEqual('firewall_1', fw['firewall']['name']) self.assertEqual(port_id, csrfw['port_id']) self.assertIsNone(csrfw['direction']) def test_create_csr_firewall_no_port_id_no_direction_specified(self): with self.firewall() as fw: ctx = context.get_admin_context() fw_id = fw['firewall']['id'] csrfw = self.lookup_firewall_csr_association( ctx, fw_id) # cant be in PENDING_XXX state for delete clean up with ctx.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(ctx, fw_id) fw_db['status'] = const.ACTIVE ctx.session.flush() self.assertEqual('firewall_1', fw['firewall']['name']) self.assertIsNone(csrfw) def test_update_csr_firewall(self): with self.router(tenant_id=self._tenant_id) as r, \ self.subnet() as s: body = self._router_interface_action( 'add', r['router']['id'], s['subnet']['id'], None) port_id = body['port_id'] self.fake_vendor_ext['if_list']['port']['id'] = port_id self.fake_vendor_ext['if_list']['direction'] = 'inside' self.mock_get_hosting_info.return_value = self.fake_vendor_ext with self.firewall(port_id=body['port_id'], direction='both') as fw: ctx = context.get_admin_context() fw_id = fw['firewall']['id'] csrfw = self.lookup_firewall_csr_association( ctx, fw_id) status_data = {'acl_id': 100} res = self.callbacks.set_firewall_status(ctx, fw_id, const.ACTIVE, status_data) # update direction on same port data = {'firewall': {'name': 'firewall_2', 'direction': 'both', 'port_id': port_id}} req = self.new_update_request('firewalls', data, fw['firewall']['id']) req.environ['neutron.context'] = context.Context( '', 'test-tenant') res = self.deserialize(self.fmt, req.get_response(self.ext_api)) csrfw = self.lookup_firewall_csr_association(ctx, fw['firewall']['id']) self.assertEqual('firewall_2', res['firewall']['name']) self.assertEqual(port_id, csrfw['port_id']) self.assertEqual('both', csrfw['direction']) # cant be in PENDING_XXX state for delete clean up with ctx.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(ctx, fw_id) fw_db['status'] = const.ACTIVE ctx.session.flush() self._router_interface_action( 'remove', r['router']['id'], s['subnet']['id'], None) def test_update_csr_firewall_port_id(self): with self.router(tenant_id=self._tenant_id) as r, \ self.subnet() as s1, \ self.subnet(cidr='20.0.0.0/24') as s2: body = self._router_interface_action( 'add', r['router']['id'], s1['subnet']['id'], None) port_id1 = body['port_id'] body = self._router_interface_action( 'add', r['router']['id'], s2['subnet']['id'], None) port_id2 = body['port_id'] self.fake_vendor_ext['if_list']['port']['id'] = port_id1 self.fake_vendor_ext['if_list']['direction'] = 'inside' self.mock_get_hosting_info.return_value = self.fake_vendor_ext with self.firewall(port_id=port_id1, direction='both') as fw: ctx = context.get_admin_context() fw_id = fw['firewall']['id'] status_data = {'acl_id': 100} res = self.callbacks.set_firewall_status(ctx, fw_id, const.ACTIVE, status_data) # update direction on same port data = {'firewall': {'name': 'firewall_2', 'direction': 'both', 'port_id': port_id2}} req = self.new_update_request('firewalls', data, fw['firewall']['id']) req.environ['neutron.context'] = context.Context( '', 'test-tenant') res = self.deserialize(self.fmt, req.get_response(self.ext_api)) csrfw = self.lookup_firewall_csr_association(ctx, fw['firewall']['id']) self.assertEqual('firewall_2', res['firewall']['name']) self.assertEqual(port_id2, csrfw['port_id']) self.assertEqual('both', csrfw['direction']) # cant be in PENDING_XXX state for delete clean up with ctx.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(ctx, fw_id) fw_db['status'] = const.ACTIVE ctx.session.flush() self._router_interface_action('remove', r['router']['id'], s1['subnet']['id'], None) self._router_interface_action( 'remove', r['router']['id'], s2['subnet']['id'], None) def test_delete_csr_firewall(self): with self.router(tenant_id=self._tenant_id) as r, \ self.subnet() as s: body = self._router_interface_action( 'add', r['router']['id'], s['subnet']['id'], None) port_id = body['port_id'] self.fake_vendor_ext['if_list']['port']['id'] = port_id self.fake_vendor_ext['if_list']['direction'] = 'inside' self.mock_get_hosting_info.return_value = self.fake_vendor_ext with self.firewall(port_id=port_id, direction='inside', do_delete=False) as fw: fw_id = fw['firewall']['id'] ctx = context.get_admin_context() csrfw = self.lookup_firewall_csr_association(ctx, fw_id) self.assertIsNotNone(csrfw) req = self.new_delete_request('firewalls', fw_id) req.get_response(self.ext_api) with ctx.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(ctx, fw_id) fw_db['status'] = const.PENDING_DELETE ctx.session.flush() self.callbacks.firewall_deleted(ctx, fw_id) csrfw = self.lookup_firewall_csr_association(ctx, fw_id) self.assertIsNone(csrfw) self._router_interface_action( 'remove', r['router']['id'], s['subnet']['id'], None) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/plugins/cisco/__init__.py0000664000567000056710000000000012701407720032755 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/plugins/__init__.py0000664000567000056710000000000012701407720031655 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/0000775000567000056710000000000012701410073027546 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/linux/0000775000567000056710000000000012701410073030705 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/linux/test_iptables_fwaas.py0000664000567000056710000003066112701407720035315 0ustar jenkinsjenkins00000000000000# 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. import mock from oslo_config import cfg from neutron.agent.common import config as a_cfg from neutron.tests import base from neutron.tests.unit.api.v2 import test_base as test_api_v2 import neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas as fwaas _uuid = test_api_v2._uuid FAKE_SRC_PREFIX = '10.0.0.0/24' FAKE_DST_PREFIX = '20.0.0.0/24' FAKE_PROTOCOL = 'tcp' FAKE_SRC_PORT = 5000 FAKE_DST_PORT = 22 FAKE_FW_ID = 'fake-fw-uuid' class IptablesFwaasTestCase(base.BaseTestCase): def setUp(self): super(IptablesFwaasTestCase, self).setUp() cfg.CONF.register_opts(a_cfg.ROOT_HELPER_OPTS, 'AGENT') self.utils_exec_p = mock.patch( 'neutron.agent.linux.utils.execute') self.utils_exec = self.utils_exec_p.start() self.iptables_cls_p = mock.patch( 'neutron.agent.linux.iptables_manager.IptablesManager') self.iptables_cls_p.start() self.firewall = fwaas.IptablesFwaasDriver() def _fake_rules_v4(self, fwid, apply_list): rule_list = [] rule1 = {'enabled': True, 'action': 'allow', 'ip_version': 4, 'protocol': 'tcp', 'destination_port': '80', 'source_ip_address': '10.24.4.2'} rule2 = {'enabled': True, 'action': 'deny', 'ip_version': 4, 'protocol': 'tcp', 'destination_port': '22'} rule3 = {'enabled': True, 'action': 'reject', 'ip_version': 4, 'protocol': 'tcp', 'destination_port': '23'} ingress_chain = ('iv4%s' % fwid)[:11] egress_chain = ('ov4%s' % fwid)[:11] for router_info_inst in apply_list: v4filter_inst = router_info_inst.iptables_manager.ipv4['filter'] v4filter_inst.chains.append(ingress_chain) v4filter_inst.chains.append(egress_chain) rule_list.append(rule1) rule_list.append(rule2) rule_list.append(rule3) return rule_list def _fake_firewall_no_rule(self): rule_list = [] fw_inst = {'id': FAKE_FW_ID, 'admin_state_up': True, 'tenant_id': 'tenant-uuid', 'firewall_rule_list': rule_list} return fw_inst def _fake_firewall(self, rule_list): fw_inst = {'id': FAKE_FW_ID, 'admin_state_up': True, 'tenant_id': 'tenant-uuid', 'firewall_rule_list': rule_list} return fw_inst def _fake_firewall_with_admin_down(self, rule_list): fw_inst = {'id': FAKE_FW_ID, 'admin_state_up': False, 'tenant_id': 'tenant-uuid', 'firewall_rule_list': rule_list} return fw_inst def _fake_apply_list(self, router_count=1, distributed=False, distributed_mode=None): apply_list = [] while router_count > 0: iptables_inst = mock.Mock() if distributed is not None: router_inst = {'distributed': distributed} else: router_inst = {} v4filter_inst = mock.Mock() v6filter_inst = mock.Mock() v4filter_inst.chains = [] v6filter_inst.chains = [] iptables_inst.ipv4 = {'filter': v4filter_inst} iptables_inst.ipv6 = {'filter': v6filter_inst} router_info_inst = mock.Mock() router_info_inst.iptables_manager = iptables_inst router_info_inst.snat_iptables_manager = iptables_inst if distributed_mode == 'dvr': router_info_inst.dist_fip_count = 1 router_info_inst.router = router_inst apply_list.append(router_info_inst) router_count -= 1 return apply_list def _setup_firewall_with_rules(self, func, router_count=1, distributed=False, distributed_mode=None): apply_list = self._fake_apply_list(router_count=router_count, distributed=distributed, distributed_mode=distributed_mode) rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list) firewall = self._fake_firewall(rule_list) if distributed: if distributed_mode == 'dvr_snat': if_prefix = 'sg-+' if distributed_mode == 'dvr': if_prefix = 'rfp-+' else: if_prefix = 'qr-+' distributed_mode = 'legacy' func(distributed_mode, apply_list, firewall) invalid_rule = '-m state --state INVALID -j DROP' est_rule = '-m state --state ESTABLISHED,RELATED -j ACCEPT' rule1 = '-p tcp --dport 80 -s 10.24.4.2 -j ACCEPT' rule2 = '-p tcp --dport 22 -j DROP' rule3 = '-p tcp --dport 23 -j REJECT' ingress_chain = 'iv4%s' % firewall['id'] egress_chain = 'ov4%s' % firewall['id'] bname = fwaas.iptables_manager.binary_name ipt_mgr_ichain = '%s-%s' % (bname, ingress_chain[:11]) ipt_mgr_echain = '%s-%s' % (bname, egress_chain[:11]) for router_info_inst in apply_list: v4filter_inst = router_info_inst.iptables_manager.ipv4['filter'] calls = [mock.call.remove_chain('iv4fake-fw-uuid'), mock.call.remove_chain('ov4fake-fw-uuid'), mock.call.remove_chain('fwaas-default-policy'), mock.call.add_chain('fwaas-default-policy'), mock.call.add_rule('fwaas-default-policy', '-j DROP'), mock.call.add_chain(ingress_chain), mock.call.add_rule(ingress_chain, invalid_rule), mock.call.add_rule(ingress_chain, est_rule), mock.call.add_chain(egress_chain), mock.call.add_rule(egress_chain, invalid_rule), mock.call.add_rule(egress_chain, est_rule), mock.call.add_rule(ingress_chain, rule1), mock.call.add_rule(egress_chain, rule1), mock.call.add_rule(ingress_chain, rule2), mock.call.add_rule(egress_chain, rule2), mock.call.add_rule(ingress_chain, rule3), mock.call.add_rule(egress_chain, rule3), mock.call.add_rule('FORWARD', '-o %s -j %s' % (if_prefix, ipt_mgr_ichain)), mock.call.add_rule('FORWARD', '-i %s -j %s' % (if_prefix, ipt_mgr_echain)), mock.call.add_rule('FORWARD', '-o %s -j %s-fwaas-defau' % (if_prefix, bname)), mock.call.add_rule('FORWARD', '-i %s -j %s-fwaas-defau' % (if_prefix, bname))] v4filter_inst.assert_has_calls(calls) def test_create_firewall_no_rules(self): apply_list = self._fake_apply_list() firewall = self._fake_firewall_no_rule() self.firewall.create_firewall('legacy', apply_list, firewall) invalid_rule = '-m state --state INVALID -j DROP' est_rule = '-m state --state ESTABLISHED,RELATED -j ACCEPT' bname = fwaas.iptables_manager.binary_name for ip_version in (4, 6): ingress_chain = ('iv%s%s' % (ip_version, firewall['id'])) egress_chain = ('ov%s%s' % (ip_version, firewall['id'])) calls = [mock.call.remove_chain( 'iv%sfake-fw-uuid' % ip_version), mock.call.remove_chain( 'ov%sfake-fw-uuid' % ip_version), mock.call.remove_chain('fwaas-default-policy'), mock.call.add_chain('fwaas-default-policy'), mock.call.add_rule('fwaas-default-policy', '-j DROP'), mock.call.add_chain(ingress_chain), mock.call.add_rule(ingress_chain, invalid_rule), mock.call.add_rule(ingress_chain, est_rule), mock.call.add_chain(egress_chain), mock.call.add_rule(egress_chain, invalid_rule), mock.call.add_rule(egress_chain, est_rule), mock.call.add_rule('FORWARD', '-o qr-+ -j %s-fwaas-defau' % bname), mock.call.add_rule('FORWARD', '-i qr-+ -j %s-fwaas-defau' % bname)] if ip_version == 4: v4filter_inst = apply_list[0].iptables_manager.ipv4['filter'] v4filter_inst.assert_has_calls(calls) else: v6filter_inst = apply_list[0].iptables_manager.ipv6['filter'] v6filter_inst.assert_has_calls(calls) def test_create_firewall_with_rules(self): self._setup_firewall_with_rules(self.firewall.create_firewall) def test_create_firewall_with_rules_without_distributed_attr(self): self._setup_firewall_with_rules(self.firewall.create_firewall, distributed=None) def test_create_firewall_with_rules_two_routers(self): self._setup_firewall_with_rules(self.firewall.create_firewall, router_count=2) def test_update_firewall_with_rules(self): self._setup_firewall_with_rules(self.firewall.update_firewall) def test_update_firewall_with_rules_without_distributed_attr(self): self._setup_firewall_with_rules(self.firewall.update_firewall, distributed=None) def _test_delete_firewall(self, distributed=False): apply_list = self._fake_apply_list(distributed=distributed) firewall = self._fake_firewall_no_rule() self.firewall.delete_firewall('legacy', apply_list, firewall) ingress_chain = 'iv4%s' % firewall['id'] egress_chain = 'ov4%s' % firewall['id'] calls = [mock.call.remove_chain(ingress_chain), mock.call.remove_chain(egress_chain), mock.call.remove_chain('fwaas-default-policy')] apply_list[0].iptables_manager.ipv4['filter'].assert_has_calls(calls) def test_delete_firewall(self): self._test_delete_firewall() def test_delete_firewall_without_distributed_attr(self): self._test_delete_firewall(distributed=None) def test_create_firewall_with_admin_down(self): apply_list = self._fake_apply_list() rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list) firewall = self._fake_firewall_with_admin_down(rule_list) self.firewall.create_firewall('legacy', apply_list, firewall) calls = [mock.call.remove_chain('iv4fake-fw-uuid'), mock.call.remove_chain('ov4fake-fw-uuid'), mock.call.remove_chain('fwaas-default-policy'), mock.call.add_chain('fwaas-default-policy'), mock.call.add_rule('fwaas-default-policy', '-j DROP')] apply_list[0].iptables_manager.ipv4['filter'].assert_has_calls(calls) def test_create_firewall_with_rules_dvr_snat(self): self._setup_firewall_with_rules(self.firewall.create_firewall, distributed=True, distributed_mode='dvr_snat') def test_update_firewall_with_rules_dvr_snat(self): self._setup_firewall_with_rules(self.firewall.update_firewall, distributed=True, distributed_mode='dvr_snat') def test_create_firewall_with_rules_dvr(self): self._setup_firewall_with_rules(self.firewall.create_firewall, distributed=True, distributed_mode='dvr') def test_update_firewall_with_rules_dvr(self): self._setup_firewall_with_rules(self.firewall.update_firewall, distributed=True, distributed_mode='dvr') neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/linux/__init__.py0000664000567000056710000000000012701407720033011 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/mcafee/0000775000567000056710000000000012701410073030766 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/mcafee/__init__.py0000664000567000056710000000000012701407720033072 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/mcafee/test_ngfw_fwaas.py0000664000567000056710000002135312701407720034532 0ustar jenkinsjenkins00000000000000# Copyright 2015 Intel Corporation. # 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 import neutron_fwaas.services.firewall.drivers.mcafee as mcafee import neutron_fwaas.services.firewall.drivers.mcafee.ngfw_fwaas as fwaas from neutron.tests import base FAKE_FIREWALL_ID = 'firewall_id' FAKE_POLICY_ID = 'policy_id' FAKE_TENANT_ID = 'tenant_id' FAKE_ROUTER_ID = 'router_id' FAKE_FW_NAME = 'fw_name' class NGFWFwaasTestCase(base.BaseTestCase): def setUp(self): super(NGFWFwaasTestCase, self).setUp() self.firewall = fwaas.NgfwFwaasDriver() self.rule_list = self._fake_ipv4_rules() self.apply_list = self._fake_apply_list() self.post_return = mock.MagicMock() self.tmp_ref = 'temp_ref' self.post_return.headers = {'location': self.tmp_ref} # we generate the policy name by formatting the ids of firewall, # policy, router self.policy_name = "%s_%s_%s" % ( FAKE_FIREWALL_ID[0:7], FAKE_POLICY_ID[0:7], FAKE_ROUTER_ID[0:7]) def _fake_ipv4_rules(self): rule1 = {'action': 'deny', 'description': '', 'destination_ip_address': None, 'destination_port': '23', 'enabled': True, 'firewall_policy_id': FAKE_POLICY_ID, 'id': '1', 'ip_version': 4, 'name': 'a2', 'position': 1, 'protocol': 'udp', 'shared': False, 'source_ip_address': None, 'source_port': '23', 'tenant_id': FAKE_TENANT_ID} rule2 = {'action': 'deny', 'description': '', 'destination_ip_address': None, 'destination_port': None, 'enabled': True, 'firewall_policy_id': FAKE_POLICY_ID, 'id': '2', 'ip_version': 4, 'name': 'a3', 'position': 2, 'protocol': 'icmp', 'shared': False, 'source_ip_address': '192.168.100.0/24', 'source_port': None, 'tenant_id': FAKE_TENANT_ID} rule3 = {'action': 'allow', 'description': '', 'destination_ip_address': None, 'destination_port': None, 'enabled': True, 'firewall_policy_id': FAKE_POLICY_ID, 'id': '3', 'ip_version': 4, 'name': 'a4', 'position': 3, 'protocol': 'tcp', 'shared': False, 'source_ip_address': None, 'source_port': None, 'tenant_id': FAKE_TENANT_ID} return [rule1, rule2, rule3] def _fake_firewall(self, rule_list): fw = { 'admin_state_up': True, 'description': '', 'firewall_policy_id': FAKE_POLICY_ID, 'id': FAKE_FIREWALL_ID, 'name': FAKE_FW_NAME, 'shared': None, 'status': 'PENDING_CREATE', 'tenant_id': FAKE_TENANT_ID, 'firewall_rule_list': rule_list} return fw def _fake_apply_list(self): apply_list = [] router_info_inst = mock.Mock() fake_interface = mock.Mock() router_inst = ( {'_interfaces': fake_interface, 'admin_state_up': True, 'distributed': False, 'external_gateway_info': None, 'gw_port_id': None, 'ha': False, 'ha_vr_id': 0, 'id': FAKE_ROUTER_ID, 'name': 'rrr1', 'routes': [], 'status': 'ACTIVE', 'tenant_id': FAKE_TENANT_ID}) router_info_inst.router = router_inst apply_list.append(router_info_inst) return apply_list def test_update_firewall(self): firewall = self._fake_firewall(self.rule_list) ref_v4rule = self.tmp_ref + "/fw_ipv4_access_rule" ref_upload = self.tmp_ref + "/upload" # NOTE(cbrandily): we replace jsonutils.dumps by identity in order # to compare dictionaries instead of their json dumps and avoid to # assume how jsonutils.dumps order dictionaries. with mock.patch('oslo_serialization.jsonutils.dumps', side_effect=lambda x: x), \ mock.patch.object(mcafee.smc_api.SMCAPIConnection, 'login'), \ mock.patch.object(mcafee.smc_api.SMCAPIConnection, 'get'), \ mock.patch.object(mcafee.smc_api.SMCAPIConnection, 'logout'), \ mock.patch.object(mcafee.smc_api.SMCAPIConnection, 'post', return_value=self.post_return) as post: expected = [ mock.call( 'elements/fw_policy', {"name": self.policy_name, "template": None}), mock.call( 'elements/udp_service', {"min_dst_port": 23, "max_dst_port": 23, "name": "service-a2", "max_src_port": 23, "min_src_port": 23}), mock.call( ref_v4rule, {"action": {"action": "discard", "connection_tracking_options": {}}, "services": {"service": [self.tmp_ref]}, "sources": {"src": ["None"]}, "name": "a2", "destinations": {"dst": ["None"]}}, raw=True), mock.call( 'elements/network', {"ipv4_network": "192.168.100.0/24", "name": "network-192.168.100.0/24"}), mock.call( 'elements/icmp_service', {"icmp_code": 0, "icmp_type": 0, "name": "service22"}), mock.call( ref_v4rule, {"action": {"action": "discard", "connection_tracking_options": {}}, "services": {"service": [self.tmp_ref]}, "sources": {"src": [self.tmp_ref]}, "name": "a3", "destinations": {"dst": ["None"]}}, raw=True), mock.call( 'elements/tcp_service', {"min_dst_port": 0, "max_dst_port": 65535, "name": "service-a4", "max_src_port": 65535, "min_src_port": 0}), mock.call( ref_v4rule, {"action": {"action": "allow", "connection_tracking_options": {}}, "services": {"service": [self.tmp_ref]}, "sources": {"src": ["None"]}, "name": "a4", "destinations": {"dst": ["None"]}}, raw=True), mock.call(ref_upload, '', raw=True)] self.firewall.update_firewall('legacy', self.apply_list, firewall) self.assertEqual(expected, post.call_args_list) def test_create_firewall(self): self.test_update_firewall() def test_delete_firewall(self): firewall = self._fake_firewall(self.rule_list) get_value = [{'result': [{'name': self.policy_name, 'href': self.tmp_ref}, ]}, ] with mock.patch.object(mcafee.smc_api.SMCAPIConnection, 'login'), \ mock.patch.object(mcafee.smc_api.SMCAPIConnection, 'get', return_value=get_value),\ mock.patch.object(mcafee.smc_api.SMCAPIConnection, 'logout'), \ mock.patch.object(mcafee.smc_api.SMCAPIConnection, 'post', return_value=self.post_return), \ mock.patch.object(mcafee.smc_api.SMCAPIConnection, 'delete' ) as delete: self.firewall.delete_firewall('legacy', self.apply_list, firewall) expected = [ mock.call(self.tmp_ref, raw=True), mock.call(self.tmp_ref, raw=True) ] self.assertEqual(expected, delete.call_args_list) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/varmour/0000775000567000056710000000000012701410073031241 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/varmour/__init__.py0000664000567000056710000000000012701407720033345 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/varmour/test_varmour_fwaas.py0000664000567000056710000002131712701407720035537 0ustar jenkinsjenkins00000000000000# 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. import mock from neutron.agent.common import config as agent_config from neutron.agent.l3 import config as l3_config from neutron.agent.l3 import ha from neutron.agent.l3 import router_info from neutron.agent.linux import interface from neutron.common import config as base_config from neutron.tests import base from neutron_lib import constants as l3_constants from oslo_utils import uuidutils from neutron_fwaas.services.firewall.agents.varmour import varmour_router from neutron_fwaas.services.firewall.drivers.varmour import varmour_fwaas _uuid = uuidutils.generate_uuid HOSTNAME = 'myhost' FAKE_DIRECTOR = '1.1.1.1' class TestBasicRouterOperations(base.BaseTestCase): def setUp(self): super(TestBasicRouterOperations, self).setUp() self.conf = agent_config.setup_conf() self.conf.register_opts(base_config.core_opts) self.conf.register_opts(l3_config.OPTS) self.conf.register_opts(ha.OPTS) agent_config.register_process_monitor_opts(self.conf) agent_config.register_interface_driver_opts_helper(self.conf) self.conf.register_opts(interface.OPTS) self.conf.set_override('interface_driver', 'neutron.agent.linux.interface.NullDriver') self.conf.state_path = '' self.device_exists_p = mock.patch( 'neutron.agent.linux.ip_lib.device_exists') self.device_exists = self.device_exists_p.start() self.utils_exec_p = mock.patch( 'neutron.agent.linux.utils.execute') self.utils_exec = self.utils_exec_p.start() self.external_process_p = mock.patch( 'neutron.agent.linux.external_process.ProcessManager') self.external_process = self.external_process_p.start() self.makedirs_p = mock.patch('os.makedirs') self.makedirs = self.makedirs_p.start() self.dvr_cls_p = mock.patch('neutron.agent.linux.interface.NullDriver') driver_cls = self.dvr_cls_p.start() self.mock_driver = mock.MagicMock() self.mock_driver.DEV_NAME_LEN = ( interface.LinuxInterfaceDriver.DEV_NAME_LEN) driver_cls.return_value = self.mock_driver self.ip_cls_p = mock.patch('neutron.agent.linux.ip_lib.IPWrapper') ip_cls = self.ip_cls_p.start() self.mock_ip = mock.MagicMock() ip_cls.return_value = self.mock_ip mock.patch('neutron.agent.l3.agent.L3PluginApi').start() self.looping_call_p = mock.patch( 'oslo_service.loopingcall.FixedIntervalLoopingCall') self.looping_call_p.start() self.fake_agent_mode = None self.ri_kwargs = {'agent_conf': self.conf, 'interface_driver': self.mock_driver} def _create_router(self): router = varmour_router.vArmourL3NATAgent(HOSTNAME, self.conf) router.rest.server = FAKE_DIRECTOR router.rest.user = 'varmour' router.rest.passwd = 'varmour' return router def _create_fwaas(self): fwaas = varmour_fwaas.vArmourFwaasDriver() fwaas.rest.server = FAKE_DIRECTOR fwaas.rest.user = 'varmour' fwaas.rest.passwd = 'varmour' return fwaas def _del_all_internal_ports(self, router): router[l3_constants.INTERFACE_KEY] = [] def _del_internal_ports(self, router, port_idx): del router[l3_constants.INTERFACE_KEY][port_idx] def _add_internal_ports(self, router, port_count=1): self._del_all_internal_ports(router) for i in range(port_count): port = {'id': _uuid(), 'network_id': _uuid(), 'admin_state_up': True, 'fixed_ips': [{'ip_address': '10.0.%s.4' % i, 'subnet_id': _uuid()}], 'mac_address': 'ca:fe:de:ad:be:ef', 'subnet': {'cidr': '10.0.%s.0/24' % i, 'gateway_ip': '10.0.%s.1' % i}} router[l3_constants.INTERFACE_KEY].append(port) def _del_all_floating_ips(self, router): router[l3_constants.FLOATINGIP_KEY] = [] def _del_floating_ips(self, router, port_idx): del router[l3_constants.FLOATINGIP_KEY][port_idx] def _add_floating_ips(self, router, port_count=1): self._del_all_floating_ips(router) for i in range(port_count): fip = {'id': _uuid(), 'port_id': router['gw_port']['id'], 'floating_ip_address': '172.24.4.%s' % (100 + i), 'fixed_ip_address': '10.0.0.%s' % (100 + i)} router[l3_constants.FLOATINGIP_KEY].append(fip) def _prepare_router_data(self, enable_snat=None): router_id = _uuid() ex_gw_port = {'id': _uuid(), 'network_id': _uuid(), 'fixed_ips': [{'ip_address': '172.24.4.2', 'subnet_id': _uuid()}], 'subnet': {'cidr': '172.24.4.0/24', 'gateway_ip': '172.24.4.1'}, 'ip_cidr': '172.24.4.226/28'} int_ports = [] router = { 'id': router_id, l3_constants.INTERFACE_KEY: int_ports, 'routes': [], 'gw_port': ex_gw_port} if enable_snat is not None: router['enable_snat'] = enable_snat ri = router_info.RouterInfo(router_id=router['id'], router=router, **self.ri_kwargs) return ri def _add_firewall_rules(self, fw, rule_count=1): rules = [] for i in range(rule_count): rule = {'id': _uuid(), 'enabled': True, 'action': 'deny' if (i % 2 == 0) else 'allow', 'ip_version': 4, 'protocol': 'tcp', 'source_ip_address': '10.0.0.%s/24' % (100 + i), 'destination_port': '%s' % (100 + i)} rules.append(rule) fw['firewall_rule_list'] = rules def _prepare_firewall_data(self): fw = {'id': _uuid(), 'admin_state_up': True, 'firewall_rule_list': []} return fw def test_firewall_without_rule(self): fwaas = self._create_fwaas() fwaas.create_firewall = mock.Mock() fwaas.delete_firewall = mock.Mock() ri = self._prepare_router_data(enable_snat=True) self._add_internal_ports(ri.router, port_count=1) self._add_floating_ips(ri.router, port_count=1) rl = [ri] fw = self._prepare_firewall_data() fwaas.create_firewall(self.fake_agent_mode, rl, fw) fwaas.create_firewall.assert_called_once_with(self.fake_agent_mode, rl, fw) fwaas.delete_firewall(self.fake_agent_mode, rl, fw) def test_firewall_with_rules(self): fwaas = self._create_fwaas() fwaas.create_firewall = mock.Mock() fwaas.delete_firewall = mock.Mock() fw = self._prepare_firewall_data() self._add_firewall_rules(fw, 2) ri = self._prepare_router_data(enable_snat=True) self._add_internal_ports(ri.router, port_count=1) self._add_floating_ips(ri.router, port_count=1) rl = [ri] fwaas.create_firewall(self.fake_agent_mode, rl, fw) fwaas.create_firewall.assert_called_once_with(self.fake_agent_mode, rl, fw) fwaas.delete_firewall(self.fake_agent_mode, rl, fw) def test_firewall_add_remove_rules(self): fwaas = self._create_fwaas() fwaas.create_firewall = mock.Mock() fwaas.delete_firewall = mock.Mock() fw = self._prepare_firewall_data() ri = self._prepare_router_data(enable_snat=True) self._add_internal_ports(ri.router, port_count=1) self._add_floating_ips(ri.router, port_count=1) rl = [ri] self._add_firewall_rules(fw, 2) fwaas.create_firewall(self.fake_agent_mode, rl, fw) # 3x number of policies self._add_firewall_rules(fw, 1) fwaas.create_firewall(self.fake_agent_mode, rl, fw) fwaas.delete_firewall(self.fake_agent_mode, rl, fw) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/cisco/0000775000567000056710000000000012701410073030646 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/cisco/test_csr_acl_driver.py0000664000567000056710000004160512701407720035253 0ustar jenkinsjenkins00000000000000# Copyright 2014 Cisco Systems, 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 copy import mock import requests import sys from neutron.tests import base with mock.patch.dict(sys.modules, { 'networking_cisco': mock.Mock(), 'networking_cisco.plugins': mock.Mock().plugins, 'networking_cisco.plugins.cisco': mock.Mock().cisco, 'networking_cisco.plugins.cisco.cfg_agent': mock.Mock().cfg_agent, 'networking_cisco.plugins.cisco.cfg_agent.device_drivers': mock.Mock().device_drivers, }): from neutron_fwaas.services.firewall.drivers.cisco import csr_acl_driver FAKE_ACL_ID = 'acl123' FAKE_FW = { 'id': '123456789', 'admin_state_up': True, 'vendor_ext': { 'acl_id': FAKE_ACL_ID, 'host_mngt_ip': '192.169.101.5', 'host_usr_nm': 'lab', 'host_usr_pw': 'lab', 'if_list': [ { 'direction': 'inside', 'port': { 'id': 'fake_port_id', 'hosting_info': { # map to interface GigabitEthernet3.101 'segmentation_id': 101, 'hosting_port_name': 't2_p:1', }, }, }, ] }, 'firewall_rule_list': [ { 'enabled': True, 'name': 'r1', 'ip_version': 4, 'protocol': 'tcp', 'action': 'allow', 'source_port': '3001', 'destination_port': '3001', }, ] } class TestCsrAclDriver(base.BaseTestCase): def setUp(self): super(TestCsrAclDriver, self).setUp() self.csr = mock.Mock() self.csracl = csr_acl_driver.CsrAclDriver() self.csracl._get_csr_host = mock.Mock(return_value=self.csr) self.acl_data = self.csracl._get_acl_rule_data(FAKE_FW) self.aclapi_response = 'https://' + FAKE_FW[ 'vendor_ext']['host_mngt_ip'] + '/' + FAKE_ACL_ID def _set_csracl_mocks(self): self.csracl._post_acl = mock.Mock() self.csracl._post_acl_to_interfaces = mock.Mock() self.csracl._delete_acl = mock.Mock() self.csracl._put_acl = mock.Mock() self.csracl._delete_acl_on_interface = mock.Mock() self.csracl._get_acl_interface = mock.Mock() def _set_csr_mocks(self): self.csr.post_request = mock.Mock() self.csr.delete_request = mock.Mock() self.csr.get_request = mock.Mock() self.csr.put_request = mock.Mock() def _test_post_acl(self): self._set_csr_mocks() self.csr.post_request.return_value = self.aclapi_response acl_id = self.csracl._post_acl(self.csr, self.acl_data) self.csr.post_request.assert_called_once_with('acl', self.acl_data) if self.csr.status == requests.codes.CREATED: self.assertEqual(FAKE_ACL_ID, acl_id) else: self.assertEqual('', acl_id) def test_post_acl_error(self): self.csr.status = requests.codes.SERVER_ERROR self._test_post_acl() def test_post_acl(self): self.csr.status = requests.codes.CREATED self._test_post_acl() def _test_delete_acl(self): self._set_csr_mocks() success = self.csracl._delete_acl(self.csr, FAKE_ACL_ID) self.csr.delete_request.assert_called_once_with('acl/' + FAKE_ACL_ID) if self.csr.status == requests.codes.NO_CONTENT: self.assertTrue(success) else: self.assertFalse(success) def test_delete_acl_error(self): self.csr.status = requests.codes.SERVER_ERROR self._test_delete_acl() def test_delete_acl(self): self.csr.status = requests.codes.NO_CONTENT self._test_delete_acl() def _test_put_acl(self): self._set_csr_mocks() success = self.csracl._put_acl( self.csr, FAKE_ACL_ID, self.acl_data) self.csr.put_request.assert_called_once_with( 'acl/' + FAKE_ACL_ID, self.acl_data) if self.csr.status == requests.codes.NO_CONTENT: self.assertTrue(success) else: self.assertFalse(success) def test_put_acl_error(self): self.csr.status = requests.codes.SERVER_ERROR self._test_put_acl() def test_put_acl(self): self.csr.status = requests.codes.NO_CONTENT self._test_put_acl() def _test_post_acl_to_interfaces(self): self._set_csr_mocks() self.csr.post_request.return_value = 'fake_post_response' status_data = { 'fw_id': FAKE_FW['id'], 'acl_id': FAKE_ACL_ID, 'if_list': [] } firewall_interface = FAKE_FW['vendor_ext']['if_list'][0] interface_name = self.csracl._get_interface_name_from_hosting_port( firewall_interface['port']) acl_interface_data = { 'if-id': interface_name, 'direction': firewall_interface['direction']} api = 'acl/' + FAKE_ACL_ID + '/interfaces' self.csracl._post_acl_to_interfaces(FAKE_FW, self.csr, FAKE_ACL_ID, status_data) self.csr.post_request.assert_called_once_with(api, acl_interface_data) if self.csr.status == requests.codes.CREATED: self.assertEqual( [{'port_id': firewall_interface['port']['id'], 'status': 'OK'}], status_data['if_list']) else: self.assertEqual( [{'port_id': firewall_interface['port']['id'], 'status': 'ERROR'}], status_data['if_list']) def test_post_acl_to_interfaces_error(self): self.csr.status = requests.codes.SERVER_ERROR self._test_post_acl_to_interfaces() def test_post_acl_to_interfaces(self): self.csr.status = requests.codes.CREATED self._test_post_acl_to_interfaces() def test_delete_acl_on_interface(self): self._set_csr_mocks() self.csr.status = requests.codes.NO_CONTENT csr_acl_interfaces = [ { 'acl-id': FAKE_ACL_ID, 'if-id': 'GigabitEthernet3.101', 'direction': 'inside' } ] api = 'acl/%s/interfaces/%s_%s' % ( FAKE_ACL_ID, csr_acl_interfaces[0]['if-id'], csr_acl_interfaces[0]['direction']) self.csracl._delete_acl_on_interface( self.csr, FAKE_ACL_ID, csr_acl_interfaces) self.csr.delete_request.assert_called_once_with(api) def _test_get_acl_interface(self): self._set_csr_mocks() api = 'acl/%s/interfaces' % FAKE_ACL_ID get_rsp = {'items': [{'fake_k1': 'fake_d1'}]} self.csr.get_request.return_value = get_rsp rsp = self.csracl._get_acl_interface(self.csr, FAKE_ACL_ID) self.csr.get_request.assert_called_once_with(api) if self.csr.status == requests.codes.OK: self.assertEqual(get_rsp['items'], rsp) else: self.assertEqual('', rsp) def test_get_acl_interface_err(self): self.csr.status = requests.codes.SERVER_ERROR self._test_get_acl_interface() def test_get_acl_interface(self): self.csr.status = requests.codes.OK self._test_get_acl_interface() def test_create_firewall_admin_state_not_up(self): firewall = copy.deepcopy(FAKE_FW) firewall['admin_state_up'] = False self._set_csracl_mocks() self.csracl._post_acl.return_value = FAKE_ACL_ID success, status = self.csracl.create_firewall(None, None, firewall) self.csracl._post_acl.assert_called_once_with(self.csr, self.acl_data) self.assertTrue(success) self.assertEqual( {'fw_id': FAKE_FW['id'], 'acl_id': FAKE_ACL_ID, 'if_list': []}, status) def test_create_firewall_post_acl_error(self): self._set_csracl_mocks() self.csracl._post_acl.return_value = '' success, status = self.csracl.create_firewall(None, None, FAKE_FW) self.csracl._post_acl.assert_called_once_with(self.csr, self.acl_data) self.assertFalse(success) def test_create_firewall(self): self._set_csracl_mocks() self.csracl._post_acl.return_value = FAKE_ACL_ID status_data = { 'fw_id': FAKE_FW['id'], 'acl_id': FAKE_ACL_ID, 'if_list': [] } success, status = self.csracl.create_firewall(None, None, FAKE_FW) self.csracl._post_acl.assert_called_once_with(self.csr, self.acl_data) self.csracl._post_acl_to_interfaces.assert_called_once_with( FAKE_FW, self.csr, FAKE_ACL_ID, status_data) self.assertTrue(success) def _test_delete_firewall(self, delete_acl_success): self._set_csracl_mocks() self.csracl._delete_acl.return_value = delete_acl_success success = self.csracl.delete_firewall(None, None, FAKE_FW) self.csracl._delete_acl.assert_called_once_with(self.csr, FAKE_ACL_ID) self.assertEqual(delete_acl_success, success) def test_delete_firewall(self): self._test_delete_firewall(True) def test_delete_firewall_error(self): self._test_delete_firewall(False) def test_udpate_firewall_put_acl_error(self): self._set_csracl_mocks() self.csracl._put_acl.return_value = False acldata = self.acl_data acldata['acl-id'] = FAKE_ACL_ID success, status = self.csracl.update_firewall(None, None, FAKE_FW) self.csracl._put_acl.assert_called_once_with( self.csr, FAKE_ACL_ID, acldata) self.assertFalse(success) def _test_update_firewall(self, admin_stat_up): firewall = copy.deepcopy(FAKE_FW) firewall['admin_state_up'] = admin_stat_up self._set_csracl_mocks() self.csracl._put_acl.return_value = True acldata = self.acl_data acldata['acl-id'] = FAKE_ACL_ID fake_acl_interface_list = [{'if-id': 'GigabitEthernet3.101'}] self.csracl._get_acl_interface.return_value = fake_acl_interface_list status_data = { 'fw_id': firewall['id'], 'acl_id': FAKE_ACL_ID, 'if_list': [] } success, status = self.csracl.update_firewall(None, None, firewall) self.csracl._put_acl.assert_called_once_with( self.csr, FAKE_ACL_ID, acldata) self.csracl._get_acl_interface.assert_called_once_with( self.csr, FAKE_ACL_ID) self.csracl._delete_acl_on_interface.assert_called_once_with( self.csr, FAKE_ACL_ID, fake_acl_interface_list) self.assertTrue(success) if not admin_stat_up: self.assertEqual(status_data, status) else: self.csracl._post_acl_to_interfaces.assert_called_once_with( firewall, self.csr, FAKE_ACL_ID, status_data) def test_update_firewall_admin_state_not_up(self): self._test_update_firewall(False) def test_update_firewall(self): self._test_update_firewall(True) class TestCsrAclDriverValidation(base.BaseTestCase): def setUp(self): super(TestCsrAclDriverValidation, self).setUp() self.csracl = csr_acl_driver.CsrAclDriver() self.firewall = copy.deepcopy(FAKE_FW) def test_create_firewall_no_admin_state(self): del self.firewall['admin_state_up'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_vendor_ext(self): del self.firewall['vendor_ext'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_host_mngt_ip(self): del self.firewall['vendor_ext']['host_mngt_ip'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_host_usr_name(self): del self.firewall['vendor_ext']['host_usr_nm'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_host_usr_password(self): del self.firewall['vendor_ext']['host_usr_pw'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_if_list(self): del self.firewall['vendor_ext']['if_list'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_direction(self): del self.firewall['vendor_ext']['if_list'][0]['direction'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_invalid_direction(self): self.firewall['vendor_ext']['if_list'][0]['direction'] = 'dir' success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_port(self): del self.firewall['vendor_ext']['if_list'][0]['port'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_host_info(self): del self.firewall['vendor_ext']['if_list'][0]['port']['hosting_info'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_segmentation_id(self): del self.firewall['vendor_ext']['if_list'][0]['port']['hosting_info'][ 'segmentation_id'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_host_port_name(self): del self.firewall['vendor_ext']['if_list'][0]['port']['hosting_info'][ 'hosting_port_name'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_invalid_host_port_name(self): self.firewall['vendor_ext']['if_list'][0]['port']['hosting_info'][ 'hosting_port_name'] = 't3_p:1' success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_no_rule_list(self): del self.firewall['firewall_rule_list'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_rule_no_name(self): del self.firewall['firewall_rule_list'][0]['name'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_rule_no_ip_version(self): del self.firewall['firewall_rule_list'][0]['ip_version'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_rule_not_ipv4(self): self.firewall['firewall_rule_list'][0]['ip_version'] = 6 success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_rule_no_protocol(self): del self.firewall['firewall_rule_list'][0]['protocol'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_rule_no_action(self): del self.firewall['firewall_rule_list'][0]['action'] success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_create_firewall_rule_invalid_action(self): self.firewall['firewall_rule_list'][0]['action'] = 'action' success, status = self.csracl.create_firewall( None, None, self.firewall) self.assertFalse(success) def test_update_firewall_no_acl_id(self): del self.firewall['vendor_ext']['acl_id'] success, status = self.csracl.update_firewall( None, None, self.firewall) self.assertFalse(success) def test_delete_firewall_no_acl_id(self): del self.firewall['vendor_ext']['acl_id'] success = self.csracl.delete_firewall(None, None, self.firewall) self.assertFalse(success) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/cisco/__init__.py0000664000567000056710000000000012701407720032752 0ustar jenkinsjenkins00000000000000././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/cisco/test_csr_firewall_svc_helper.pyneutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/cisco/test_csr_firewall_svc_h0000664000567000056710000002266512701407720035506 0ustar jenkinsjenkins00000000000000# Copyright 2014 Cisco Systems, 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 import sys from neutron import context as n_context from neutron.plugins.common import constants from neutron.tests import base # Mocking imports of 3rd party cisco library in unit tests and all modules # that depends on this library. with mock.patch.dict(sys.modules, { 'networking_cisco': mock.Mock(), 'networking_cisco.plugins': mock.Mock().plugins, 'networking_cisco.plugins.cisco': mock.Mock().cisco, 'networking_cisco.plugins.cisco.cfg_agent': mock.Mock().cfg_agent, 'networking_cisco.plugins.cisco.cfg_agent.device_drivers': mock.Mock().device_drivers, 'networking_cisco.plugins.cisco.cfg_agent.service_helpers': mock.Mock().service_helpers, }): from neutron_fwaas.services.firewall.drivers.cisco import ( csr_firewall_svc_helper) HOST = 'myhost' FAKE_FW = {'id': '1234'} FAKE_FW_STATUS = { 'fw_id': '1234', 'acl_id': 'acl123', 'if_list': [] } class TestCsrFirewallServiceHelper(base.BaseTestCase): def setUp(self): super(TestCsrFirewallServiceHelper, self).setUp() self.firewall_plugin_api_cls_p = mock.patch( 'neutron_fwaas.services.firewall.drivers.cisco.' 'csr_firewall_svc_helper.CsrFirewalllPluginApi') self.firewall_plugin_api_cls = self.firewall_plugin_api_cls_p.start() self.firewall_plugin_api = mock.Mock() self.firewall_plugin_api_cls.return_value = self.firewall_plugin_api self.firewall_plugin_api.get_firewalls_for_device = mock.MagicMock() self.firewall_plugin_api.get_firewalls_for_tenant = mock.MagicMock() self.firewall_plugin_api.get_tenants_with_firewalls = mock.MagicMock() self.firewall_plugin_api.firewall_deleted = mock.MagicMock() self.firewall_plugin_api.set_firewall_status = mock.MagicMock() mock.patch('neutron.common.rpc.create_connection').start() self.fw_svc_helper = csr_firewall_svc_helper.CsrFirewallServiceHelper( HOST, mock.Mock(), mock.Mock()) self.fw_svc_helper.acl_driver = mock.Mock() self.fw_svc_helper.event_q = mock.Mock() self.fw_svc_helper.event_q.enqueue = mock.Mock() self.ctx = mock.Mock() def _test_firewall_even_enqueue(self, event_name): firewall_event = {'event': event_name, 'context': self.ctx, 'firewall': FAKE_FW, 'host': HOST} self.fw_svc_helper.event_q.enqueue.assert_called_with( 'csr_fw_event_q', firewall_event) def test_create_firewall(self): self.fw_svc_helper.create_firewall(self.ctx, FAKE_FW, HOST) self._test_firewall_even_enqueue('FW_EVENT_CREATE') def test_update_firewall(self): self.fw_svc_helper.update_firewall(self.ctx, FAKE_FW, HOST) self._test_firewall_even_enqueue('FW_EVENT_UPDATE') def test_delete_firewall(self): self.fw_svc_helper.delete_firewall(self.ctx, FAKE_FW, HOST) self._test_firewall_even_enqueue('FW_EVENT_DELETE') def _test_fullsync(self, firewall_status, function_name): self.fw_svc_helper._invoke_firewall_driver = mock.Mock() self.fw_svc_helper.fullsync = True self.firewall_plugin_api.get_tenants_with_firewalls.return_value = [ '1'] firewall = FAKE_FW firewall['status'] = firewall_status self.firewall_plugin_api.get_firewalls_for_tenant.return_value = [ firewall] ctx_p = mock.patch.object(n_context, 'Context').start() ctx_p.return_value = self.ctx self.fw_svc_helper.process_service() self.fw_svc_helper._invoke_firewall_driver.assert_called_with( self.ctx, firewall, function_name) self.assertFalse(self.fw_svc_helper.fullsync) def test_proc_service_fullsync_firewall_pending_create(self): self._test_fullsync('PENDING_CREATE', 'create_firewall') def test_proc_service_fullsync_firewall_pending_update(self): self._test_fullsync('PENDING_UPDATE', 'update_firewall') def test_proc_service_fullsync_frewall_pending_delete(self): self._test_fullsync('PENDING_DELETE', 'delete_firewall') def _test_proc_service_device_ids(self, firewall_status, function_name): self.fw_svc_helper._invoke_firewall_driver = mock.Mock() self.fw_svc_helper.fullsync = False ctx_p = mock.patch.object(n_context, 'Context').start() ctx_p.return_value = self.ctx firewall = FAKE_FW firewall['status'] = firewall_status self.firewall_plugin_api.get_firewalls_for_device.return_value = [ firewall] self.fw_svc_helper.process_service(device_ids=['123']) self.fw_svc_helper._invoke_firewall_driver.assert_called_with( self.ctx, firewall, function_name) def test_proc_service_device_ids_firewall_pending_create(self): self._test_proc_service_device_ids( 'PENDING_CREATE', 'create_firewall') def test_proc_service_device_ids_firewall_pending_update(self): self._test_proc_service_device_ids( 'PENDING_UPDATE', 'update_firewall') def test_proc_service_device_ids_firewall_pending_delete(self): self._test_proc_service_device_ids( 'PENDING_DELETE', 'delete_firewall') def _test_firewall_event(self, event, function_name): self.fw_svc_helper._invoke_firewall_driver = mock.Mock() self.fw_svc_helper.fullsync = False event_data = {'event': event, 'context': self.ctx, 'firewall': FAKE_FW, 'host': HOST} event_q_returns = [event_data, None] def _ev_dequeue_side_effect(*args): return event_q_returns.pop(0) self.fw_svc_helper.event_q.dequeue = mock.Mock( side_effect=_ev_dequeue_side_effect) self.fw_svc_helper.process_service() self.fw_svc_helper._invoke_firewall_driver.assert_called_once_with( self.ctx, FAKE_FW, function_name) def test_proc_service_firewall_event_create(self): self._test_firewall_event('FW_EVENT_CREATE', 'create_firewall') def test_proc_service_firewall_event_update(self): self._test_firewall_event('FW_EVENT_UPDATE', 'update_firewall') def test_proc_service_firewall_event_delete(self): self._test_firewall_event('FW_EVENT_DELETE', 'delete_firewall') def test_invoke_firewall_driver_for_delete(self): self.fw_svc_helper.acl_driver.delete_firewall = mock.Mock() self.fw_svc_helper.acl_driver.delete_firewall.return_value = True self.fw_svc_helper._invoke_firewall_driver( self.ctx, FAKE_FW, 'delete_firewall') self.fw_svc_helper.acl_driver.delete_firewall.assert_called_with( None, None, FAKE_FW) self.firewall_plugin_api.firewall_deleted.assert_called_with( self.ctx, FAKE_FW['id']) self.fw_svc_helper.acl_driver.delete_firewall.return_value = False self.fw_svc_helper._invoke_firewall_driver( self.ctx, FAKE_FW, 'delete_firewall') self.firewall_plugin_api.set_firewall_status.assert_called_with( self.ctx, FAKE_FW['id'], constants.ERROR) def test_invoke_firewall_driver_for_create(self): self.fw_svc_helper.acl_driver.create_firewall = mock.Mock() self.fw_svc_helper.acl_driver.create_firewall.return_value = ( True, FAKE_FW_STATUS) self.fw_svc_helper._invoke_firewall_driver( self.ctx, FAKE_FW, 'create_firewall') self.fw_svc_helper.acl_driver.create_firewall.assert_called_with( None, None, FAKE_FW) self.firewall_plugin_api.set_firewall_status.assert_called_with( self.ctx, FAKE_FW['id'], constants.ACTIVE, FAKE_FW_STATUS) self.fw_svc_helper.acl_driver.create_firewall.return_value = ( False, {}) self.fw_svc_helper._invoke_firewall_driver( self.ctx, FAKE_FW, 'create_firewall') self.firewall_plugin_api.set_firewall_status.assert_called_with( self.ctx, FAKE_FW['id'], constants.ERROR) def test_invoke_firewall_driver_for_update(self): self.fw_svc_helper.acl_driver.update_firewall = mock.Mock() self.fw_svc_helper.acl_driver.update_firewall.return_value = ( True, FAKE_FW_STATUS) self.fw_svc_helper._invoke_firewall_driver( self.ctx, FAKE_FW, 'update_firewall') self.fw_svc_helper.acl_driver.update_firewall.assert_called_with( None, None, FAKE_FW) self.firewall_plugin_api.set_firewall_status.assert_called_with( self.ctx, FAKE_FW['id'], constants.ACTIVE, FAKE_FW_STATUS) self.fw_svc_helper.acl_driver.update_firewall.return_value = ( False, {}) self.fw_svc_helper._invoke_firewall_driver( self.ctx, FAKE_FW, 'update_firewall') self.firewall_plugin_api.set_firewall_status.assert_called_with( self.ctx, FAKE_FW['id'], constants.ERROR) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/__init__.py0000664000567000056710000000000012701407720031652 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/vyatta/0000775000567000056710000000000012701410073031056 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/vyatta/__init__.py0000664000567000056710000000000012701407720033162 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/drivers/vyatta/test_vyatta_fwaas.py0000664000567000056710000002324112701407720035167 0ustar jenkinsjenkins00000000000000# Copyright 2015 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. import sys import mock from neutron.tests import base from oslo_utils import uuidutils from six.moves.urllib import parse # Mocking imports of 3rd party vyatta library in unit tests and all modules # that depends on this library. Import will fail if not mocked and 3rd party # vyatta library is not installed. with mock.patch.dict(sys.modules, { 'networking_brocade': mock.Mock(), 'networking_brocade.vyatta': mock.Mock(), 'networking_brocade.vyatta.common': mock.Mock(), 'networking_brocade.vyatta.vrouter': mock.Mock(), }): from networking_brocade.vyatta.vrouter import client as vyatta_client from neutron_fwaas.services.firewall.agents.vyatta import vyatta_utils from neutron_fwaas.services.firewall.drivers.vyatta import vyatta_fwaas _uuid = uuidutils.generate_uuid FAKE_FW_UUID = _uuid() def fake_cmd(*args, **kwargs): return (args, kwargs) class VyattaFwaasTestCase(base.BaseTestCase): def setUp(self): super(VyattaFwaasTestCase, self).setUp() mock.patch.object(vyatta_client, 'SetCmd', fake_cmd).start() mock.patch.object(vyatta_client, 'DeleteCmd', fake_cmd).start() self.fwaas_driver = vyatta_fwaas.VyattaFirewallDriver() self.fake_rules = [self._make_fake_fw_rule()] self.fake_firewall = self._make_fake_firewall(self.fake_rules) self.fake_firewall_name = vyatta_utils.get_firewall_name( None, self.fake_firewall) self.fake_apply_list = [self._make_fake_router_info()] self.fake_agent_mode = None def test_create_firewall(self): with mock.patch.object( self.fwaas_driver, 'update_firewall') as fw_update: self.fwaas_driver.create_firewall( self.fake_agent_mode, self.fake_apply_list, self.fake_firewall) fw_update.assert_called_once_with( self.fake_agent_mode, self.fake_apply_list, self.fake_firewall) def test_update_firewall(self): with mock.patch.object( self.fwaas_driver, '_update_firewall') as fw_update: self.fake_firewall['admin_state_up'] = True self.fwaas_driver.create_firewall( self.fake_agent_mode, self.fake_apply_list, self.fake_firewall) fw_update.assert_called_once_with( self.fake_apply_list, self.fake_firewall) with mock.patch.object( self.fwaas_driver, 'apply_default_policy') as fw_apply_policy: self.fake_firewall['admin_state_up'] = False self.fwaas_driver.create_firewall( self.fake_agent_mode, self.fake_apply_list, self.fake_firewall) fw_apply_policy.assert_called_once_with( self.fake_agent_mode, self.fake_apply_list, self.fake_firewall) def test_delete_firewall(self): with mock.patch.object( self.fwaas_driver, 'apply_default_policy') as fw_apply_policy: self.fwaas_driver.delete_firewall( self.fake_agent_mode, self.fake_apply_list, self.fake_firewall) fw_apply_policy.assert_called_once_with( self.fake_agent_mode, self.fake_apply_list, self.fake_firewall) def test_apply_default_policy(self): with mock.patch.object( self.fwaas_driver, '_delete_firewall') as fw_delete: self.fwaas_driver.apply_default_policy( self.fake_agent_mode, self.fake_apply_list, self.fake_firewall) calls = [mock.call(x, self.fake_firewall) for x in self.fake_apply_list] fw_delete.assert_has_calls(calls) def test_update_firewall_internal(self): with mock.patch.object( self.fwaas_driver, '_delete_firewall' ) as fw_delete, mock.patch.object( self.fwaas_driver, '_setup_firewall') as fw_setup: self.fwaas_driver._update_firewall( self.fake_apply_list, self.fake_firewall) calls = [mock.call(x, self.fake_firewall) for x in self.fake_apply_list] fw_delete.assert_has_calls(calls) fw_setup.assert_has_calls(calls) def test_setup_firewall_internal(self): fake_rule = self._make_fake_fw_rule() fake_router_info = self._make_fake_router_info() fake_rule_cmd = 'fake-fw-rule0' fake_zone_configure_rules = ['fake-config-rule0'] mock_api = mock.Mock() mock_api_gen = mock.Mock(return_value=mock_api) mock_get_firewall_rule = mock.Mock(return_value=[fake_rule_cmd]) mock_get_zone_cmds = mock.Mock(return_value=fake_zone_configure_rules) with mock.patch.object(self.fwaas_driver, '_get_vyatta_client', mock_api_gen), \ mock.patch.object(vyatta_fwaas.vyatta_utils, 'get_zone_cmds', mock_get_zone_cmds), \ mock.patch.object(self.fwaas_driver, '_set_firewall_rule', mock_get_firewall_rule): self.fwaas_driver._setup_firewall( fake_router_info, self.fake_firewall) mock_api_gen.assert_called_once_with( fake_router_info.router) mock_get_firewall_rule.assert_called_once_with( self.fake_firewall_name, 1, fake_rule) mock_get_zone_cmds.assert_called_once_with( mock_api, fake_router_info, self.fake_firewall_name) cmds = [ vyatta_client.SetCmd( vyatta_fwaas.FW_NAME.format( self.fake_firewall_name)), vyatta_client.SetCmd( vyatta_fwaas.FW_DESCRIPTION.format( self.fake_firewall_name, parse.quote_plus(self.fake_firewall['description']))), vyatta_client.SetCmd( vyatta_fwaas.FW_ESTABLISHED_ACCEPT), vyatta_client.SetCmd( vyatta_fwaas.FW_RELATED_ACCEPT), fake_rule_cmd, ] + fake_zone_configure_rules mock_api.exec_cmd_batch.assert_called_once_with(cmds) def test_delete_firewall_internal(self): fake_router_info = self._make_fake_router_info() with mock.patch.object( self.fwaas_driver, '_get_vyatta_client') as mock_client_factory: mock_api = mock_client_factory.return_value self.fwaas_driver._delete_firewall( fake_router_info, self.fake_firewall) cmds = [ vyatta_client.DeleteCmd("zone-policy"), vyatta_client.DeleteCmd(vyatta_fwaas.FW_NAME.format( self.fake_firewall_name)), vyatta_client.DeleteCmd("firewall/state-policy"), ] mock_api.exec_cmd_batch.assert_called_once_with(cmds) def test_set_firewall_rule_internal(self): fake_rule = self._make_fake_fw_rule() fake_firewall_name = 'fake-fw-name' fake_rule.update({ 'description': 'rule description', 'source_port': '2080', 'destination_ip_address': '172.16.1.1' }) action_map = { 'allow': 'accept', } cmds_actual = self.fwaas_driver._set_firewall_rule( fake_firewall_name, 1, fake_rule) cmds_expect = [ vyatta_client.SetCmd( vyatta_fwaas.FW_RULE_DESCRIPTION.format( parse.quote_plus(fake_firewall_name), 1, parse.quote_plus(fake_rule['description']))) ] rules = [ ('protocol', vyatta_fwaas.FW_RULE_PROTOCOL), ('source_port', vyatta_fwaas.FW_RULE_SRC_PORT), ('destination_port', vyatta_fwaas.FW_RULE_DEST_PORT), ('source_ip_address', vyatta_fwaas.FW_RULE_SRC_ADDR), ('destination_ip_address', vyatta_fwaas.FW_RULE_DEST_ADDR), ] for key, url in rules: cmds_expect.append(vyatta_client.SetCmd( url.format( parse.quote_plus(fake_firewall_name), 1, parse.quote_plus(fake_rule[key])))) cmds_expect.append(vyatta_client.SetCmd( vyatta_fwaas.FW_RULE_ACTION.format( parse.quote_plus(fake_firewall_name), 1, action_map.get(fake_rule['action'], 'drop')))) self.assertEqual(cmds_expect, cmds_actual) def _make_fake_router_info(self): info = mock.Mock() info.router = { 'id': 'fake-router-id', 'tenant_id': 'tenant-uuid', } return info def _make_fake_fw_rule(self): return { 'enabled': True, 'action': 'allow', 'ip_version': 4, 'protocol': 'tcp', 'destination_port': '80', 'source_ip_address': '10.24.4.2'} def _make_fake_firewall(self, rules): return {'id': FAKE_FW_UUID, 'admin_state_up': True, 'name': 'test-firewall', 'tenant_id': 'tenant-uuid', 'description': 'Fake firewall', 'firewall_rule_list': rules} neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/0000775000567000056710000000000012701410073027351 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/test_firewall_agent_api.py0000664000567000056710000000473312701407720034612 0ustar jenkinsjenkins00000000000000# 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. import mock from neutron_fwaas.services.firewall.agents import firewall_agent_api as api from neutron_fwaas.services.firewall.drivers import fwaas_base as base_driver from neutron_fwaas.tests import base class NoopFwaasDriver(base_driver.FwaasDriverBase): """Noop Fwaas Driver. Firewall driver which does nothing. This driver is for disabling Fwaas functionality. """ def create_firewall(self, agent_mode, apply_list, firewall): pass def delete_firewall(self, agent_mode, apply_list, firewall): pass def update_firewall(self, agent_mode, apply_list, firewall): pass def apply_default_policy(self, agent_mode, apply_list, firewall): pass class TestFWaaSAgentApi(base.BaseTestCase): def setUp(self): super(TestFWaaSAgentApi, self).setUp() self.api = api.FWaaSPluginApiMixin( 'topic', 'host') def test_init(self): self.assertEqual('host', self.api.host) def _test_firewall_method(self, method_name, **kwargs): with mock.patch.object(self.api.client, 'call') as rpc_mock, \ mock.patch.object(self.api.client, 'prepare') as prepare_mock: prepare_mock.return_value = self.api.client getattr(self.api, method_name)(mock.sentinel.context, 'test', **kwargs) prepare_args = {} prepare_mock.assert_called_once_with(**prepare_args) rpc_mock.assert_called_once_with(mock.sentinel.context, method_name, firewall_id='test', host='host', **kwargs) def test_set_firewall_status(self): self._test_firewall_method('set_firewall_status', status='fake_status') def test_firewall_deleted(self): self._test_firewall_method('firewall_deleted') neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/l3reference/0000775000567000056710000000000012701410073031546 5ustar jenkinsjenkins00000000000000././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/l3reference/test_firewall_l3_agent.pyneutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/l3reference/test_firewall_l3_a0000664000567000056710000003515412701407720035250 0ustar jenkinsjenkins00000000000000# 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. import uuid import mock from oslo_config import cfg from neutron.agent.l3 import config as l3_config from neutron.agent.l3 import ha from neutron.agent.l3 import router_info from neutron.agent.linux import ip_lib from neutron.common import config as base_config from neutron import context from neutron.plugins.common import constants from neutron_fwaas.services.firewall.agents import firewall_agent_api from neutron_fwaas.services.firewall.agents.l3reference \ import firewall_l3_agent from neutron_fwaas.tests import base from neutron_fwaas.tests.unit.services.firewall.agents \ import test_firewall_agent_api class FWaasHelper(object): def __init__(self, host): pass class FWaasAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, FWaasHelper): neutron_service_plugins = [] def _setup_test_agent_class(service_plugins): class FWaasTestAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, FWaasHelper): neutron_service_plugins = service_plugins def __init__(self, conf): self.event_observers = mock.Mock() self.conf = conf super(FWaasTestAgent, self).__init__(conf) return FWaasTestAgent class TestFwaasL3AgentRpcCallback(base.BaseTestCase): def setUp(self): super(TestFwaasL3AgentRpcCallback, self).setUp() self.conf = cfg.ConfigOpts() self.conf.register_opts(base_config.core_opts) self.conf.register_opts(l3_config.OPTS) self.conf.register_opts(ha.OPTS) self.conf.register_opts(firewall_agent_api.FWaaSOpts, 'fwaas') self.api = FWaasAgent(self.conf) self.api.fwaas_driver = test_firewall_agent_api.NoopFwaasDriver() self.adminContext = context.get_admin_context() self.router_id = str(uuid.uuid4()) self.agent_conf = mock.Mock() self.ri_kwargs = {'router': {'id': self.router_id, 'tenant_id': str(uuid.uuid4())}, 'agent_conf': self.agent_conf, 'interface_driver': mock.ANY, 'use_ipv6': mock.ANY, } def test_fw_config_match(self): test_agent_class = _setup_test_agent_class([constants.FIREWALL]) cfg.CONF.set_override('enabled', True, 'fwaas') with mock.patch('oslo_utils.importutils.import_object'): test_agent_class(cfg.CONF) def test_fw_config_mismatch_plugin_enabled_agent_disabled(self): test_agent_class = _setup_test_agent_class([constants.FIREWALL]) cfg.CONF.set_override('enabled', False, 'fwaas') self.assertRaises(SystemExit, test_agent_class, cfg.CONF) def test_fw_plugin_list_unavailable(self): test_agent_class = _setup_test_agent_class(None) cfg.CONF.set_override('enabled', False, 'fwaas') with mock.patch('oslo_utils.importutils.import_object'): test_agent_class(cfg.CONF) def test_create_firewall(self): fake_firewall = {'id': 0, 'tenant_id': 1, 'admin_state_up': True, 'add-router-ids': [1, 2]} self.api.plugin_rpc = mock.Mock() with mock.patch.object(self.api, '_get_router_info_list_for_tenant' ) as mock_get_router_info_list_for_tenant, \ mock.patch.object(self.api.fwaas_driver, 'create_firewall' ) as mock_driver_create_firewall, \ mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status' ) as mock_set_firewall_status: mock_driver_create_firewall.return_value = True self.api.create_firewall( context=mock.sentinel.context, firewall=fake_firewall, host='host') mock_get_router_info_list_for_tenant.assert_called_once_with( fake_firewall['add-router-ids'], fake_firewall['tenant_id']) mock_set_firewall_status.assert_called_once_with( mock.sentinel.context, fake_firewall['id'], 'ACTIVE') def test_update_firewall_with_routers_added_and_deleted(self): fake_firewall = {'id': 0, 'tenant_id': 1, 'admin_state_up': True, 'add-router-ids': [1, 2], 'del-router-ids': [3, 4], 'router_ids': [], 'last-router': False} self.api.plugin_rpc = mock.Mock() with mock.patch.object(self.api, '_get_router_info_list_for_tenant' ) as mock_get_router_info_list_for_tenant, \ mock.patch.object(self.api.fwaas_driver, 'update_firewall' ) as mock_driver_delete_firewall, \ mock.patch.object(self.api.fwaas_driver, 'delete_firewall' ) as mock_driver_update_firewall, \ mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status' ) as mock_set_firewall_status: mock_driver_delete_firewall.return_value = True mock_driver_update_firewall.return_value = True calls = [mock.call(fake_firewall['del-router-ids'], fake_firewall['tenant_id']), mock.call(fake_firewall['add-router-ids'], fake_firewall['tenant_id'])] self.api.update_firewall( context=mock.sentinel.context, firewall=fake_firewall, host='host') self.assertEqual( mock_get_router_info_list_for_tenant.call_args_list, calls) mock_set_firewall_status.assert_called_once_with( mock.sentinel.context, fake_firewall['id'], 'ACTIVE') def test_update_firewall_with_routers_added_and_admin_state_down(self): fake_firewall = {'id': 0, 'tenant_id': 1, 'admin_state_up': False, 'add-router-ids': [1, 2], 'del-router-ids': [], 'router_ids': [], 'last-router': False} self.api.plugin_rpc = mock.Mock() with mock.patch.object(self.api, '_get_router_info_list_for_tenant' ) as mock_get_router_info_list_for_tenant, \ mock.patch.object(self.api.fwaas_driver, 'update_firewall' ) as mock_driver_update_firewall, \ mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status' ) as mock_set_firewall_status: mock_driver_update_firewall.return_value = True self.api.update_firewall( context=mock.sentinel.context, firewall=fake_firewall, host='host') mock_get_router_info_list_for_tenant.assert_called_once_with( fake_firewall['add-router-ids'], fake_firewall['tenant_id']) mock_set_firewall_status.assert_called_once_with( mock.sentinel.context, fake_firewall['id'], 'DOWN') def test_update_firewall_with_all_routers_deleted(self): fake_firewall = {'id': 0, 'tenant_id': 1, 'admin_state_up': True, 'add-router-ids': [], 'del-router-ids': [3, 4], 'last-router': True} self.api.plugin_rpc = mock.Mock() with mock.patch.object(self.api, '_get_router_info_list_for_tenant' ) as mock_get_router_info_list_for_tenant, \ mock.patch.object(self.api.fwaas_driver, 'delete_firewall' ) as mock_driver_delete_firewall, \ mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status' ) as mock_set_firewall_status: mock_driver_delete_firewall.return_value = True self.api.update_firewall( context=mock.sentinel.context, firewall=fake_firewall, host='host') mock_get_router_info_list_for_tenant.assert_called_once_with( fake_firewall['del-router-ids'], fake_firewall['tenant_id']) mock_set_firewall_status.assert_called_once_with( mock.sentinel.context, fake_firewall['id'], 'INACTIVE') def test_update_firewall_with_rtrs_and_no_rtrs_added_nor_deleted(self): fake_firewall = {'id': 0, 'tenant_id': 1, 'admin_state_up': True, 'add-router-ids': [], 'del-router-ids': [], 'router_ids': [1, 2]} self.api.plugin_rpc = mock.Mock() with mock.patch.object(self.api.fwaas_driver, 'update_firewall' ) as mock_driver_update_firewall, \ mock.patch.object(self.api, '_get_router_info_list_for_tenant' ) as mock_get_router_info_list_for_tenant, \ mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status' ) as mock_set_firewall_status: mock_driver_update_firewall.return_value = True self.api.update_firewall( context=mock.sentinel.context, firewall=fake_firewall, host='host') mock_get_router_info_list_for_tenant.assert_called_once_with( fake_firewall['router_ids'], fake_firewall['tenant_id']) mock_set_firewall_status.assert_called_once_with( mock.sentinel.context, fake_firewall['id'], 'ACTIVE') def test_update_firewall_with_no_rtrs_and_no_rtrs_added_nor_deleted(self): fake_firewall = {'id': 0, 'tenant_id': 1, 'admin_state_up': True, 'add-router-ids': [], 'del-router-ids': [], 'router_ids': []} self.api.plugin_rpc = mock.Mock() with mock.patch.object(self.api.fwaas_driver, 'update_firewall' ) as mock_driver_update_firewall, \ mock.patch.object(self.api.fwplugin_rpc, 'set_firewall_status' ) as mock_set_firewall_status: mock_driver_update_firewall.return_value = True self.api.update_firewall( context=mock.sentinel.context, firewall=fake_firewall, host='host') mock_set_firewall_status.assert_called_once_with( mock.sentinel.context, fake_firewall['id'], 'INACTIVE') def test_delete_firewall(self): fake_firewall = {'id': 0, 'tenant_id': 1, 'admin_state_up': True, 'add-router-ids': [], 'del-router-ids': [3, 4], 'last-router': True} self.api.plugin_rpc = mock.Mock() with mock.patch.object(self.api, '_get_router_info_list_for_tenant' ) as mock_get_router_info_list_for_tenant, \ mock.patch.object(self.api.fwaas_driver, 'delete_firewall' ) as mock_driver_delete_firewall, \ mock.patch.object(self.api.fwplugin_rpc, 'firewall_deleted' ) as mock_firewall_deleted: mock_driver_delete_firewall.return_value = True self.api.delete_firewall( context=mock.sentinel.context, firewall=fake_firewall, host='host') mock_get_router_info_list_for_tenant.assert_called_once_with( fake_firewall['del-router-ids'], fake_firewall['tenant_id']) mock_firewall_deleted.assert_called_once_with( mock.sentinel.context, fake_firewall['id']) def _prepare_router_data(self): return router_info.RouterInfo(self.router_id, **self.ri_kwargs) def test_get_router_info_list_for_tenant(self): ri = self._prepare_router_data() routers = [ri.router] router_ids = [router['id'] for router in routers] self.api.router_info = {ri.router_id: ri} with mock.patch.object(ip_lib.IPWrapper, 'get_namespaces') as mock_get_namespaces: mock_get_namespaces.return_value = [] router_info_list = self.api._get_router_info_list_for_tenant( router_ids, ri.router['tenant_id']) mock_get_namespaces.assert_called_once_with() self.assertFalse(router_info_list) def _get_router_info_list_router_without_router_info_helper(self, rtr_with_ri): # ri.router with associated router_info (ri) # rtr2 has no router_info ri = self._prepare_router_data() rtr2 = {'id': str(uuid.uuid4()), 'tenant_id': ri.router['tenant_id']} routers = [rtr2] self.api.router_info = {} ri_expected = [] if rtr_with_ri: self.api.router_info[ri.router_id] = ri routers.append(ri.router) ri_expected.append(ri) router_ids = [router['id'] for router in routers] with mock.patch.object(ip_lib.IPWrapper, 'get_namespaces') as mock_get_namespaces: mock_get_namespaces.return_value = ri.ns_name router_info_list = self.api._get_router_info_list_for_tenant( router_ids, ri.router['tenant_id']) self.assertEqual(ri_expected, router_info_list) def test_get_router_info_list_router_without_router_info(self): self._get_router_info_list_router_without_router_info_helper( rtr_with_ri=False) def test_get_router_info_list_two_routers_one_without_router_info(self): self._get_router_info_list_router_without_router_info_helper( rtr_with_ri=True) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/l3reference/__init__.py0000664000567000056710000000000012701407720033652 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/varmour/0000775000567000056710000000000012701410073031044 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/varmour/__init__.py0000664000567000056710000000000012701407720033150 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/varmour/test_varmour_router.py0000664000567000056710000002024212701407720035555 0ustar jenkinsjenkins00000000000000# 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. import mock from neutron.agent.common import config as agent_config from neutron.agent.l3 import config as l3_config from neutron.agent.l3 import ha from neutron.agent.l3 import router_info from neutron.agent.linux import interface from neutron.common import config as base_config from neutron_fwaas.services.firewall.agents.varmour import varmour_router from neutron_fwaas.tests import base from neutron_lib import constants as l3_constants from oslo_utils import uuidutils _uuid = uuidutils.generate_uuid HOSTNAME = 'myhost' FAKE_DIRECTOR = '1.1.1.1' class TestVarmourRouter(base.BaseTestCase): def setUp(self): super(TestVarmourRouter, self).setUp() self.conf = agent_config.setup_conf() self.conf.register_opts(base_config.core_opts) self.conf.register_opts(l3_config.OPTS) self.conf.register_opts(ha.OPTS) agent_config.register_process_monitor_opts(self.conf) agent_config.register_interface_driver_opts_helper(self.conf) self.conf.register_opts(interface.OPTS) self.conf.set_override('interface_driver', 'neutron.agent.linux.interface.NullDriver') self.conf.state_path = '' self.device_exists_p = mock.patch( 'neutron.agent.linux.ip_lib.device_exists') self.device_exists = self.device_exists_p.start() self.utils_exec_p = mock.patch( 'neutron.agent.linux.utils.execute') self.utils_exec = self.utils_exec_p.start() self.external_process_p = mock.patch( 'neutron.agent.linux.external_process.ProcessManager') self.external_process = self.external_process_p.start() self.makedirs_p = mock.patch('os.makedirs') self.makedirs = self.makedirs_p.start() self.dvr_cls_p = mock.patch('neutron.agent.linux.interface.NullDriver') driver_cls = self.dvr_cls_p.start() self.mock_driver = mock.MagicMock() self.mock_driver.DEV_NAME_LEN = ( interface.LinuxInterfaceDriver.DEV_NAME_LEN) driver_cls.return_value = self.mock_driver self.ip_cls_p = mock.patch('neutron.agent.linux.ip_lib.IPWrapper') ip_cls = self.ip_cls_p.start() self.mock_ip = mock.MagicMock() ip_cls.return_value = self.mock_ip mock.patch('neutron.agent.l3.agent.L3PluginApi').start() self.looping_call_p = mock.patch( 'oslo_service.loopingcall.FixedIntervalLoopingCall') self.looping_call_p.start() self.ri_kwargs = {'agent_conf': self.conf, 'interface_driver': self.mock_driver} def _create_router(self): router = varmour_router.vArmourL3NATAgent(HOSTNAME, self.conf) router.rest.server = FAKE_DIRECTOR router.rest.user = 'varmour' router.rest.passwd = 'varmour' return router def _del_all_internal_ports(self, router): router[l3_constants.INTERFACE_KEY] = [] def _del_internal_ports(self, router, port_idx): del router[l3_constants.INTERFACE_KEY][port_idx] def _add_internal_ports(self, router, port_count=1): self._del_all_internal_ports(router) for i in range(port_count): port = {'id': _uuid(), 'network_id': _uuid(), 'admin_state_up': True, 'fixed_ips': [{'ip_address': '10.0.%s.4' % i, 'subnet_id': _uuid()}], 'mac_address': 'ca:fe:de:ad:be:ef', 'subnet': {'cidr': '10.0.%s.0/24' % i, 'gateway_ip': '10.0.%s.1' % i}} router[l3_constants.INTERFACE_KEY].append(port) def _del_all_floating_ips(self, router): router[l3_constants.FLOATINGIP_KEY] = [] def _del_floating_ips(self, router, port_idx): del router[l3_constants.FLOATINGIP_KEY][port_idx] def _add_floating_ips(self, router, port_count=1): self._del_all_floating_ips(router) for i in range(port_count): fip = {'id': _uuid(), 'port_id': router['gw_port']['id'], 'floating_ip_address': '172.24.4.%s' % (100 + i), 'fixed_ip_address': '10.0.0.%s' % (100 + i)} router[l3_constants.FLOATINGIP_KEY].append(fip) def _prepare_router_data(self, enable_snat=None): router_id = _uuid() ex_gw_port = {'id': _uuid(), 'mac_address': 'ca:fe:de:ad:be:ee', 'network_id': _uuid(), 'fixed_ips': [{'ip_address': '172.24.4.2', 'subnet_id': _uuid()}], 'subnet': {'cidr': '172.24.4.0/24', 'gateway_ip': '172.24.4.1'}, 'ip_cidr': '172.24.4.226/28'} int_ports = [] router = { 'id': router_id, 'distributed': False, l3_constants.INTERFACE_KEY: int_ports, 'routes': [], 'gw_port': ex_gw_port} if enable_snat is not None: router['enable_snat'] = enable_snat ri = router_info.RouterInfo(router_id=router['id'], router=router, **self.ri_kwargs) return ri def test_agent_add_internal_network(self): router = self._create_router() self._add_internal_ports = mock.Mock() ri = self._prepare_router_data(enable_snat=True) router._router_added(ri.router['id'], ri.router) self._add_internal_ports(ri.router, port_count=1) self._add_internal_ports.assert_called_once_with(ri.router, port_count=1) def test_agent_remove_internal_network(self): router = self._create_router() self._del_internal_ports = mock.Mock() ri = self._prepare_router_data(enable_snat=True) router._router_added(ri.router['id'], ri.router) self._add_internal_ports(ri.router, port_count=2) self._del_internal_ports(ri.router, 0) self._del_internal_ports.assert_called_once_with(ri.router, 0) def test_agent_add_floating_ips(self): router = self._create_router() self._add_floating_ips = mock.Mock() ri = self._prepare_router_data(enable_snat=True) self._add_internal_ports(ri.router, port_count=1) router._router_added(ri.router['id'], ri.router) self._add_floating_ips(ri.router, port_count=1) self._add_floating_ips.assert_called_once_with(ri.router, port_count=1) def test_agent_remove_floating_ips(self): router = self._create_router() self._del_floating_ips = mock.Mock() ri = self._prepare_router_data(enable_snat=True) self._add_internal_ports(ri.router, port_count=1) self._add_floating_ips(ri.router, port_count=2) router._router_added(ri.router['id'], ri.router) self._del_floating_ips(ri.router, 0) self._del_floating_ips.assert_called_once_with(ri.router, 0) def test_agent_external_gateway(self): router = self._create_router() router._router_removed = mock.Mock() ri = self._prepare_router_data(enable_snat=True) router._router_added(ri.router['id'], ri.router) router._router_removed(ri.router['id']) router._router_removed.assert_called_once_with(ri.router['id']) def test_agent_snat_enable(self): router = self._create_router() ri = self._prepare_router_data(enable_snat=True) router._router_added(ri.router['id'], ri.router) ri.router['enable_snat'] = False self.assertFalse(ri.router['enable_snat']) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/__init__.py0000664000567000056710000000000012701407720031455 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/test_firewall_service.py0000664000567000056710000000455612701407720034326 0ustar jenkinsjenkins00000000000000# Copyright 2014 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. from neutron.tests import base from oslo_config import cfg from neutron_fwaas.services.firewall.agents import firewall_service FWAAS_NOP_DEVICE = ('neutron_fwaas.tests.unit.services.firewall.agents.' 'test_firewall_agent_api.NoopFwaasDriver') class TestFirewallDeviceDriverLoading(base.BaseTestCase): def setUp(self): super(TestFirewallDeviceDriverLoading, self).setUp() self.service = firewall_service.FirewallService() def test_loading_firewall_device_driver(self): """Get the sole device driver for FWaaS.""" cfg.CONF.set_override('driver', FWAAS_NOP_DEVICE, 'fwaas') driver = self.service.load_device_drivers() self.assertIsNotNone(driver) self.assertIn(driver.__class__.__name__, FWAAS_NOP_DEVICE) def test_fail_no_such_firewall_device_driver(self): """Failure test of import error for FWaaS device driver.""" cfg.CONF.set_override('driver', 'no.such.class', 'fwaas') self.assertRaises(ImportError, self.service.load_device_drivers) def test_fail_firewall_no_device_driver_specified(self): """Failure test when no FWaaS device driver is specified. This is a configuration error, as the user must specify a device driver, when enabling the firewall service (and there is no default configuration set. We'll simulate that by using an empty string. """ cfg.CONF.set_override('driver', '', 'fwaas') self.assertRaises(ValueError, self.service.load_device_drivers) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/vyatta/0000775000567000056710000000000012701410073030661 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/vyatta/test_vyatta_utils.py0000664000567000056710000000775112701407720035041 0ustar jenkinsjenkins00000000000000# Copyright 2015 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. import sys import mock from neutron.tests import base from neutron_lib import constants as l3_constants from six.moves.urllib import parse # Mocking imports of 3rd party vyatta library in unit tests and all modules # that depends on this library. Import will fail if not mocked and 3rd party # vyatta library is not installed. with mock.patch.dict(sys.modules, { 'networking_brocade': mock.Mock(), 'networking_brocade.vyatta': mock.Mock(), 'networking_brocade.vyatta.vrouter': mock.Mock(), }): from networking_brocade.vyatta.vrouter import client as vyatta_client from neutron_fwaas.services.firewall.agents.vyatta import vyatta_utils def fake_cmd(*args, **kwargs): return (args, kwargs) class TestVyattaUtils(base.BaseTestCase): def setUp(self): super(TestVyattaUtils, self).setUp() mock.patch.object(vyatta_client, 'SetCmd', fake_cmd).start() mock.patch.object(vyatta_client, 'DeleteCmd', fake_cmd).start() def test_get_firewall_name(self): fake_firewall = { 'id': '74bc106d-fff0-4f92-ac1a-60d4b6b44fe1', } fw_name = vyatta_utils.get_firewall_name( None, fake_firewall) self.assertEqual('74bc106dfff04f92ac1a60d4b6b4', fw_name) def test_get_trusted_zone_name(self): fake_apply_list = object() self.assertEqual( 'Internal_Trust', vyatta_utils.get_trusted_zone_name( fake_apply_list)) def test_get_untrusted_zone_name(self): fake_apply_list = object() self.assertEqual( 'External_Untrust', vyatta_utils.get_untrusted_zone_name( fake_apply_list)) def test_get_zone_cmds(self): firewall_name = 'fake_firewall0' eth_iface = 'eth0' fake_api = mock.NonCallableMock() fake_api.get_ethernet_if_id.return_value = eth_iface mac_address = '00:00:00:00:00:00' fake_apply_rule = mock.NonCallableMock() fake_apply_rule.router = { 'gw_port': { 'mac_address': mac_address}, l3_constants.INTERFACE_KEY: [{ 'mac_address': mac_address}] } trusted_zone_name = vyatta_utils.get_trusted_zone_name( fake_apply_rule) untrusted_zone_name = vyatta_utils.get_untrusted_zone_name( fake_apply_rule) cmds_actual = vyatta_utils.get_zone_cmds( fake_api, fake_apply_rule, firewall_name) cmds_expect = [ vyatta_client.DeleteCmd('zone-policy'), vyatta_client.SetCmd( vyatta_utils.ZONE_INTERFACE_CMD.format( trusted_zone_name, eth_iface)), vyatta_client.SetCmd( vyatta_utils.ZONE_INTERFACE_CMD.format( untrusted_zone_name, eth_iface)), vyatta_client.SetCmd( vyatta_utils.ZONE_FIREWALL_CMD.format( trusted_zone_name, untrusted_zone_name, parse.quote_plus(firewall_name))), vyatta_client.SetCmd( vyatta_utils.ZONE_FIREWALL_CMD.format( untrusted_zone_name, trusted_zone_name, parse.quote_plus(firewall_name))), ] self.assertEqual(cmds_expect, cmds_actual) fake_api.get_ethernet_if_id.assert_has_calls([ mock.call(mac_address), mock.call(mac_address), ]) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/vyatta/__init__.py0000664000567000056710000000000012701407720032765 0ustar jenkinsjenkins00000000000000././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/vyatta/test_firewall_service.pyneutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/agents/vyatta/test_firewall_service.p0000664000567000056710000000644612701407720035445 0ustar jenkinsjenkins00000000000000# Copyright 2015 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. import sys import uuid import mock from neutron.tests import base class FakeL3AgentMidleware(object): def __init__(self, host, conf=None): self._vyatta_clients_pool = mock.Mock() self.fwplugin_rpc = mock.Mock() self.conf = conf # Mocking imports of 3rd party vyatta library in unit tests and all modules # that depends on this library. Import will fail if not mocked and 3rd party # vyatta library is not installed. with mock.patch.dict(sys.modules, { 'networking_brocade': mock.Mock(), 'networking_brocade.vyatta': mock.Mock(), 'networking_brocade.vyatta.common': mock.Mock(), 'networking_brocade.vyatta.vrouter': mock.Mock(), }): from networking_brocade.vyatta.common import l3_agent l3_agent.L3AgentMiddleware = FakeL3AgentMidleware from neutron_fwaas.services.firewall.agents.vyatta import firewall_service from neutron_fwaas.services.firewall.agents.vyatta import fwaas_agent from neutron_fwaas.services.firewall.agents.vyatta import vyatta_utils def fake_cmd(*args, **kwargs): return (args, kwargs) class TestVyattaFirewallService(base.BaseTestCase): def test_sync_firewall_zones(self): agent = self._make_agent() fake_client = mock.Mock() agent._vyatta_clients_pool.get_by_db_lookup.return_value = fake_client router_id = str(uuid.uuid4()) fake_fw_record = { 'id': str(uuid.uuid4()), 'name': 'fake-fw-record0', 'router_ids': [router_id] } agent.fwplugin_rpc.get_firewalls_for_tenant.return_value = [ fake_fw_record ] router = { 'id': router_id, 'tenant_id': str(uuid.uuid4()) } router_info = mock.NonCallableMock() router_info.router = router cmd_list = [ fake_cmd("zone-policy"), fake_cmd(vyatta_utils.ZONE_INTERFACE_CMD.format( 'fake-zone', 'eth0')), fake_cmd(vyatta_utils.ZONE_FIREWALL_CMD.format( vyatta_utils.UNTRUST_ZONE, vyatta_utils.TRUST_ZONE, 'fake-fw-name')) ] with mock.patch.object( vyatta_utils, 'get_zone_cmds') as get_zone_mock: get_zone_mock.return_value = cmd_list firewall_service.sync_firewall_zones( None, None, agent, router=router_info) agent._vyatta_clients_pool.get_by_db_lookup.assert_called_once_with( router_info.router['id'], mock.ANY) fake_client.exec_cmd_batch.assert_called_once_with(cmd_list) def _make_agent(self): agent = fwaas_agent.VyattaFirewallAgent('fake-host') agent.router_info = dict() return agent neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/firewall/test_fwaas_plugin.py0000664000567000056710000007720512701407720032200 0ustar jenkinsjenkins00000000000000# Copyright 2013 Big Switch 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. import mock from neutron.api.v2 import attributes as attr from neutron import context from neutron import manager from neutron.plugins.common import constants as const from neutron.tests import fake_notifier from neutron.tests.unit.extensions import test_l3 as test_l3_plugin from oslo_config import cfg import six from webob import exc import neutron_fwaas.extensions from neutron_fwaas.extensions import firewall from neutron_fwaas.extensions import firewallrouterinsertion from neutron_fwaas.services.firewall import fwaas_plugin from neutron_fwaas.tests import base from neutron_fwaas.tests.unit.db.firewall import ( test_firewall_db as test_db_firewall) extensions_path = neutron_fwaas.extensions.__path__[0] FW_PLUGIN_KLASS = ( "neutron_fwaas.services.firewall.fwaas_plugin.FirewallPlugin" ) class FirewallTestExtensionManager(test_l3_plugin.L3TestExtensionManager): def get_resources(self): res = super(FirewallTestExtensionManager, self).get_resources() firewall.RESOURCE_ATTRIBUTE_MAP['firewalls'].update( firewallrouterinsertion.EXTENDED_ATTRIBUTES_2_0['firewalls']) return res + firewall.Firewall.get_resources() def get_actions(self): return [] def get_request_extensions(self): return [] class TestFirewallRouterInsertionBase( test_db_firewall.FirewallPluginDbTestCase): def setUp(self, core_plugin=None, fw_plugin=None, ext_mgr=None): self.agentapi_del_fw_p = mock.patch(test_db_firewall.DELETEFW_PATH, create=True, new=test_db_firewall.FakeAgentApi().delete_firewall) self.agentapi_del_fw_p.start() # the plugin without L3 support plugin = 'neutron.tests.unit.extensions.test_l3.TestNoL3NatPlugin' # the L3 service plugin l3_plugin = ('neutron.tests.unit.extensions.test_l3.' 'TestL3NatServicePlugin') cfg.CONF.set_override('api_extensions_path', extensions_path) self.saved_attr_map = {} for resource, attrs in six.iteritems(attr.RESOURCE_ATTRIBUTE_MAP): self.saved_attr_map[resource] = attrs.copy() if not fw_plugin: fw_plugin = FW_PLUGIN_KLASS service_plugins = {'l3_plugin_name': l3_plugin, 'fw_plugin_name': fw_plugin} if not ext_mgr: ext_mgr = FirewallTestExtensionManager() super(test_db_firewall.FirewallPluginDbTestCase, self).setUp( plugin=plugin, service_plugins=service_plugins, ext_mgr=ext_mgr) self.setup_notification_driver() self.l3_plugin = manager.NeutronManager.get_service_plugins().get( const.L3_ROUTER_NAT) self.plugin = manager.NeutronManager.get_service_plugins().get( const.FIREWALL) self.callbacks = self.plugin.endpoints[0] def restore_attribute_map(self): # Remove the csrfirewallinsertion extension firewall.RESOURCE_ATTRIBUTE_MAP['firewalls'].pop('router_ids') # Restore the original RESOURCE_ATTRIBUTE_MAP attr.RESOURCE_ATTRIBUTE_MAP = self.saved_attr_map def tearDown(self): self.restore_attribute_map() super(TestFirewallRouterInsertionBase, self).tearDown() def _create_firewall(self, fmt, name, description, firewall_policy_id=None, admin_state_up=True, expected_res_status=None, **kwargs): tenant_id = kwargs.get('tenant_id', self._tenant_id) router_ids = kwargs.get('router_ids') if firewall_policy_id is None: res = self._create_firewall_policy(fmt, 'fwp', description="firewall_policy", shared=True, firewall_rules=[], audited=True) firewall_policy = self.deserialize(fmt or self.fmt, res) firewall_policy_id = firewall_policy["firewall_policy"]["id"] data = {'firewall': {'name': name, 'description': description, 'firewall_policy_id': firewall_policy_id, 'admin_state_up': admin_state_up, 'tenant_id': tenant_id}} if router_ids is not None: data['firewall']['router_ids'] = router_ids firewall_req = self.new_create_request('firewalls', data, fmt) firewall_res = firewall_req.get_response(self.ext_api) if expected_res_status: self.assertEqual(expected_res_status, firewall_res.status_int) return firewall_res class TestFirewallCallbacks(TestFirewallRouterInsertionBase): def setUp(self): super(TestFirewallCallbacks, self).setUp(fw_plugin=FW_PLUGIN_KLASS) self.callbacks = self.plugin.endpoints[0] def test_set_firewall_status(self): ctx = context.get_admin_context() with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall( firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP ) as fw: fw_id = fw['firewall']['id'] res = self.callbacks.set_firewall_status(ctx, fw_id, const.ACTIVE, host='dummy') fw_db = self.plugin.get_firewall(ctx, fw_id) self.assertEqual(const.ACTIVE, fw_db['status']) self.assertTrue(res) res = self.callbacks.set_firewall_status(ctx, fw_id, const.ERROR) fw_db = self.plugin.get_firewall(ctx, fw_id) self.assertEqual(const.ERROR, fw_db['status']) self.assertFalse(res) def test_set_firewall_status_pending_delete(self): ctx = context.get_admin_context() with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall( firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP ) as fw: fw_id = fw['firewall']['id'] fw_db = self.plugin._get_firewall(ctx, fw_id) fw_db['status'] = const.PENDING_DELETE ctx.session.flush() res = self.callbacks.set_firewall_status(ctx, fw_id, const.ACTIVE, host='dummy') fw_db = self.plugin.get_firewall(ctx, fw_id) self.assertEqual(const.PENDING_DELETE, fw_db['status']) self.assertFalse(res) def test_firewall_deleted(self): ctx = context.get_admin_context() with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP, do_delete=False) as fw: fw_id = fw['firewall']['id'] with ctx.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(ctx, fw_id) fw_db['status'] = const.PENDING_DELETE ctx.session.flush() res = self.callbacks.firewall_deleted(ctx, fw_id, host='dummy') self.assertTrue(res) self.assertRaises(firewall.FirewallNotFound, self.plugin.get_firewall, ctx, fw_id) def test_firewall_deleted_error(self): ctx = context.get_admin_context() with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall( firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP, ) as fw: fw_id = fw['firewall']['id'] res = self.callbacks.firewall_deleted(ctx, fw_id, host='dummy') self.assertFalse(res) fw_db = self.plugin._get_firewall(ctx, fw_id) self.assertEqual(const.ERROR, fw_db['status']) def test_get_firewall_for_tenant(self): tenant_id = 'test-tenant' ctx = context.Context('', tenant_id) with self.firewall_rule(name='fwr1', tenant_id=tenant_id) as fwr1, \ self.firewall_rule(name='fwr2', tenant_id=tenant_id) as fwr2, \ self.firewall_rule(name='fwr3', tenant_id=tenant_id) as fwr3: with self.firewall_policy(tenant_id=tenant_id) as fwp: fwp_id = fwp['firewall_policy']['id'] fr = [fwr1, fwr2, fwr3] fw_rule_ids = [r['firewall_rule']['id'] for r in fr] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp_id) res = req.get_response(self.ext_api) attrs = self._get_test_firewall_attrs() attrs['firewall_policy_id'] = fwp_id with self.firewall( firewall_policy_id=fwp_id, tenant_id=tenant_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP) as fw: fw_id = fw['firewall']['id'] res = self.callbacks.get_firewalls_for_tenant(ctx, host='dummy') fw_rules = ( self.plugin._make_firewall_dict_with_rules(ctx, fw_id) ) fw_rules['add-router-ids'] = [] fw_rules['del-router-ids'] = [] self.assertEqual(fw_rules, res[0]) self._compare_firewall_rule_lists( fwp_id, fr, res[0]['firewall_rule_list']) def test_get_firewall_for_tenant_without_rules(self): tenant_id = 'test-tenant' ctx = context.Context('', tenant_id) with self.firewall_policy(tenant_id=tenant_id) as fwp: fwp_id = fwp['firewall_policy']['id'] attrs = self._get_test_firewall_attrs() attrs['firewall_policy_id'] = fwp_id with self.firewall(firewall_policy_id=fwp_id, tenant_id=tenant_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP ) as fw: # router_ids is not present in the firewall db # but is added in the get_firewalls override by plugin fw_list = [fw['firewall']] f = self.callbacks.get_firewalls_for_tenant_without_rules res = f(ctx, host='dummy') for fw in res: del fw['shared'] self.assertEqual(fw_list, res) class TestFirewallAgentApi(base.BaseTestCase): def setUp(self): super(TestFirewallAgentApi, self).setUp() self.api = fwaas_plugin.FirewallAgentApi('topic', 'host') def test_init(self): self.assertEqual('topic', self.api.client.target.topic) self.assertEqual('host', self.api.host) def _call_test_helper(self, method_name): with mock.patch.object(self.api.client, 'cast') as rpc_mock, \ mock.patch.object(self.api.client, 'prepare') as prepare_mock: prepare_mock.return_value = self.api.client getattr(self.api, method_name)(mock.sentinel.context, 'test') prepare_args = {'fanout': True} prepare_mock.assert_called_once_with(**prepare_args) rpc_mock.assert_called_once_with(mock.sentinel.context, method_name, firewall='test', host='host') def test_create_firewall(self): self._call_test_helper('create_firewall') def test_update_firewall(self): self._call_test_helper('update_firewall') def test_delete_firewall(self): self._call_test_helper('delete_firewall') class TestFirewallPluginBase(TestFirewallRouterInsertionBase, test_l3_plugin.L3NatTestCaseMixin): def setUp(self): super(TestFirewallPluginBase, self).setUp(fw_plugin=FW_PLUGIN_KLASS) fake_notifier.reset() def tearDown(self): super(TestFirewallPluginBase, self).tearDown() def test_create_firewall_routers_not_specified(self): """neutron firewall-create test-policy """ with self.router(name='router1', admin_state_up=True, tenant_id=self._tenant_id): with self.router(name='router2', admin_state_up=True, tenant_id=self._tenant_id): with self.firewall() as fw1: self.assertEqual(const.PENDING_CREATE, fw1['firewall']['status']) def test_create_firewall_routers_specified(self): """neutron firewall-create test-policy --router-ids "r1 r2" """ with self.router(name='router1', admin_state_up=True, tenant_id=self._tenant_id) as router1: with self.router(name='router2', admin_state_up=True, tenant_id=self._tenant_id) as router2: router_ids = [router1['router']['id'], router2['router']['id']] with self.firewall(router_ids=router_ids) as fw1: self.assertEqual(const.PENDING_CREATE, fw1['firewall']['status']) def test_create_firewall_routers_present_empty_list_specified(self): """neutron firewall-create test-policy --router-ids "" """ with self.router(name='router1', admin_state_up=True, tenant_id=self._tenant_id): with self.router(name='router2', admin_state_up=True, tenant_id=self._tenant_id): router_ids = [] with self.firewall(router_ids=router_ids) as fw1: self.assertEqual(const.INACTIVE, fw1['firewall']['status']) def test_create_firewall_no_routers_empty_list_specified(self): """neutron firewall-create test-policy --router-ids "" """ router_ids = [] with self.firewall(router_ids=router_ids) as fw1: self.assertEqual(const.INACTIVE, fw1['firewall']['status']) def test_create_second_firewall_on_same_tenant(self): """fw1 created with default routers, fw2 no routers on same tenant.""" with self.router(name='router1', admin_state_up=True, tenant_id=self._tenant_id): with self.router(name='router2', admin_state_up=True, tenant_id=self._tenant_id): router_ids = [] with self.firewall() as fw1: with self.firewall(router_ids=router_ids) as fw2: self.assertEqual(const.PENDING_CREATE, fw1['firewall']['status']) self.assertEqual(const.INACTIVE, fw2['firewall']['status']) def test_create_firewall_admin_not_affected_by_other_tenant(self): # Create fw with admin after creating fw with other tenant with self.firewall(tenant_id='other-tenant') as fw1: with self.firewall() as fw2: self.assertEqual('other-tenant', fw1['firewall']['tenant_id']) self.assertEqual(self._tenant_id, fw2['firewall']['tenant_id']) def test_update_firewall(self): ctx = context.get_admin_context() name = "new_firewall1" attrs = self._get_test_firewall_attrs(name) with self.router(name='router1', admin_state_up=True, tenant_id=self._tenant_id) as router1: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall( firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP, router_ids=[router1['router']['id']] ) as firewall: fw_id = firewall['firewall']['id'] res = self.callbacks.set_firewall_status(ctx, fw_id, const.ACTIVE) data = {'firewall': {'name': name}} req = self.new_update_request('firewalls', data, fw_id) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) attrs = self._replace_firewall_status(attrs, const.PENDING_CREATE, const.PENDING_UPDATE) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall'][k]) def test_update_firewall_fails_when_firewall_pending(self): name = "new_firewall1" attrs = self._get_test_firewall_attrs(name) with self.router(name='router1', admin_state_up=True, tenant_id=self._tenant_id) as router1: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall( firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP, router_ids=[router1['router']['id']] ) as firewall: fw_id = firewall['firewall']['id'] data = {'firewall': {'name': name}} req = self.new_update_request('firewalls', data, fw_id) res = req.get_response(self.ext_api) self.assertEqual(exc.HTTPConflict.code, res.status_int) def test_update_firewall_with_router_when_firewall_inactive(self): name = "firewall1" attrs = self._get_test_firewall_attrs(name) with self.router(name='router1', admin_state_up=True, tenant_id=self._tenant_id) as router1: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall( name=name, firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP, router_ids=[] ) as firewall: fw_id = firewall['firewall']['id'] data = { 'firewall': {'router_ids': [router1['router']['id']]}} req = self.new_update_request('firewalls', data, fw_id) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) attrs = self._replace_firewall_status(attrs, const.PENDING_CREATE, const.PENDING_UPDATE) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall'][k]) def test_update_firewall_shared_fails_for_non_admin(self): ctx = context.get_admin_context() with self.router(name='router1', admin_state_up=True, tenant_id=self._tenant_id) as router1: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall( firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP, tenant_id='noadmin', router_ids=[router1['router']['id']] ) as firewall: fw_id = firewall['firewall']['id'] self.callbacks.set_firewall_status(ctx, fw_id, const.ACTIVE) data = {'firewall': {'shared': True}} req = self.new_update_request( 'firewalls', data, fw_id, context=context.Context('', 'noadmin')) res = req.get_response(self.ext_api) self.assertEqual(exc.HTTPForbidden.code, res.status_int) def test_update_firewall_policy_fails_when_firewall_pending(self): name = "new_firewall1" attrs = self._get_test_firewall_attrs(name) with self.router(name='router1', admin_state_up=True, tenant_id=self._tenant_id): with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall( firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP ): data = {'firewall_policy': {'name': name}} req = self.new_update_request('firewall_policies', data, fwp_id) res = req.get_response(self.ext_api) self.assertEqual(exc.HTTPConflict.code, res.status_int) def test_update_firewall_rule_fails_when_firewall_pending(self): with self.router(name='router1', admin_state_up=True, tenant_id=self._tenant_id): with self.firewall_rule(name='fwr1') as fr: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] fr_id = fr['firewall_rule']['id'] fw_rule_ids = [fr_id] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp_id) req.get_response(self.ext_api) with self.firewall( firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP ): data = {'firewall_rule': {'protocol': 'udp'}} req = self.new_update_request('firewall_rules', data, fr_id) res = req.get_response(self.ext_api) self.assertEqual(exc.HTTPConflict.code, res.status_int) def test_delete_firewall_with_no_routers(self): ctx = context.get_admin_context() # stop the AgentRPC patch for this one to test pending states self.agentapi_del_fw_p.stop() with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall( firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP, do_delete=False ) as fw: fw_id = fw['firewall']['id'] req = self.new_delete_request('firewalls', fw_id) res = req.get_response(self.ext_api) self.assertEqual(exc.HTTPNoContent.code, res.status_int) self.assertRaises(firewall.FirewallNotFound, self.plugin.get_firewall, ctx, fw_id) def test_delete_firewall_after_agent_delete(self): ctx = context.get_admin_context() with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(firewall_policy_id=fwp_id, do_delete=False) as fw: fw_id = fw['firewall']['id'] req = self.new_delete_request('firewalls', fw_id) res = req.get_response(self.ext_api) self.assertEqual(exc.HTTPNoContent.code, res.status_int) self.assertRaises(firewall.FirewallNotFound, self.plugin.get_firewall, ctx, fw_id) def test_make_firewall_dict_with_in_place_rules(self): ctx = context.get_admin_context() with self.firewall_rule(name='fwr1') as fwr1, \ self.firewall_rule(name='fwr2') as fwr2, \ self.firewall_rule(name='fwr3') as fwr3: with self.firewall_policy() as fwp: fr = [fwr1, fwr2, fwr3] fwp_id = fwp['firewall_policy']['id'] fw_rule_ids = [r['firewall_rule']['id'] for r in fr] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp_id) req.get_response(self.ext_api) attrs = self._get_test_firewall_attrs() attrs['firewall_policy_id'] = fwp_id with self.firewall( firewall_policy_id=fwp_id, admin_state_up=test_db_firewall.ADMIN_STATE_UP, router_ids=[] ) as fw: fw_id = fw['firewall']['id'] fw_rules = ( self.plugin._make_firewall_dict_with_rules(ctx, fw_id) ) self.assertEqual(fw_id, fw_rules['id']) self._compare_firewall_rule_lists( fwp_id, fr, fw_rules['firewall_rule_list']) def test_make_firewall_dict_with_in_place_rules_no_policy(self): ctx = context.get_admin_context() with self.firewall() as fw: fw_id = fw['firewall']['id'] fw_rules = self.plugin._make_firewall_dict_with_rules(ctx, fw_id) self.assertEqual([], fw_rules['firewall_rule_list']) def test_list_firewalls(self): with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(name='fw1', firewall_policy_id=fwp_id, description='fw') as fwalls: self._test_list_resources('firewall', [fwalls], query_params='description=fw') def test_insert_rule(self): ctx = context.get_admin_context() with self.firewall_rule() as fwr: fr_id = fwr['firewall_rule']['id'] rule_info = {'firewall_rule_id': fr_id} with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(firewall_policy_id=fwp_id) as fw: fw_id = fw['firewall']['id'] self.plugin.insert_rule(ctx, fwp_id, rule_info) fw_rules = self.plugin._make_firewall_dict_with_rules( ctx, fw_id) self.assertEqual(1, len(fw_rules['firewall_rule_list'])) self.assertEqual(fr_id, fw_rules['firewall_rule_list'][0]['id']) def test_insert_rule_notif(self): ctx = context.get_admin_context() with self.firewall_rule() as fwr: fr_id = fwr['firewall_rule']['id'] rule_info = {'firewall_rule_id': fr_id} with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(firewall_policy_id=fwp_id): self.plugin.insert_rule(ctx, fwp_id, rule_info) notifications = fake_notifier.NOTIFICATIONS expected_event_type = 'firewall_policy.update.insert_rule' event_types = [event['event_type'] for event in notifications] self.assertIn(expected_event_type, event_types) def test_remove_rule(self): ctx = context.get_admin_context() with self.firewall_rule() as fwr: fr_id = fwr['firewall_rule']['id'] rule_info = {'firewall_rule_id': fr_id} with self.firewall_policy(firewall_rules=[fr_id]) as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(firewall_policy_id=fwp_id) as fw: fw_id = fw['firewall']['id'] self.plugin.remove_rule(ctx, fwp_id, rule_info) fw_rules = self.plugin._make_firewall_dict_with_rules( ctx, fw_id) self.assertEqual([], fw_rules['firewall_rule_list']) def test_remove_rule_notif(self): ctx = context.get_admin_context() with self.firewall_rule() as fwr: fr_id = fwr['firewall_rule']['id'] rule_info = {'firewall_rule_id': fr_id} with self.firewall_policy(firewall_rules=[fr_id]) as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(firewall_policy_id=fwp_id): self.plugin.remove_rule(ctx, fwp_id, rule_info) notifications = fake_notifier.NOTIFICATIONS expected_event_type = 'firewall_policy.update.remove_rule' event_types = [event['event_type'] for event in notifications] self.assertIn(expected_event_type, event_types) def test_firewall_quota_lower(self): """Test quota using overridden value.""" cfg.CONF.set_override('quota_firewall', 3, group='QUOTAS') with self.firewall(name='quota1'), \ self.firewall(name='quota2'), \ self.firewall(name='quota3'): data = {'firewall': {'name': 'quota4', 'firewall_policy_id': None, 'tenant_id': self._tenant_id, 'shared': False}} req = self.new_create_request('firewalls', data, 'json') res = req.get_response(self.ext_api) self.assertIn('Quota exceeded', res.body.decode('utf-8')) self.assertEqual(exc.HTTPConflict.code, res.status_int) def test_firewall_quota_default(self): """Test quota using default value.""" with self.firewall(name='quota1'), \ self.firewall(name='quota2'), \ self.firewall(name='quota3'), \ self.firewall(name='quota4'), \ self.firewall(name='quota5'), \ self.firewall(name='quota6'), \ self.firewall(name='quota7'), \ self.firewall(name='quota8'), \ self.firewall(name='quota9'), \ self.firewall(name='quota10'): data = {'firewall': {'name': 'quota11', 'firewall_policy_id': None, 'tenant_id': self._tenant_id, 'shared': False}} req = self.new_create_request('firewalls', data, 'json') res = req.get_response(self.ext_api) self.assertIn('Quota exceeded', res.body.decode('utf-8')) self.assertEqual(exc.HTTPConflict.code, res.status_int) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/services/__init__.py0000664000567000056710000000000012701407720026367 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/extensions/0000775000567000056710000000000012701410073024637 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/extensions/__init__.py0000664000567000056710000000000012701407720026743 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/extensions/test_firewall.py0000664000567000056710000006453012701407720030072 0ustar jenkinsjenkins00000000000000# Copyright 2013 Big Switch 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. import copy import mock from neutron.api.v2 import attributes as attr from neutron.plugins.common import constants from neutron.tests import base from neutron.tests.unit.api.v2 import test_base as test_api_v2 from neutron.tests.unit.extensions import base as test_api_v2_extension from oslo_utils import uuidutils from webob import exc import webtest from neutron_fwaas.extensions import firewall _uuid = uuidutils.generate_uuid _get_path = test_api_v2._get_path _long_name = 'x' * (attr.NAME_MAX_LEN + 1) _long_description = 'y' * (attr.DESCRIPTION_MAX_LEN + 1) class FirewallExtensionTestCase(test_api_v2_extension.ExtensionTestCase): fmt = 'json' def setUp(self): super(FirewallExtensionTestCase, self).setUp() plural_mappings = {'firewall_policy': 'firewall_policies'} self._setUpExtension( 'neutron_fwaas.extensions.firewall.FirewallPluginBase', constants.FIREWALL, firewall.RESOURCE_ATTRIBUTE_MAP, firewall.Firewall, 'fw', plural_mappings=plural_mappings) def test_create_firewall(self): fw_id = _uuid() data = {'firewall': {'description': 'descr_firewall1', 'name': 'firewall1', 'admin_state_up': True, 'firewall_policy_id': _uuid(), 'shared': False, 'tenant_id': _uuid()}} return_value = copy.copy(data['firewall']) return_value.update({'id': fw_id}) # since 'shared' is hidden del return_value['shared'] instance = self.plugin.return_value instance.create_firewall.return_value = return_value res = self.api.post(_get_path('fw/firewalls', fmt=self.fmt), self.serialize(data), content_type='application/%s' % self.fmt) instance.create_firewall.assert_called_with(mock.ANY, firewall=data) self.assertEqual(exc.HTTPCreated.code, res.status_int) res = self.deserialize(res) self.assertIn('firewall', res) self.assertEqual(return_value, res['firewall']) def test_create_firewall_invalid_long_name(self): data = {'firewall': {'description': 'descr_firewall1', 'name': _long_name, 'admin_state_up': True, 'firewall_policy_id': _uuid(), 'shared': False, 'tenant_id': _uuid()}} res = self.api.post(_get_path('fw/firewalls', fmt=self.fmt), self.serialize(data), content_type='application/%s' % self.fmt, status=exc.HTTPBadRequest.code) self.assertIn('Invalid input for name', res.body.decode('utf-8')) def test_create_firewall_invalid_long_description(self): data = {'firewall': {'description': _long_description, 'name': 'firewall1', 'admin_state_up': True, 'firewall_policy_id': _uuid(), 'shared': False, 'tenant_id': _uuid()}} res = self.api.post(_get_path('fw/firewalls', fmt=self.fmt), self.serialize(data), content_type='application/%s' % self.fmt, status=exc.HTTPBadRequest.code) self.assertIn('Invalid input for description', res.body.decode('utf-8')) def test_firewall_list(self): fw_id = _uuid() return_value = [{'tenant_id': _uuid(), 'id': fw_id}] instance = self.plugin.return_value instance.get_firewalls.return_value = return_value res = self.api.get(_get_path('fw/firewalls', fmt=self.fmt)) instance.get_firewalls.assert_called_with(mock.ANY, fields=mock.ANY, filters=mock.ANY) self.assertEqual(exc.HTTPOk.code, res.status_int) def test_firewall_get(self): fw_id = _uuid() return_value = {'tenant_id': _uuid(), 'id': fw_id} instance = self.plugin.return_value instance.get_firewall.return_value = return_value res = self.api.get(_get_path('fw/firewalls', id=fw_id, fmt=self.fmt)) instance.get_firewall.assert_called_with(mock.ANY, fw_id, fields=mock.ANY) self.assertEqual(exc.HTTPOk.code, res.status_int) res = self.deserialize(res) self.assertIn('firewall', res) self.assertEqual(return_value, res['firewall']) def test_firewall_update(self): fw_id = _uuid() update_data = {'firewall': {'name': 'new_name'}} return_value = {'tenant_id': _uuid(), 'id': fw_id} instance = self.plugin.return_value instance.update_firewall.return_value = return_value res = self.api.put(_get_path('fw/firewalls', id=fw_id, fmt=self.fmt), self.serialize(update_data)) instance.update_firewall.assert_called_with(mock.ANY, fw_id, firewall=update_data) self.assertEqual(exc.HTTPOk.code, res.status_int) res = self.deserialize(res) self.assertIn('firewall', res) self.assertEqual(return_value, res['firewall']) def test_firewall_delete(self): self._test_entity_delete('firewall') def _test_create_firewall_rule(self, src_port, dst_port): rule_id = _uuid() data = {'firewall_rule': {'description': 'descr_firewall_rule1', 'name': 'rule1', 'shared': False, 'protocol': 'tcp', 'ip_version': 4, 'source_ip_address': '192.168.0.1', 'destination_ip_address': '127.0.0.1', 'source_port': src_port, 'destination_port': dst_port, 'action': 'allow', 'enabled': True, 'tenant_id': _uuid()}} expected_ret_val = copy.copy(data['firewall_rule']) expected_ret_val['source_port'] = str(src_port) expected_ret_val['destination_port'] = str(dst_port) expected_call_args = copy.copy(expected_ret_val) expected_ret_val['id'] = rule_id instance = self.plugin.return_value instance.create_firewall_rule.return_value = expected_ret_val res = self.api.post(_get_path('fw/firewall_rules', fmt=self.fmt), self.serialize(data), content_type='application/%s' % self.fmt) instance.create_firewall_rule.assert_called_with( mock.ANY, firewall_rule={'firewall_rule': expected_call_args}) self.assertEqual(exc.HTTPCreated.code, res.status_int) res = self.deserialize(res) self.assertIn('firewall_rule', res) self.assertEqual(expected_ret_val, res['firewall_rule']) def test_create_firewall_rule_with_integer_ports(self): self._test_create_firewall_rule(1, 10) def test_create_firewall_rule_with_string_ports(self): self._test_create_firewall_rule('1', '10') def test_create_firewall_rule_with_port_range(self): self._test_create_firewall_rule('1:20', '30:40') def test_create_firewall_rule_invalid_long_name(self): data = {'firewall_rule': {'description': 'descr_firewall_rule1', 'name': _long_name, 'shared': False, 'protocol': 'tcp', 'ip_version': 4, 'source_ip_address': '192.168.0.1', 'destination_ip_address': '127.0.0.1', 'source_port': 1, 'destination_port': 1, 'action': 'allow', 'enabled': True, 'tenant_id': _uuid()}} res = self.api.post(_get_path('fw/firewall_rules', fmt=self.fmt), self.serialize(data), content_type='application/%s' % self.fmt, status=exc.HTTPBadRequest.code) self.assertIn('Invalid input for name', res.body.decode('utf-8')) def test_create_firewall_rule_invalid_long_description(self): data = {'firewall_rule': {'description': _long_description, 'name': 'rule1', 'shared': False, 'protocol': 'tcp', 'ip_version': 4, 'source_ip_address': '192.168.0.1', 'destination_ip_address': '127.0.0.1', 'source_port': 1, 'destination_port': 1, 'action': 'allow', 'enabled': True, 'tenant_id': _uuid()}} res = self.api.post(_get_path('fw/firewall_rules', fmt=self.fmt), self.serialize(data), content_type='application/%s' % self.fmt, status=exc.HTTPBadRequest.code) self.assertIn('Invalid input for description', res.body.decode('utf-8')) def test_firewall_rule_list(self): rule_id = _uuid() return_value = [{'tenant_id': _uuid(), 'id': rule_id}] instance = self.plugin.return_value instance.get_firewall_rules.return_value = return_value res = self.api.get(_get_path('fw/firewall_rules', fmt=self.fmt)) instance.get_firewall_rules.assert_called_with(mock.ANY, fields=mock.ANY, filters=mock.ANY) self.assertEqual(exc.HTTPOk.code, res.status_int) def test_firewall_rule_get(self): rule_id = _uuid() return_value = {'tenant_id': _uuid(), 'id': rule_id} instance = self.plugin.return_value instance.get_firewall_rule.return_value = return_value res = self.api.get(_get_path('fw/firewall_rules', id=rule_id, fmt=self.fmt)) instance.get_firewall_rule.assert_called_with(mock.ANY, rule_id, fields=mock.ANY) self.assertEqual(exc.HTTPOk.code, res.status_int) res = self.deserialize(res) self.assertIn('firewall_rule', res) self.assertEqual(return_value, res['firewall_rule']) def test_firewall_rule_update(self): rule_id = _uuid() update_data = {'firewall_rule': {'action': 'deny'}} return_value = {'tenant_id': _uuid(), 'id': rule_id} instance = self.plugin.return_value instance.update_firewall_rule.return_value = return_value res = self.api.put(_get_path('fw/firewall_rules', id=rule_id, fmt=self.fmt), self.serialize(update_data)) instance.update_firewall_rule.assert_called_with( mock.ANY, rule_id, firewall_rule=update_data) self.assertEqual(exc.HTTPOk.code, res.status_int) res = self.deserialize(res) self.assertIn('firewall_rule', res) self.assertEqual(return_value, res['firewall_rule']) def test_firewall_rule_delete(self): self._test_entity_delete('firewall_rule') def test_create_firewall_policy(self): policy_id = _uuid() data = {'firewall_policy': {'description': 'descr_firewall_policy1', 'name': 'new_fw_policy1', 'shared': False, 'firewall_rules': [_uuid(), _uuid()], 'audited': False, 'tenant_id': _uuid()}} return_value = copy.copy(data['firewall_policy']) return_value.update({'id': policy_id}) instance = self.plugin.return_value instance.create_firewall_policy.return_value = return_value res = self.api.post(_get_path('fw/firewall_policies', fmt=self.fmt), self.serialize(data), content_type='application/%s' % self.fmt) instance.create_firewall_policy.assert_called_with( mock.ANY, firewall_policy=data) self.assertEqual(exc.HTTPCreated.code, res.status_int) res = self.deserialize(res) self.assertIn('firewall_policy', res) self.assertEqual(return_value, res['firewall_policy']) def test_create_firewall_policy_invalid_long_name(self): data = {'firewall_policy': {'description': 'descr_firewall_policy1', 'name': _long_name, 'shared': False, 'firewall_rules': [_uuid(), _uuid()], 'audited': False, 'tenant_id': _uuid()}} res = self.api.post(_get_path('fw/firewall_policies', fmt=self.fmt), self.serialize(data), content_type='application/%s' % self.fmt, status=exc.HTTPBadRequest.code) self.assertIn('Invalid input for name', res.body.decode('utf-8')) def test_create_firewall_policy_invalid_long_description(self): data = {'firewall_policy': {'description': _long_description, 'name': 'new_fw_policy1', 'shared': False, 'firewall_rules': [_uuid(), _uuid()], 'audited': False, 'tenant_id': _uuid()}} res = self.api.post(_get_path('fw/firewall_policies', fmt=self.fmt), self.serialize(data), content_type='application/%s' % self.fmt, status=exc.HTTPBadRequest.code) self.assertIn('Invalid input for description', res.body.decode('utf-8')) def test_firewall_policy_list(self): policy_id = _uuid() return_value = [{'tenant_id': _uuid(), 'id': policy_id}] instance = self.plugin.return_value instance.get_firewall_policies.return_value = return_value res = self.api.get(_get_path('fw/firewall_policies', fmt=self.fmt)) instance.get_firewall_policies.assert_called_with(mock.ANY, fields=mock.ANY, filters=mock.ANY) self.assertEqual(exc.HTTPOk.code, res.status_int) def test_firewall_policy_get(self): policy_id = _uuid() return_value = {'tenant_id': _uuid(), 'id': policy_id} instance = self.plugin.return_value instance.get_firewall_policy.return_value = return_value res = self.api.get(_get_path('fw/firewall_policies', id=policy_id, fmt=self.fmt)) instance.get_firewall_policy.assert_called_with(mock.ANY, policy_id, fields=mock.ANY) self.assertEqual(exc.HTTPOk.code, res.status_int) res = self.deserialize(res) self.assertIn('firewall_policy', res) self.assertEqual(return_value, res['firewall_policy']) def test_firewall_policy_update(self): policy_id = _uuid() update_data = {'firewall_policy': {'audited': True}} return_value = {'tenant_id': _uuid(), 'id': policy_id} instance = self.plugin.return_value instance.update_firewall_policy.return_value = return_value res = self.api.put(_get_path('fw/firewall_policies', id=policy_id, fmt=self.fmt), self.serialize(update_data)) instance.update_firewall_policy.assert_called_with( mock.ANY, policy_id, firewall_policy=update_data) self.assertEqual(exc.HTTPOk.code, res.status_int) res = self.deserialize(res) self.assertIn('firewall_policy', res) self.assertEqual(return_value, res['firewall_policy']) def test_firewall_policy_update_malformed_rules(self): # emulating client request when no rule uuids are provided for # --firewall_rules parameter update_data = {'firewall_policy': {'firewall_rules': True}} # have to check for generic AppError self.assertRaises( webtest.AppError, self.api.put, _get_path('fw/firewall_policies', id=_uuid(), fmt=self.fmt), self.serialize(update_data)) def test_firewall_policy_delete(self): self._test_entity_delete('firewall_policy') def test_firewall_policy_insert_rule(self): firewall_policy_id = _uuid() firewall_rule_id = _uuid() ref_firewall_rule_id = _uuid() insert_data = {'firewall_rule_id': firewall_rule_id, 'insert_before': ref_firewall_rule_id, 'insert_after': None} return_value = {'firewall_policy': {'tenant_id': _uuid(), 'id': firewall_policy_id, 'firewall_rules': [ref_firewall_rule_id, firewall_rule_id]}} instance = self.plugin.return_value instance.insert_rule.return_value = return_value path = _get_path('fw/firewall_policies', id=firewall_policy_id, action="insert_rule", fmt=self.fmt) res = self.api.put(path, self.serialize(insert_data)) instance.insert_rule.assert_called_with(mock.ANY, firewall_policy_id, insert_data) self.assertEqual(exc.HTTPOk.code, res.status_int) res = self.deserialize(res) self.assertEqual(return_value, res) def test_firewall_policy_remove_rule(self): firewall_policy_id = _uuid() firewall_rule_id = _uuid() remove_data = {'firewall_rule_id': firewall_rule_id} return_value = {'firewall_policy': {'tenant_id': _uuid(), 'id': firewall_policy_id, 'firewall_rules': []}} instance = self.plugin.return_value instance.remove_rule.return_value = return_value path = _get_path('fw/firewall_policies', id=firewall_policy_id, action="remove_rule", fmt=self.fmt) res = self.api.put(path, self.serialize(remove_data)) instance.remove_rule.assert_called_with(mock.ANY, firewall_policy_id, remove_data) self.assertEqual(exc.HTTPOk.code, res.status_int) res = self.deserialize(res) self.assertEqual(return_value, res) class TestFirewallAttributeValidators(base.BaseTestCase): def test_validate_port_range(self): msg = firewall._validate_port_range(None) self.assertIsNone(msg) msg = firewall._validate_port_range('10') self.assertIsNone(msg) msg = firewall._validate_port_range(10) self.assertIsNone(msg) msg = firewall._validate_port_range(-1) self.assertEqual("Invalid port '-1'", msg) msg = firewall._validate_port_range('66000') self.assertEqual("Invalid port '66000'", msg) msg = firewall._validate_port_range('10:20') self.assertIsNone(msg) msg = firewall._validate_port_range('1:65535') self.assertIsNone(msg) msg = firewall._validate_port_range('0:65535') self.assertEqual("Invalid port '0'", msg) msg = firewall._validate_port_range('1:65536') self.assertEqual("Invalid port '65536'", msg) msg = firewall._validate_port_range('abc:efg') self.assertEqual("Port 'abc' is not a valid number", msg) msg = firewall._validate_port_range('1:efg') self.assertEqual("Port 'efg' is not a valid number", msg) msg = firewall._validate_port_range('-1:10') self.assertEqual("Invalid port '-1'", msg) msg = firewall._validate_port_range('66000:10') self.assertEqual("Invalid port '66000'", msg) msg = firewall._validate_port_range('10:66000') self.assertEqual("Invalid port '66000'", msg) msg = firewall._validate_port_range('1:-10') self.assertEqual("Invalid port '-10'", msg) def test_validate_ip_or_subnet_or_none(self): msg = firewall._validate_ip_or_subnet_or_none(None) self.assertIsNone(msg) msg = firewall._validate_ip_or_subnet_or_none('1.1.1.1') self.assertIsNone(msg) msg = firewall._validate_ip_or_subnet_or_none('1.1.1.0/24') self.assertIsNone(msg) ip_addr = '1111.1.1.1' msg = firewall._validate_ip_or_subnet_or_none(ip_addr) self.assertEqual( ("'%s' is not a valid IP address and " "'%s' is not a valid IP subnet") % (ip_addr, ip_addr), msg) ip_addr = '1.1.1.1 has whitespace' msg = firewall._validate_ip_or_subnet_or_none(ip_addr) self.assertEqual( ("'%s' is not a valid IP address and " "'%s' is not a valid IP subnet") % (ip_addr, ip_addr), msg) ip_addr = '111.1.1.1\twhitespace' msg = firewall._validate_ip_or_subnet_or_none(ip_addr) self.assertEqual( ("'%s' is not a valid IP address and " "'%s' is not a valid IP subnet") % (ip_addr, ip_addr), msg) ip_addr = '111.1.1.1\nwhitespace' msg = firewall._validate_ip_or_subnet_or_none(ip_addr) self.assertEqual( ("'%s' is not a valid IP address and " "'%s' is not a valid IP subnet") % (ip_addr, ip_addr), msg) # Valid - IPv4 cidr = "10.0.2.0/24" msg = firewall._validate_ip_or_subnet_or_none(cidr, None) self.assertIsNone(msg) # Valid - IPv6 without final octets cidr = "fe80::/24" msg = firewall._validate_ip_or_subnet_or_none(cidr, None) self.assertIsNone(msg) # Valid - IPv6 with final octets cidr = "fe80::0/24" msg = firewall._validate_ip_or_subnet_or_none(cidr, None) self.assertIsNone(msg) cidr = "fe80::" msg = firewall._validate_ip_or_subnet_or_none(cidr, None) self.assertIsNone(msg) # Invalid - IPv6 with final octets, missing mask cidr = "fe80::0" msg = firewall._validate_ip_or_subnet_or_none(cidr, None) self.assertIsNone(msg) # Invalid - Address format error cidr = 'invalid' msg = firewall._validate_ip_or_subnet_or_none(cidr, None) self.assertEqual( ("'%s' is not a valid IP address and " "'%s' is not a valid IP subnet") % (cidr, cidr), msg) class TestFirewallConvertProtocols(base.BaseTestCase): def test_convert_protocol_digit(self): res = firewall.convert_protocol("0") self.assertEqual(0, res) res = firewall.convert_protocol("255") self.assertEqual(255, res) def test_convert_protocol_invalid_digit(self): res = lambda: firewall.convert_protocol("-1") self.assertRaises(firewall.FirewallRuleInvalidProtocol, res) res = lambda: firewall.convert_protocol("256") self.assertRaises(firewall.FirewallRuleInvalidProtocol, res) def test_convert_protocol_name(self): res = firewall.convert_protocol("tcp") self.assertEqual("tcp", res) res = firewall.convert_protocol("UDP") self.assertEqual("udp", res) res = firewall.convert_protocol("Icmp") self.assertEqual("icmp", res) def test_convert_protocol_invalid_name(self): res = lambda: firewall.convert_protocol("foo") self.assertRaises(firewall.FirewallRuleInvalidProtocol, res) class TestConvertActionToCaseInsensitive(base.BaseTestCase): def test_convert_action_to_case_insensitive_none(self): res = firewall.convert_action_to_case_insensitive(None) self.assertIsNone(res) def test_convert_action_to_case_insensitive_value(self): res = firewall.convert_action_to_case_insensitive("foo") self.assertEqual("foo", res) res = firewall.convert_action_to_case_insensitive("Bar") self.assertEqual("bar", res) res = firewall.convert_action_to_case_insensitive("BAZ") self.assertEqual("baz", res) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/db/0000775000567000056710000000000012701410073023025 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/db/firewall/0000775000567000056710000000000012701410073024632 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/db/firewall/__init__.py0000664000567000056710000000000012701407720026736 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/db/firewall/test_firewall_db.py0000664000567000056710000021727512701407720030540 0ustar jenkinsjenkins00000000000000# Copyright 2013 Big Switch 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. import contextlib import mock from neutron.api import extensions as api_ext from neutron.common import config from neutron import context import neutron.extensions as nextensions from neutron.extensions import l3 from neutron import manager from neutron.plugins.common import constants from oslo_config import cfg from oslo_utils import importutils from oslo_utils import uuidutils import six import webob.exc from neutron_fwaas.db.firewall import firewall_db as fdb from neutron_fwaas import extensions from neutron_fwaas.extensions import firewall from neutron_fwaas.services.firewall import fwaas_plugin from neutron_fwaas.tests import base DB_FW_PLUGIN_KLASS = ( "neutron_fwaas.db.firewall.firewall_db.Firewall_db_mixin" ) FWAAS_PLUGIN = 'neutron_fwaas.services.firewall.fwaas_plugin' DELETEFW_PATH = FWAAS_PLUGIN + '.FirewallAgentApi.delete_firewall' extensions_path = ':'.join(extensions.__path__ + nextensions.__path__) DESCRIPTION = 'default description' SHARED = True PROTOCOL = 'tcp' IP_VERSION = 4 SOURCE_IP_ADDRESS_RAW = '1.1.1.1' DESTINATION_IP_ADDRESS_RAW = '2.2.2.2' SOURCE_PORT = '55000:56000' DESTINATION_PORT = '56000:57000' ACTION = 'allow' AUDITED = True ENABLED = True ADMIN_STATE_UP = True class FakeAgentApi(fwaas_plugin.FirewallCallbacks): """ This class used to mock the AgentAPI delete method inherits from FirewallCallbacks because it needs access to the firewall_deleted method. The delete_firewall method belongs to the FirewallAgentApi, which has no access to the firewall_deleted method normally because it's not responsible for deleting the firewall from the DB. However, it needs to in the unit tests since there is no agent to call back. """ def __init__(self): pass def delete_firewall(self, context, firewall, **kwargs): self.plugin = manager.NeutronManager.get_service_plugins()['FIREWALL'] self.firewall_deleted(context, firewall['id'], **kwargs) class FirewallPluginDbTestCase(base.NeutronDbPluginV2TestCase): resource_prefix_map = dict( (k, firewall.FIREWALL_PREFIX) for k in firewall.RESOURCE_ATTRIBUTE_MAP.keys() ) def setUp(self, core_plugin=None, fw_plugin=None, ext_mgr=None): self.agentapi_delf_p = mock.patch(DELETEFW_PATH, create=True, new=FakeAgentApi().delete_firewall) self.agentapi_delf_p.start() if not fw_plugin: fw_plugin = DB_FW_PLUGIN_KLASS service_plugins = {'fw_plugin_name': fw_plugin} fdb.Firewall_db_mixin.supported_extension_aliases = ["fwaas"] fdb.Firewall_db_mixin.path_prefix = firewall.FIREWALL_PREFIX super(FirewallPluginDbTestCase, self).setUp( ext_mgr=ext_mgr, service_plugins=service_plugins ) if not ext_mgr: self.plugin = importutils.import_object(fw_plugin) ext_mgr = api_ext.PluginAwareExtensionManager( extensions_path, {constants.FIREWALL: self.plugin} ) app = config.load_paste_app('extensions_test_app') self.ext_api = api_ext.ExtensionMiddleware(app, ext_mgr=ext_mgr) def _test_list_resources(self, resource, items, neutron_context=None, query_params=None): if resource.endswith('y'): resource_plural = resource.replace('y', 'ies') else: resource_plural = resource + 's' res = self._list(resource_plural, neutron_context=neutron_context, query_params=query_params) resource = resource.replace('-', '_') self.assertEqual( sorted([i[resource]['id'] for i in items]), sorted([i['id'] for i in res[resource_plural]])) def _get_test_firewall_rule_attrs(self, name='firewall_rule1'): attrs = {'name': name, 'tenant_id': self._tenant_id, 'shared': SHARED, 'protocol': PROTOCOL, 'ip_version': IP_VERSION, 'source_ip_address': SOURCE_IP_ADDRESS_RAW, 'destination_ip_address': DESTINATION_IP_ADDRESS_RAW, 'source_port': SOURCE_PORT, 'destination_port': DESTINATION_PORT, 'action': ACTION, 'enabled': ENABLED} return attrs def _get_test_firewall_policy_attrs(self, name='firewall_policy1', audited=AUDITED): attrs = {'name': name, 'description': DESCRIPTION, 'tenant_id': self._tenant_id, 'shared': SHARED, 'firewall_rules': [], 'audited': audited} return attrs def _get_test_firewall_attrs(self, name='firewall_1', status='PENDING_CREATE'): attrs = {'name': name, 'tenant_id': self._tenant_id, 'admin_state_up': ADMIN_STATE_UP, 'status': status} return attrs def _create_firewall_policy(self, fmt, name, description, shared, firewall_rules, audited, expected_res_status=None, **kwargs): tenant_id = kwargs.get('tenant_id', self._tenant_id) data = {'firewall_policy': {'name': name, 'description': description, 'tenant_id': tenant_id, 'shared': shared, 'firewall_rules': firewall_rules, 'audited': audited}} fw_policy_req = self.new_create_request('firewall_policies', data, fmt) fw_policy_res = fw_policy_req.get_response(self.ext_api) if expected_res_status: self.assertEqual(expected_res_status, fw_policy_res.status_int) return fw_policy_res def _replace_firewall_status(self, attrs, old_status, new_status): if attrs['status'] is old_status: attrs['status'] = new_status return attrs @contextlib.contextmanager def firewall_policy(self, fmt=None, name='firewall_policy1', description=DESCRIPTION, shared=True, firewall_rules=None, audited=True, do_delete=True, **kwargs): if firewall_rules is None: firewall_rules = [] if not fmt: fmt = self.fmt res = self._create_firewall_policy(fmt, name, description, shared, firewall_rules, audited, **kwargs) if res.status_int >= 400: raise webob.exc.HTTPClientError(code=res.status_int) firewall_policy = self.deserialize(fmt or self.fmt, res) yield firewall_policy if do_delete: self._delete('firewall_policies', firewall_policy['firewall_policy']['id']) def _create_firewall_rule(self, fmt, name, shared, protocol, ip_version, source_ip_address, destination_ip_address, source_port, destination_port, action, enabled, expected_res_status=None, **kwargs): tenant_id = kwargs.get('tenant_id', self._tenant_id) data = {'firewall_rule': {'name': name, 'tenant_id': tenant_id, 'shared': shared, 'protocol': protocol, 'ip_version': ip_version, 'source_ip_address': source_ip_address, 'destination_ip_address': destination_ip_address, 'source_port': source_port, 'destination_port': destination_port, 'action': action, 'enabled': enabled}} fw_rule_req = self.new_create_request('firewall_rules', data, fmt) fw_rule_res = fw_rule_req.get_response(self.ext_api) if expected_res_status: self.assertEqual(expected_res_status, fw_rule_res.status_int) return fw_rule_res @contextlib.contextmanager def firewall_rule(self, fmt=None, name='firewall_rule1', shared=SHARED, protocol=PROTOCOL, ip_version=IP_VERSION, source_ip_address=SOURCE_IP_ADDRESS_RAW, destination_ip_address=DESTINATION_IP_ADDRESS_RAW, source_port=SOURCE_PORT, destination_port=DESTINATION_PORT, action=ACTION, enabled=ENABLED, do_delete=True, **kwargs): if not fmt: fmt = self.fmt res = self._create_firewall_rule(fmt, name, shared, protocol, ip_version, source_ip_address, destination_ip_address, source_port, destination_port, action, enabled, **kwargs) if res.status_int >= 400: raise webob.exc.HTTPClientError(code=res.status_int) firewall_rule = self.deserialize(fmt or self.fmt, res) yield firewall_rule if do_delete: self._delete('firewall_rules', firewall_rule['firewall_rule']['id']) def _create_firewall(self, fmt, name, description, firewall_policy_id, admin_state_up=True, expected_res_status=None, **kwargs): tenant_id = kwargs.get('tenant_id', self._tenant_id) if firewall_policy_id is None: res = self._create_firewall_policy(fmt, 'fwp', description=DESCRIPTION, shared=True, firewall_rules=[], tenant_id=tenant_id, audited=AUDITED) firewall_policy = self.deserialize(fmt or self.fmt, res) firewall_policy_id = firewall_policy["firewall_policy"]["id"] data = {'firewall': {'name': name, 'description': description, 'firewall_policy_id': firewall_policy_id, 'admin_state_up': admin_state_up}} ctx = kwargs.get('context', None) if ctx is None or ctx.is_admin: data['firewall'].update({'tenant_id': tenant_id}) firewall_req = self.new_create_request('firewalls', data, fmt, context=ctx) firewall_res = firewall_req.get_response(self.ext_api) if expected_res_status: self.assertEqual(expected_res_status, firewall_res.status_int) return firewall_res @contextlib.contextmanager def firewall(self, fmt=None, name='firewall_1', description=DESCRIPTION, firewall_policy_id=None, admin_state_up=True, do_delete=True, **kwargs): if not fmt: fmt = self.fmt res = self._create_firewall(fmt, name, description, firewall_policy_id, admin_state_up, **kwargs) if res.status_int >= 400: raise webob.exc.HTTPClientError(code=res.status_int) firewall = self.deserialize(fmt or self.fmt, res) yield firewall if do_delete: self._delete('firewalls', firewall['firewall']['id']) def _rule_action(self, action, id, firewall_rule_id, insert_before=None, insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=None, body_data=None): # We intentionally do this check for None since we want to distinguish # from empty dictionary if body_data is None: if action == 'insert': body_data = {'firewall_rule_id': firewall_rule_id, 'insert_before': insert_before, 'insert_after': insert_after} else: body_data = {'firewall_rule_id': firewall_rule_id} req = self.new_action_request('firewall_policies', body_data, id, "%s_rule" % action) res = req.get_response(self.ext_api) self.assertEqual(expected_code, res.status_int) response = self.deserialize(self.fmt, res) if expected_body: self.assertEqual(expected_body, response) return response def _compare_firewall_rule_lists(self, firewall_policy_id, observed_list, expected_list): position = 0 for r1, r2 in zip(observed_list, expected_list): rule = r1['firewall_rule'] rule['firewall_policy_id'] = firewall_policy_id position += 1 rule['position'] = position for k in rule: self.assertEqual(r2[k], rule[k]) class TestFirewallDBPlugin(FirewallPluginDbTestCase): def test_create_firewall_policy(self): name = "firewall_policy1" attrs = self._get_test_firewall_policy_attrs(name) with self.firewall_policy(name=name, shared=SHARED, firewall_rules=None, audited=AUDITED) as firewall_policy: for k, v in six.iteritems(attrs): self.assertEqual(v, firewall_policy['firewall_policy'][k]) def test_create_firewall_policy_with_rules(self): name = "firewall_policy1" attrs = self._get_test_firewall_policy_attrs(name) with self.firewall_rule(name='fwr1') as fwr1, \ self.firewall_rule(name='fwr2') as fwr2, \ self.firewall_rule(name='fwr3') as fwr3: fr = [fwr1, fwr2, fwr3] fw_rule_ids = [r['firewall_rule']['id'] for r in fr] attrs['firewall_rules'] = fw_rule_ids with self.firewall_policy(name=name, shared=SHARED, firewall_rules=fw_rule_ids, audited=AUDITED) as fwp: for k, v in six.iteritems(attrs): self.assertEqual(v, fwp['firewall_policy'][k]) def test_create_admin_firewall_policy_with_other_tenant_rules(self): with self.firewall_rule(shared=False) as fr: fw_rule_ids = [fr['firewall_rule']['id']] res = self._create_firewall_policy(None, 'firewall_policy1', description=DESCRIPTION, shared=SHARED, firewall_rules=fw_rule_ids, audited=AUDITED, tenant_id='admin-tenant') self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) def test_create_firewall_policy_with_previously_associated_rule(self): with self.firewall_rule() as fwr: fw_rule_ids = [fwr['firewall_rule']['id']] with self.firewall_policy(firewall_rules=fw_rule_ids): res = self._create_firewall_policy( None, 'firewall_policy2', description=DESCRIPTION, shared=SHARED, firewall_rules=fw_rule_ids, audited=AUDITED) self.assertEqual(409, res.status_int) def test_create_shared_firewall_policy_with_unshared_rule(self): with self.firewall_rule(shared=False) as fwr: fw_rule_ids = [fwr['firewall_rule']['id']] res = self._create_firewall_policy( None, 'firewall_policy1', description=DESCRIPTION, shared=True, firewall_rules=fw_rule_ids, audited=AUDITED) self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) def test_show_firewall_policy(self): name = "firewall_policy1" attrs = self._get_test_firewall_policy_attrs(name) with self.firewall_policy(name=name, shared=SHARED, firewall_rules=None, audited=AUDITED) as fwp: req = self.new_show_request('firewall_policies', fwp['firewall_policy']['id'], fmt=self.fmt) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_policy'][k]) def test_list_firewall_policies(self): with self.firewall_policy(name='fwp1', description='fwp') as fwp1, \ self.firewall_policy(name='fwp2', description='fwp') as fwp2, \ self.firewall_policy(name='fwp3', description='fwp') as fwp3: fw_policies = [fwp1, fwp2, fwp3] self._test_list_resources('firewall_policy', fw_policies, query_params='description=fwp') def test_update_firewall_policy(self): name = "new_firewall_policy1" attrs = self._get_test_firewall_policy_attrs(name, audited=False) with self.firewall_policy(shared=SHARED, firewall_rules=None, audited=AUDITED) as fwp: data = {'firewall_policy': {'name': name}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_policy'][k]) def _test_update_firewall_policy(self, with_audited): with self.firewall_policy(name='firewall_policy1', description='fwp', audited=AUDITED) as fwp: attrs = self._get_test_firewall_policy_attrs(audited=with_audited) data = {'firewall_policy': {'description': 'fw_p1'}} if with_audited: data['firewall_policy']['audited'] = 'True' req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) attrs['description'] = 'fw_p1' for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_policy'][k]) def test_update_firewall_policy_set_audited_false(self): self._test_update_firewall_policy(with_audited=False) def test_update_firewall_policy_with_audited_set_true(self): self._test_update_firewall_policy(with_audited=True) def test_update_firewall_policy_with_rules(self): attrs = self._get_test_firewall_policy_attrs() with self.firewall_rule(name='fwr1') as fwr1, \ self.firewall_rule(name='fwr2') as fwr2, \ self.firewall_rule(name='fwr3') as fwr3: with self.firewall_policy() as fwp: fr = [fwr1, fwr2, fwr3] fw_rule_ids = [r['firewall_rule']['id'] for r in fr] attrs['firewall_rules'] = fw_rule_ids data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) attrs['audited'] = False for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_policy'][k]) def test_update_firewall_policy_replace_rules(self): attrs = self._get_test_firewall_policy_attrs() with self.firewall_rule(name='fwr1') as fwr1, \ self.firewall_rule(name='fwr2') as fwr2, \ self.firewall_rule(name='fwr3') as fwr3, \ self.firewall_rule(name='fwr4') as fwr4: frs = [fwr1, fwr2, fwr3, fwr4] fr1 = frs[0:2] fr2 = frs[2:4] with self.firewall_policy() as fwp: fw_rule_ids = [r['firewall_rule']['id'] for r in fr1] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) req.get_response(self.ext_api) fw_rule_ids = [r['firewall_rule']['id'] for r in fr2] attrs['firewall_rules'] = fw_rule_ids new_data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', new_data, fwp['firewall_policy']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) attrs['audited'] = False for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_policy'][k]) def test_update_firewall_policy_reorder_rules(self): attrs = self._get_test_firewall_policy_attrs() with self.firewall_rule(name='fwr1') as fwr1, \ self.firewall_rule(name='fwr2') as fwr2, \ self.firewall_rule(name='fwr3') as fwr3, \ self.firewall_rule(name='fwr4') as fwr4: fr = [fwr1, fwr2, fwr3, fwr4] with self.firewall_policy() as fwp: fw_rule_ids = [fr[2]['firewall_rule']['id'], fr[3]['firewall_rule']['id']] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) req.get_response(self.ext_api) # shuffle the rules, add more rules fw_rule_ids = [fr[1]['firewall_rule']['id'], fr[3]['firewall_rule']['id'], fr[2]['firewall_rule']['id'], fr[0]['firewall_rule']['id']] attrs['firewall_rules'] = fw_rule_ids data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) rules = [] for rule_id in fw_rule_ids: req = self.new_show_request('firewall_rules', rule_id, fmt=self.fmt) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) rules.append(res['firewall_rule']) self.assertEqual(1, rules[0]['position']) self.assertEqual(fr[1]['firewall_rule']['id'], rules[0]['id']) self.assertEqual(2, rules[1]['position']) self.assertEqual(fr[3]['firewall_rule']['id'], rules[1]['id']) self.assertEqual(3, rules[2]['position']) self.assertEqual(fr[2]['firewall_rule']['id'], rules[2]['id']) self.assertEqual(4, rules[3]['position']) self.assertEqual(fr[0]['firewall_rule']['id'], rules[3]['id']) def test_update_firewall_policy_with_non_existing_rule(self): attrs = self._get_test_firewall_policy_attrs() with self.firewall_rule(name='fwr1') as fwr1, \ self.firewall_rule(name='fwr2') as fwr2: fr = [fwr1, fwr2] with self.firewall_policy() as fwp: fw_rule_ids = [r['firewall_rule']['id'] for r in fr] # appending non-existent rule fw_rule_ids.append(uuidutils.generate_uuid()) data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) res = req.get_response(self.ext_api) # check that the firewall_rule was not found self.assertEqual(404, res.status_int) # check if none of the rules got added to the policy req = self.new_show_request('firewall_policies', fwp['firewall_policy']['id'], fmt=self.fmt) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_policy'][k]) def test_update_shared_firewall_policy_with_unshared_rule(self): with self.firewall_rule(name='fwr1', shared=False) as fr: with self.firewall_policy() as fwp: fw_rule_ids = [fr['firewall_rule']['id']] # update shared policy with unshared rule data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) res = req.get_response(self.ext_api) self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) def test_update_firewall_policy_with_shared_attr_unshared_rule(self): with self.firewall_rule(name='fwr1', shared=False) as fr: with self.firewall_policy(shared=False) as fwp: fw_rule_ids = [fr['firewall_rule']['id']] # update shared policy with shared attr and unshared rule data = {'firewall_policy': {'shared': True, 'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) res = req.get_response(self.ext_api) self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) def test_update_firewall_policy_with_shared_attr_exist_unshare_rule(self): with self.firewall_rule(name='fwr1', shared=False) as fr: fw_rule_ids = [fr['firewall_rule']['id']] with self.firewall_policy(shared=False, firewall_rules=fw_rule_ids) as fwp: # update policy with shared attr data = {'firewall_policy': {'shared': True}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) res = req.get_response(self.ext_api) self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) def test_update_firewall_policy_assoc_with_other_tenant_firewall(self): with self.firewall_policy(shared=True, tenant_id='tenant1') as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(firewall_policy_id=fwp_id): data = {'firewall_policy': {'shared': False}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) res = req.get_response(self.ext_api) self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) def test_delete_firewall_policy(self): ctx = context.get_admin_context() with self.firewall_policy(do_delete=False) as fwp: fwp_id = fwp['firewall_policy']['id'] req = self.new_delete_request('firewall_policies', fwp_id) res = req.get_response(self.ext_api) self.assertEqual(204, res.status_int) self.assertRaises(firewall.FirewallPolicyNotFound, self.plugin.get_firewall_policy, ctx, fwp_id) def test_delete_firewall_policy_with_rule(self): ctx = context.get_admin_context() attrs = self._get_test_firewall_policy_attrs() with self.firewall_policy(do_delete=False) as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall_rule(name='fwr1') as fr: fr_id = fr['firewall_rule']['id'] fw_rule_ids = [fr_id] attrs['firewall_rules'] = fw_rule_ids data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) req.get_response(self.ext_api) fw_rule = self.plugin.get_firewall_rule(ctx, fr_id) self.assertEqual(fwp_id, fw_rule['firewall_policy_id']) req = self.new_delete_request('firewall_policies', fwp_id) res = req.get_response(self.ext_api) self.assertEqual(204, res.status_int) self.assertRaises(firewall.FirewallPolicyNotFound, self.plugin.get_firewall_policy, ctx, fwp_id) fw_rule = self.plugin.get_firewall_rule(ctx, fr_id) self.assertIsNone(fw_rule['firewall_policy_id']) def test_delete_firewall_policy_with_firewall_association(self): attrs = self._get_test_firewall_attrs() with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall( firewall_policy_id=fwp_id, admin_state_up=ADMIN_STATE_UP): req = self.new_delete_request('firewall_policies', fwp_id) res = req.get_response(self.ext_api) self.assertEqual(409, res.status_int) def test_create_firewall_rule(self): attrs = self._get_test_firewall_rule_attrs() with self.firewall_rule() as firewall_rule: for k, v in six.iteritems(attrs): self.assertEqual(v, firewall_rule['firewall_rule'][k]) attrs['source_port'] = None attrs['destination_port'] = None with self.firewall_rule(source_port=None, destination_port=None) as firewall_rule: for k, v in six.iteritems(attrs): self.assertEqual(v, firewall_rule['firewall_rule'][k]) attrs['source_port'] = '10000' attrs['destination_port'] = '80' with self.firewall_rule(source_port=10000, destination_port=80) as firewall_rule: for k, v in six.iteritems(attrs): self.assertEqual(v, firewall_rule['firewall_rule'][k]) attrs['source_port'] = '10000' attrs['destination_port'] = '80' with self.firewall_rule(source_port='10000', destination_port='80') as firewall_rule: for k, v in six.iteritems(attrs): self.assertEqual(v, firewall_rule['firewall_rule'][k]) def test_create_firewall_src_port_illegal_range(self): attrs = self._get_test_firewall_rule_attrs() attrs['source_port'] = '65535:1024' res = self._create_firewall_rule(self.fmt, **attrs) self.assertEqual(400, res.status_int) def test_create_firewall_dest_port_illegal_range(self): attrs = self._get_test_firewall_rule_attrs() attrs['destination_port'] = '65535:1024' res = self._create_firewall_rule(self.fmt, **attrs) self.assertEqual(400, res.status_int) def test_create_firewall_rule_icmp_with_port(self): attrs = self._get_test_firewall_rule_attrs() attrs['protocol'] = 'icmp' res = self._create_firewall_rule(self.fmt, **attrs) self.assertEqual(400, res.status_int) def test_create_firewall_rule_icmp_without_port(self): attrs = self._get_test_firewall_rule_attrs() attrs['protocol'] = 'icmp' attrs['source_port'] = None attrs['destination_port'] = None with self.firewall_rule(source_port=None, destination_port=None, protocol='icmp') as firewall_rule: for k, v in six.iteritems(attrs): self.assertEqual(v, firewall_rule['firewall_rule'][k]) def test_create_firewall_without_source(self): attrs = self._get_test_firewall_rule_attrs() attrs['source_ip_address'] = None res = self._create_firewall_rule(self.fmt, **attrs) self.assertEqual(201, res.status_int) def test_create_firewall_rule_without_destination(self): attrs = self._get_test_firewall_rule_attrs() attrs['destination_ip_address'] = None res = self._create_firewall_rule(self.fmt, **attrs) self.assertEqual(201, res.status_int) def test_create_firewall_rule_without_protocol_with_dport(self): attrs = self._get_test_firewall_rule_attrs() attrs['protocol'] = None attrs['source_port'] = None res = self._create_firewall_rule(self.fmt, **attrs) self.assertEqual(400, res.status_int) def test_create_firewall_rule_without_protocol_with_sport(self): attrs = self._get_test_firewall_rule_attrs() attrs['protocol'] = None attrs['destination_port'] = None res = self._create_firewall_rule(self.fmt, **attrs) self.assertEqual(400, res.status_int) def test_show_firewall_rule_with_fw_policy_not_associated(self): attrs = self._get_test_firewall_rule_attrs() with self.firewall_rule() as fw_rule: req = self.new_show_request('firewall_rules', fw_rule['firewall_rule']['id'], fmt=self.fmt) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_rule'][k]) def test_show_firewall_rule_with_fw_policy_associated(self): attrs = self._get_test_firewall_rule_attrs() with self.firewall_rule() as fw_rule: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id data = {'firewall_policy': {'firewall_rules': [fw_rule['firewall_rule']['id']]}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) req.get_response(self.ext_api) req = self.new_show_request('firewall_rules', fw_rule['firewall_rule']['id'], fmt=self.fmt) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_rule'][k]) def test_create_firewall_rule_with_ipv6_addrs_and_wrong_ip_version(self): attrs = self._get_test_firewall_rule_attrs() attrs['source_ip_address'] = '::/0' attrs['destination_ip_address'] = '2001:db8:3::/64' attrs['ip_version'] = 4 res = self._create_firewall_rule(self.fmt, **attrs) self.assertEqual(400, res.status_int) attrs = self._get_test_firewall_rule_attrs() attrs['source_ip_address'] = None attrs['destination_ip_address'] = '2001:db8:3::/64' attrs['ip_version'] = 4 res = self._create_firewall_rule(self.fmt, **attrs) self.assertEqual(400, res.status_int) attrs = self._get_test_firewall_rule_attrs() attrs['source_ip_address'] = '::/0' attrs['destination_ip_address'] = None attrs['ip_version'] = 4 res = self._create_firewall_rule(self.fmt, **attrs) self.assertEqual(400, res.status_int) def test_list_firewall_rules(self): with self.firewall_rule(name='fwr1') as fwr1, \ self.firewall_rule(name='fwr2') as fwr2, \ self.firewall_rule(name='fwr3') as fwr3: fr = [fwr1, fwr2, fwr3] query_params = 'protocol=tcp' self._test_list_resources('firewall_rule', fr, query_params=query_params) def test_update_firewall_rule(self): name = "new_firewall_rule1" attrs = self._get_test_firewall_rule_attrs(name) attrs['source_port'] = '10:20' attrs['destination_port'] = '30:40' with self.firewall_rule() as fwr: data = {'firewall_rule': {'name': name, 'source_port': '10:20', 'destination_port': '30:40'}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_rule'][k]) attrs['source_port'] = '10000' attrs['destination_port'] = '80' with self.firewall_rule() as fwr: data = {'firewall_rule': {'name': name, 'source_port': 10000, 'destination_port': 80}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_rule'][k]) attrs['source_port'] = '10000' attrs['destination_port'] = '80' with self.firewall_rule() as fwr: data = {'firewall_rule': {'name': name, 'source_port': '10000', 'destination_port': '80'}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_rule'][k]) attrs['source_port'] = None attrs['destination_port'] = None with self.firewall_rule() as fwr: data = {'firewall_rule': {'name': name, 'source_port': None, 'destination_port': None}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_rule'][k]) def test_update_firewall_rule_with_port_and_no_proto(self): with self.firewall_rule() as fwr: data = {'firewall_rule': {'protocol': None, 'destination_port': 80}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = req.get_response(self.ext_api) self.assertEqual(400, res.status_int) def test_update_firewall_rule_without_ports_and_no_proto(self): with self.firewall_rule() as fwr: data = {'firewall_rule': {'protocol': None, 'destination_port': None, 'source_port': None}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = req.get_response(self.ext_api) self.assertEqual(200, res.status_int) def test_update_firewall_rule_with_port(self): with self.firewall_rule(source_port=None, destination_port=None, protocol=None) as fwr: data = {'firewall_rule': {'destination_port': 80}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = req.get_response(self.ext_api) self.assertEqual(400, res.status_int) def test_update_firewall_rule_with_port_illegal_range(self): with self.firewall_rule() as fwr: data = {'firewall_rule': {'destination_port': '65535:1024'}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = req.get_response(self.ext_api) self.assertEqual(400, res.status_int) def test_update_firewall_rule_with_port_and_protocol(self): with self.firewall_rule(source_port=None, destination_port=None, protocol=None) as fwr: data = {'firewall_rule': {'destination_port': 80, 'protocol': 'tcp'}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = req.get_response(self.ext_api) self.assertEqual(200, res.status_int) def test_update_firewall_rule_with_policy_associated(self): name = "new_firewall_rule1" attrs = self._get_test_firewall_rule_attrs(name) with self.firewall_rule() as fwr: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id fwr_id = fwr['firewall_rule']['id'] data = {'firewall_policy': {'firewall_rules': [fwr_id]}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) req.get_response(self.ext_api) data = {'firewall_rule': {'name': name}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) attrs['firewall_policy_id'] = fwp_id for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall_rule'][k]) req = self.new_show_request('firewall_policies', fwp['firewall_policy']['id'], fmt=self.fmt) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) self.assertEqual( [fwr_id], res['firewall_policy']['firewall_rules']) self.assertFalse(res['firewall_policy']['audited']) def test_update_firewall_rule_associated_with_other_tenant_policy(self): with self.firewall_rule(shared=True, tenant_id='tenant1') as fwr: fwr_id = [fwr['firewall_rule']['id']] with self.firewall_policy(shared=False, firewall_rules=fwr_id): data = {'firewall_rule': {'shared': False}} req = self.new_update_request('firewall_rules', data, fwr['firewall_rule']['id']) res = req.get_response(self.ext_api) self.assertEqual(webob.exc.HTTPConflict.code, res.status_int) def test_delete_firewall_rule(self): ctx = context.get_admin_context() with self.firewall_rule(do_delete=False) as fwr: fwr_id = fwr['firewall_rule']['id'] req = self.new_delete_request('firewall_rules', fwr_id) res = req.get_response(self.ext_api) self.assertEqual(204, res.status_int) self.assertRaises(firewall.FirewallRuleNotFound, self.plugin.get_firewall_rule, ctx, fwr_id) def test_delete_firewall_rule_with_policy_associated(self): attrs = self._get_test_firewall_rule_attrs() with self.firewall_rule() as fwr: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id fwr_id = fwr['firewall_rule']['id'] data = {'firewall_policy': {'firewall_rules': [fwr_id]}} req = self.new_update_request('firewall_policies', data, fwp['firewall_policy']['id']) req.get_response(self.ext_api) req = self.new_delete_request('firewall_rules', fwr_id) res = req.get_response(self.ext_api) self.assertEqual(409, res.status_int) def _test_create_firewall(self, attrs): with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall( name=attrs['name'], firewall_policy_id=fwp_id, admin_state_up=ADMIN_STATE_UP ) as firewall: for k, v in six.iteritems(attrs): self.assertEqual(v, firewall['firewall'][k]) def test_create_firewall(self): attrs = self._get_test_firewall_attrs("firewall1") self._test_create_firewall(attrs) def test_create_firewall_with_dvr(self): cfg.CONF.set_override('router_distributed', True) attrs = self._get_test_firewall_attrs("firewall1", "CREATED") self._test_create_firewall(attrs) def test_create_firewall_with_fwp_does_not_exist(self): fmt = self.fmt fw_name = "firewall1" description = "my_firewall1" not_found_fwp_id = uuidutils.generate_uuid() self._create_firewall(fmt, fw_name, description, not_found_fwp_id, ADMIN_STATE_UP, expected_res_status=404) def test_create_firewall_with_fwp_not_found_on_different_tenant(self): fmt = self.fmt fw_name = "firewall1" description = "my_firewall1" with self.firewall_policy(shared=False, tenant_id='tenant2') as fwp: fwp_id = fwp['firewall_policy']['id'] ctx = context.Context('not_admin', 'tenant1') self._create_firewall(fmt, fw_name, description, fwp_id, context=ctx, expected_res_status=404) def test_create_firewall_with_admin_and_fwp_different_tenant(self): fmt = self.fmt fw_name = "firewall1" description = "my_firewall1" with self.firewall_policy(shared=False, tenant_id='tenant2') as fwp: fwp_id = fwp['firewall_policy']['id'] ctx = context.get_admin_context() self._create_firewall(fmt, fw_name, description, fwp_id, tenant_id="admin-tenant", context=ctx, expected_res_status=409) def test_create_firewall_with_admin_and_fwp_is_shared(self): fw_name = "fw_with_shared_fwp" with self.firewall_policy(tenant_id="tenantX") as fwp: fwp_id = fwp['firewall_policy']['id'] ctx = context.get_admin_context() target_tenant = 'tenant1' with self.firewall(name=fw_name, firewall_policy_id=fwp_id, tenant_id=target_tenant, context=ctx, admin_state_up=ADMIN_STATE_UP) as fw: self.assertEqual(target_tenant, fw['firewall']['tenant_id']) def test_show_firewall(self): name = "firewall1" attrs = self._get_test_firewall_attrs(name) with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall( name=name, firewall_policy_id=fwp_id, admin_state_up=ADMIN_STATE_UP) as firewall: req = self.new_show_request('firewalls', firewall['firewall']['id'], fmt=self.fmt) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall'][k]) def test_list_firewalls(self): with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(name='fw1', tenant_id='tenant1', firewall_policy_id=fwp_id, description='fw') as fw1, \ self.firewall(name='fw2', tenant_id='tenant2', firewall_policy_id=fwp_id, description='fw') as fw2, \ self.firewall(name='fw3', tenant_id='tenant3', firewall_policy_id=fwp_id, description='fw') as fw3: fwalls = [fw1, fw2, fw3] self._test_list_resources('firewall', fwalls, query_params='description=fw') def test_update_firewall(self): name = "new_firewall1" attrs = self._get_test_firewall_attrs(name) with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['firewall_policy_id'] = fwp_id with self.firewall( firewall_policy_id=fwp_id, admin_state_up=ADMIN_STATE_UP) as firewall: data = {'firewall': {'name': name}} req = self.new_update_request('firewalls', data, firewall['firewall']['id']) res = self.deserialize(self.fmt, req.get_response(self.ext_api)) for k, v in six.iteritems(attrs): self.assertEqual(v, res['firewall'][k]) def test_update_firewall_with_fwp(self): ctx = context.Context('not_admin', 'tenant1') with self.firewall_policy() as fwp1, \ self.firewall_policy( tenant_id='tenant1', shared=False) as fwp2, \ self.firewall(firewall_policy_id=fwp1['firewall_policy']['id'], context=ctx) as fw: fw_id = fw['firewall']['id'] fwp2_id = fwp2['firewall_policy']['id'] data = {'firewall': {'firewall_policy_id': fwp2_id}} req = self.new_update_request('firewalls', data, fw_id, context=ctx) res = req.get_response(self.ext_api) self.assertEqual(200, res.status_int) def test_update_firewall_with_shared_fwp(self): ctx = context.Context('not_admin', 'tenant1') with self.firewall_policy() as fwp1, \ self.firewall_policy(tenant_id='tenant2') as fwp2, \ self.firewall(firewall_policy_id=fwp1['firewall_policy']['id'], context=ctx) as fw: fw_id = fw['firewall']['id'] fwp2_id = fwp2['firewall_policy']['id'] data = {'firewall': {'firewall_policy_id': fwp2_id}} req = self.new_update_request('firewalls', data, fw_id, context=ctx) res = req.get_response(self.ext_api) self.assertEqual(200, res.status_int) def test_update_firewall_with_admin_and_fwp_different_tenant(self): ctx = context.get_admin_context() with self.firewall_policy() as fwp1, \ self.firewall_policy( tenant_id='tenant2', shared=False) as fwp2, \ self.firewall(firewall_policy_id=fwp1['firewall_policy']['id'], context=ctx) as fw: fw_id = fw['firewall']['id'] fwp2_id = fwp2['firewall_policy']['id'] data = {'firewall': {'firewall_policy_id': fwp2_id}} req = self.new_update_request('firewalls', data, fw_id, context=ctx) res = req.get_response(self.ext_api) self.assertEqual(409, res.status_int) def test_update_firewall_fwp_not_found_on_different_tenant(self): with self.firewall_policy(name='fwp1', tenant_id='tenant1', do_delete=False) as fwp1, \ self.firewall_policy(name='fwp2', shared=False, tenant_id='tenant2') as fwp2: fwps = [fwp1, fwp2] # create firewall using fwp1 exists the same tenant. fwp1_id = fwps[0]['firewall_policy']['id'] fwp2_id = fwps[1]['firewall_policy']['id'] ctx = context.Context('not_admin', 'tenant1') with self.firewall(firewall_policy_id=fwp1_id, context=ctx) as firewall: fw_id = firewall['firewall']['id'] fw_db = self.plugin._get_firewall(ctx, fw_id) fw_db['status'] = constants.ACTIVE # update firewall from fwp1 to fwp2(different tenant) data = {'firewall': {'firewall_policy_id': fwp2_id}} req = self.new_update_request('firewalls', data, fw_id, context=ctx) res = req.get_response(self.ext_api) self.assertEqual(404, res.status_int) def test_delete_firewall(self): ctx = context.get_admin_context() with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] with self.firewall(firewall_policy_id=fwp_id, do_delete=False) as fw: fw_id = fw['firewall']['id'] req = self.new_delete_request('firewalls', fw_id) res = req.get_response(self.ext_api) self.assertEqual(204, res.status_int) self.assertRaises(firewall.FirewallNotFound, self.plugin.get_firewall, ctx, fw_id) def test_insert_rule_in_policy_with_prior_rules_added_via_update(self): attrs = self._get_test_firewall_policy_attrs() attrs['audited'] = False attrs['firewall_list'] = [] with self.firewall_rule(name='fwr1') as fwr1, \ self.firewall_rule(name='fwr2') as fwr2, \ self.firewall_rule(name='fwr3') as fwr3: frs = [fwr1, fwr2, fwr3] fr1 = frs[0:2] fwr3 = frs[2] with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['id'] = fwp_id fw_rule_ids = [r['firewall_rule']['id'] for r in fr1] attrs['firewall_rules'] = fw_rule_ids[:] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp_id) req.get_response(self.ext_api) self._rule_action('insert', fwp_id, fw_rule_ids[0], insert_before=fw_rule_ids[0], insert_after=None, expected_code=webob.exc.HTTPConflict.code, expected_body=None) fwr3_id = fwr3['firewall_rule']['id'] attrs['firewall_rules'].insert(0, fwr3_id) self._rule_action('insert', fwp_id, fwr3_id, insert_before=fw_rule_ids[0], insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) def test_insert_rule_in_policy_failures(self): with self.firewall_rule(name='fwr1') as fr1: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] fr1_id = fr1['firewall_rule']['id'] fw_rule_ids = [fr1_id] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp_id) req.get_response(self.ext_api) # test inserting with empty request body self._rule_action('insert', fwp_id, '123', expected_code=webob.exc.HTTPBadRequest.code, expected_body=None, body_data={}) # test inserting when firewall_rule_id is missing in # request body insert_data = {'insert_before': '123', 'insert_after': '456'} self._rule_action('insert', fwp_id, '123', expected_code=webob.exc.HTTPBadRequest.code, expected_body=None, body_data=insert_data) # test inserting when firewall_rule_id is None insert_data = {'firewall_rule_id': None, 'insert_before': '123', 'insert_after': '456'} self._rule_action('insert', fwp_id, '123', expected_code=webob.exc.HTTPNotFound.code, expected_body=None, body_data=insert_data) # test inserting when firewall_policy_id is incorrect self._rule_action('insert', '123', fr1_id, expected_code=webob.exc.HTTPNotFound.code, expected_body=None) # test inserting when firewall_policy_id is None self._rule_action('insert', None, fr1_id, expected_code=webob.exc.HTTPBadRequest.code, expected_body=None) def test_insert_rule_for_previously_associated_rule(self): with self.firewall_rule() as fwr: fwr_id = fwr['firewall_rule']['id'] fw_rule_ids = [fwr_id] with self.firewall_policy(firewall_rules=fw_rule_ids): with self.firewall_policy(name='firewall_policy2') as fwp: fwp_id = fwp['firewall_policy']['id'] insert_data = {'firewall_rule_id': fwr_id} self._rule_action( 'insert', fwp_id, fwr_id, insert_before=None, insert_after=None, expected_code=webob.exc.HTTPConflict.code, expected_body=None, body_data=insert_data) def test_insert_rule_for_prev_associated_ref_rule(self): with self.firewall_rule(name='fwr0') as fwr0, \ self.firewall_rule(name='fwr1') as fwr1: fwr = [fwr0, fwr1] fwr0_id = fwr[0]['firewall_rule']['id'] fwr1_id = fwr[1]['firewall_rule']['id'] with self.firewall_policy(name='fwp0') as fwp0, \ self.firewall_policy(name='fwp1', firewall_rules=[fwr1_id]) as fwp1: fwp = [fwp0, fwp1] fwp0_id = fwp[0]['firewall_policy']['id'] # test inserting before a rule which # is associated with different policy self._rule_action('insert', fwp0_id, fwr0_id, insert_before=fwr1_id, expected_code=webob.exc.HTTPBadRequest.code, expected_body=None) # test inserting after a rule which # is associated with different policy self._rule_action('insert', fwp0_id, fwr0_id, insert_after=fwr1_id, expected_code=webob.exc.HTTPBadRequest.code, expected_body=None) def test_insert_rule_for_policy_of_other_tenant(self): with self.firewall_rule(tenant_id='tenant-2', shared=False) as fwr: fwr_id = fwr['firewall_rule']['id'] with self.firewall_policy(name='firewall_policy') as fwp: fwp_id = fwp['firewall_policy']['id'] insert_data = {'firewall_rule_id': fwr_id} self._rule_action( 'insert', fwp_id, fwr_id, insert_before=None, insert_after=None, expected_code=webob.exc.HTTPConflict.code, expected_body=None, body_data=insert_data) def test_insert_rule_in_policy(self): attrs = self._get_test_firewall_policy_attrs() attrs['audited'] = False attrs['firewall_list'] = [] with self.firewall_rule(name='fwr0') as fwr0, \ self.firewall_rule(name='fwr1') as fwr1, \ self.firewall_rule(name='fwr2') as fwr2, \ self.firewall_rule(name='fwr3') as fwr3, \ self.firewall_rule(name='fwr4') as fwr4, \ self.firewall_rule(name='fwr5') as fwr5, \ self.firewall_rule(name='fwr6') as fwr6: fwr = [fwr0, fwr1, fwr2, fwr3, fwr4, fwr5, fwr6] with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['id'] = fwp_id # test insert when rule list is empty fwr0_id = fwr[0]['firewall_rule']['id'] attrs['firewall_rules'].insert(0, fwr0_id) self._rule_action('insert', fwp_id, fwr0_id, insert_before=None, insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert at top of rule list, insert_before and # insert_after not provided fwr1_id = fwr[1]['firewall_rule']['id'] attrs['firewall_rules'].insert(0, fwr1_id) insert_data = {'firewall_rule_id': fwr1_id} self._rule_action('insert', fwp_id, fwr0_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs, body_data=insert_data) # test insert at top of list above existing rule fwr2_id = fwr[2]['firewall_rule']['id'] attrs['firewall_rules'].insert(0, fwr2_id) self._rule_action('insert', fwp_id, fwr2_id, insert_before=fwr1_id, insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert at bottom of list fwr3_id = fwr[3]['firewall_rule']['id'] attrs['firewall_rules'].append(fwr3_id) self._rule_action('insert', fwp_id, fwr3_id, insert_before=None, insert_after=fwr0_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert in the middle of the list using # insert_before fwr4_id = fwr[4]['firewall_rule']['id'] attrs['firewall_rules'].insert(1, fwr4_id) self._rule_action('insert', fwp_id, fwr4_id, insert_before=fwr1_id, insert_after=None, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert in the middle of the list using # insert_after fwr5_id = fwr[5]['firewall_rule']['id'] attrs['firewall_rules'].insert(1, fwr5_id) self._rule_action('insert', fwp_id, fwr5_id, insert_before=None, insert_after=fwr2_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) # test insert when both insert_before and # insert_after are set fwr6_id = fwr[6]['firewall_rule']['id'] attrs['firewall_rules'].insert(1, fwr6_id) self._rule_action('insert', fwp_id, fwr6_id, insert_before=fwr5_id, insert_after=fwr5_id, expected_code=webob.exc.HTTPOk.code, expected_body=attrs) def test_remove_rule_from_policy(self): attrs = self._get_test_firewall_policy_attrs() attrs['audited'] = False attrs['firewall_list'] = [] with self.firewall_rule(name='fwr1') as fwr1, \ self.firewall_rule(name='fwr2') as fwr2, \ self.firewall_rule(name='fwr3') as fwr3: fr1 = [fwr1, fwr2, fwr3] with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] attrs['id'] = fwp_id fw_rule_ids = [r['firewall_rule']['id'] for r in fr1] attrs['firewall_rules'] = fw_rule_ids[:] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp_id) req.get_response(self.ext_api) # test removing a rule from a policy that does not exist self._rule_action('remove', '123', fw_rule_ids[1], expected_code=webob.exc.HTTPNotFound.code, expected_body=None) # test removing a rule in the middle of the list attrs['firewall_rules'].remove(fw_rule_ids[1]) self._rule_action('remove', fwp_id, fw_rule_ids[1], expected_body=attrs) # test removing a rule at the top of the list attrs['firewall_rules'].remove(fw_rule_ids[0]) self._rule_action('remove', fwp_id, fw_rule_ids[0], expected_body=attrs) # test removing remaining rule in the list attrs['firewall_rules'].remove(fw_rule_ids[2]) self._rule_action('remove', fwp_id, fw_rule_ids[2], expected_body=attrs) # test removing rule that is not associated with the policy self._rule_action('remove', fwp_id, fw_rule_ids[2], expected_code=webob.exc.HTTPBadRequest.code, expected_body=None) def test_remove_rule_from_policy_failures(self): with self.firewall_rule(name='fwr1') as fr1: with self.firewall_policy() as fwp: fwp_id = fwp['firewall_policy']['id'] fw_rule_ids = [fr1['firewall_rule']['id']] data = {'firewall_policy': {'firewall_rules': fw_rule_ids}} req = self.new_update_request('firewall_policies', data, fwp_id) req.get_response(self.ext_api) # test removing rule that does not exist self._rule_action('remove', fwp_id, '123', expected_code=webob.exc.HTTPNotFound.code, expected_body=None) # test removing rule with bad request self._rule_action('remove', fwp_id, '123', expected_code=webob.exc.HTTPBadRequest.code, expected_body=None, body_data={}) # test removing rule with firewall_rule_id set to None self._rule_action('remove', fwp_id, '123', expected_code=webob.exc.HTTPNotFound.code, expected_body=None, body_data={'firewall_rule_id': None}) def test_check_router_has_no_firewall_raises(self): with mock.patch.object( manager.NeutronManager, 'get_service_plugins') as sp: fw_plugin = mock.Mock() sp.return_value = {'FIREWALL': fw_plugin} fw_plugin.get_firewalls.return_value = [mock.ANY] kwargs = { 'context': mock.ANY, 'router': {'id': 'foo_id', 'tenant_id': 'foo_tenant'} } self.assertRaises( l3.RouterInUse, fdb.migration_callback, 'router', 'before_event', mock.ANY, **kwargs) def test_check_router_has_no_firewall_passes(self): with mock.patch.object(manager.NeutronManager, 'get_service_plugins', return_value={}): kwargs = {'context': mock.ANY, 'router': mock.ANY} self.assertIsNone(fdb.migration_callback( mock.ANY, mock.ANY, mock.ANY, **kwargs)) def test_show_firewall_rule_by_name(self): with self.firewall_rule(name='firewall_Rule1') as fw_rule: res = self._show('firewall_rules', fw_rule['firewall_rule']['id']) self.assertEqual('firewall_Rule1', res['firewall_rule']['name']) def test_show_firewall_policy_by_name(self): with self.firewall_policy( name='firewall_Policy1') as fw_policy: res = self._show('firewall_policies', fw_policy['firewall_policy']['id']) self.assertEqual( 'firewall_Policy1', res['firewall_policy']['name']) def test_show_firewall_by_name(self): with self.firewall(name='fireWall1') as fw: res = self._show('firewalls', fw['firewall']['id']) self.assertEqual('fireWall1', res['firewall']['name']) neutron-fwaas-8.0.0/neutron_fwaas/tests/unit/db/__init__.py0000664000567000056710000000000012701407720025131 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/functional/0000775000567000056710000000000012701410073023623 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/functional/__init__.py0000664000567000056710000000000012701407720025727 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/tests/functional/test_fwaas_driver.py0000664000567000056710000000212512701407720027715 0ustar jenkinsjenkins00000000000000# Copyright (c) 2015 Cisco Systems, 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. # NOTE: The purpose of this module is to provide a nop test to verify that # the functional gate is working. from neutron.tests.functional import base class TestFWaaSDriver(base.BaseSudoTestCase): """Test the iptables implementation of the FWaaS driver.""" # NOTE: Tests may be added/removed/changed, when this is fleshed out # in future commits. def test_status_reporting(self): """Test status reported correctly to agent.""" pass neutron-fwaas-8.0.0/neutron_fwaas/opts.py0000664000567000056710000000156112701407720021666 0ustar jenkinsjenkins00000000000000# 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 neutron_fwaas.services.firewall.agents.firewall_agent_api def list_agent_opts(): return [ ('fwaas', neutron_fwaas.services.firewall.agents.firewall_agent_api.FWaaSOpts) ] def list_opts(): return [ ('quotas', neutron_fwaas.extensions.firewall.firewall_quota_opts) ] neutron-fwaas-8.0.0/neutron_fwaas/__init__.py0000664000567000056710000000136312701407720022440 0ustar jenkinsjenkins00000000000000# Copyright 2011 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. import gettext import six if six.PY2: gettext.install('neutron', unicode=1) else: gettext.install('neutron') neutron-fwaas-8.0.0/neutron_fwaas/services/0000775000567000056710000000000012701410073022142 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/0000775000567000056710000000000012701410073023747 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/__init__.py0000664000567000056710000000000012701407720026053 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/plugins/0000775000567000056710000000000012701410073025430 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/plugins/cisco/0000775000567000056710000000000012701410073026530 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/plugins/cisco/__init__.py0000664000567000056710000000000012701407720030634 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/plugins/cisco/cisco_fwaas_plugin.py0000664000567000056710000003727012701407720032757 0ustar jenkinsjenkins00000000000000# Copyright 2015 Cisco Systems, 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. # from neutron.api.v2 import attributes as attr from neutron.common import rpc as n_rpc from neutron import context as neutron_context from neutron import manager from neutron.plugins.common import constants as const from neutron_lib import constants as l3_const from oslo_config import cfg from oslo_log import helpers as log_helpers from oslo_log import log as logging import oslo_messaging from neutron_fwaas._i18n import _LW from neutron_fwaas.db.cisco import cisco_fwaas_db as csrfw_db import neutron_fwaas.extensions from neutron_fwaas.extensions.cisco import csr_firewall_insertion as csr_ext from neutron_fwaas.services.firewall import fwaas_plugin as ref_fw_plugin LOG = logging.getLogger(__name__) class FirewallCallbacks(object): target = oslo_messaging.Target(version='1.0') def __init__(self, plugin): super(FirewallCallbacks, self).__init__() self.plugin = plugin @log_helpers.log_method_call def set_firewall_status(self, context, firewall_id, status, status_data=None, **kwargs): """Agent uses this to set a firewall's status.""" with context.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(context, firewall_id) # ignore changing status if firewall expects to be deleted # That case means that while some pending operation has been # performed on the backend, neutron server received delete request # and changed firewall status to const.PENDING_DELETE if status == const.ERROR: fw_db.status = const.ERROR return False if fw_db.status == const.PENDING_DELETE: LOG.debug("Firewall %(fw_id)s in PENDING_DELETE state, " "not changing to %(status)s", {'fw_id': firewall_id, 'status': status}) return False if status in (const.ACTIVE, const.INACTIVE): fw_db.status = status csrfw = self.plugin.lookup_firewall_csr_association(context, firewall_id) _fw = {'id': csrfw['fw_id'], 'port_id': csrfw['port_id'], 'direction': csrfw['direction'], 'acl_id': status_data['acl_id']} self.plugin.update_firewall_csr_association(context, firewall_id, _fw) else: fw_db.status = const.ERROR @log_helpers.log_method_call def firewall_deleted(self, context, firewall_id, **kwargs): """Agent uses this to indicate firewall is deleted.""" with context.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(context, firewall_id) # allow to delete firewalls in ERROR state if fw_db.status in (const.PENDING_DELETE, const.ERROR): self.plugin.delete_db_firewall_object(context, firewall_id) return True LOG.warning(_LW('Firewall %(fw)s unexpectedly deleted by agent, ' 'status was %(status)s'), {'fw': firewall_id, 'status': fw_db.status}) fw_db.status = const.ERROR return False @log_helpers.log_method_call def get_firewalls_for_tenant(self, context, **kwargs): """Agent uses this to get all firewalls and rules for a tenant.""" fw_list = [] for fw in self.plugin.get_firewalls(context): fw_with_rules = ( self.plugin._make_firewall_dict_with_rules(context, fw['id'])) csrfw = self.plugin.lookup_firewall_csr_association(context, fw['id']) router_id = csrfw['router_id'] fw_with_rules['vendor_ext'] = self.plugin._get_hosting_info( context, csrfw['port_id'], router_id, csrfw['direction']) fw_with_rules['vendor_ext']['acl_id'] = csrfw['acl_id'] fw_list.append(fw_with_rules) return fw_list @log_helpers.log_method_call def get_firewalls_for_tenant_without_rules(self, context, **kwargs): """Agent uses this to get all firewalls for a tenant.""" return [fw for fw in self.plugin.get_firewalls(context)] @log_helpers.log_method_call def get_tenants_with_firewalls(self, context, **kwargs): """Agent uses this to get all tenants that have firewalls.""" ctx = neutron_context.get_admin_context() fw_list = self.plugin.get_firewalls(ctx) return list(set(fw['tenant_id'] for fw in fw_list)) class FirewallAgentApi(object): """Plugin side of plugin to agent RPC API.""" def __init__(self, topic, host): self.host = host target = oslo_messaging.Target(topic=topic, version='1.0') self.client = n_rpc.get_client(target) def create_firewall(self, context, firewall): cctxt = self.client.prepare(fanout=True) cctxt.cast(context, 'create_firewall', firewall=firewall, host=self.host) def update_firewall(self, context, firewall): cctxt = self.client.prepare(fanout=True) cctxt.cast(context, 'update_firewall', firewall=firewall, host=self.host) def delete_firewall(self, context, firewall): cctxt = self.client.prepare(fanout=True) cctxt.cast(context, 'delete_firewall', firewall=firewall, host=self.host) class CSRFirewallPlugin(ref_fw_plugin.FirewallPlugin, csrfw_db.CiscoFirewall_db_mixin): """Implementation of the Neutron Firewall Service Plugin. This class implements the Cisco CSR FWaaS Service Plugin, inherits from the fwaas ref plugin as no changes are made to handling fwaas policy and rules. The CRUD methods are overridden to provide for the specific implementation. The basic fwaas db is managed thru the firewall_db.Firewall_db_mixin. The backend specific associations are captured in the new table, csrfw_db.CiscoFirewall_db_mixin. """ supported_extension_aliases = ["fwaas", "csrfirewallinsertion"] def __init__(self): """Do the initialization for the firewall service plugin here.""" ext_path = neutron_fwaas.extensions.__path__[0] + '/cisco' if ext_path not in cfg.CONF.api_extensions_path.split(':'): cfg.CONF.set_override('api_extensions_path', cfg.CONF.api_extensions_path + ':' + ext_path) self.endpoints = [FirewallCallbacks(self)] self.conn = n_rpc.create_connection() self.conn.create_consumer( 'CISCO_FW_PLUGIN', self.endpoints, fanout=False) self.conn.consume_in_threads() self.agent_rpc = FirewallAgentApi( 'CISCO_FW', cfg.CONF.host ) def _rpc_update_firewall(self, context, firewall_id): status_update = {"firewall": {"status": const.PENDING_UPDATE}} fw = super(ref_fw_plugin.FirewallPlugin, self).update_firewall( context, firewall_id, status_update) if fw: fw_with_rules = ( self._make_firewall_dict_with_rules(context, firewall_id)) csrfw = self.lookup_firewall_csr_association(context, firewall_id) fw_with_rules['vendor_ext'] = self._get_hosting_info(context, csrfw['port_id'], csrfw['router_id'], csrfw['direction']) fw_with_rules['vendor_ext']['acl_id'] = csrfw['acl_id'] LOG.debug("Update of Rule or policy: fw_with_rules: %s", fw_with_rules) self.agent_rpc.update_firewall(context, fw_with_rules) @log_helpers.log_method_call def _validate_fw_port_and_get_router_id(self, context, tenant_id, port_id): # port validation with router plugin l3_plugin = manager.NeutronManager.get_service_plugins().get( const.L3_ROUTER_NAT) ctx = neutron_context.get_admin_context() routers = l3_plugin.get_routers(ctx) router_ids = [ router['id'] for router in routers if router['tenant_id'] == tenant_id] port_db = self._core_plugin._get_port(context, port_id) if not (port_db['device_id'] in router_ids and port_db['device_owner'] == l3_const.DEVICE_OWNER_ROUTER_INTF): raise csr_ext.InvalidInterfaceForCSRFW(port_id=port_id) return port_db['device_id'] def _map_csr_device_info_for_agent(self, hosting_device): return {'host_mngt_ip': hosting_device['management_ip_address'], 'host_usr_nm': hosting_device['credentials']['username'], 'host_usr_pw': hosting_device['credentials']['password']} def _get_service_insertion_points(self, context, interfaces, port_id, direction): insertion_point = dict() hosting_info = dict() for interface in interfaces: if interface['id'] == port_id: hosting_info = interface['hosting_info'] if not hosting_info: raise csr_ext.InvalidRouterHostingInfoForCSRFW(port_id=port_id) insertion_point['port'] = {'id': port_id, 'hosting_info': hosting_info} insertion_point['direction'] = direction return [insertion_point] def _get_hosting_info(self, context, port_id, router_id, direction): l3_plugin = manager.NeutronManager.get_service_plugins().get( const.L3_ROUTER_NAT) ctx = neutron_context.get_admin_context() routers = l3_plugin.get_sync_data_ext(ctx) for router in routers: if router['id'] == router_id: vendor_ext = self._map_csr_device_info_for_agent( router['hosting_device']) vendor_ext['if_list'] = self._get_service_insertion_points( context, router['_interfaces'], port_id, direction) return vendor_ext # TODO(sridar): we may need to raise an excp - check backlogging @log_helpers.log_method_call def create_firewall(self, context, firewall): port_id = firewall['firewall'].pop('port_id', None) direction = firewall['firewall'].pop('direction', None) if port_id == attr.ATTR_NOT_SPECIFIED: LOG.debug("create_firewall() called") port_id = None router_id = None else: # TODO(sridar): add check to see if the new port-id does not have # any associated firewall. router_id = self._validate_fw_port_and_get_router_id(context, firewall['firewall']['tenant_id'], port_id) if direction == attr.ATTR_NOT_SPECIFIED: direction = None firewall['firewall']['status'] = const.PENDING_CREATE fw = super(ref_fw_plugin.FirewallPlugin, self).create_firewall( context, firewall) fw_with_rules = ( self._make_firewall_dict_with_rules(context, fw['id'])) if not port_id and not direction: return fw # Add entry into firewall associations table _fw = {'id': fw['id'], 'port_id': port_id, 'direction': direction, 'router_id': router_id, 'acl_id': None} self.add_firewall_csr_association(context, _fw) if port_id and direction: fw_with_rules['vendor_ext'] = self._get_hosting_info(context, port_id, router_id, direction) fw_with_rules['vendor_ext']['acl_id'] = None self.agent_rpc.create_firewall(context, fw_with_rules) return fw @log_helpers.log_method_call def update_firewall(self, context, fwid, firewall): self._ensure_update_firewall(context, fwid) csrfw = self.lookup_firewall_csr_association(context, fwid) port_id = firewall['firewall'].pop('port_id', None) direction = firewall['firewall'].pop('direction', None) _fw = {'id': fwid} if port_id: tenant_id = self.get_firewall(context, fwid)['tenant_id'] router_id = self._validate_fw_port_and_get_router_id(context, tenant_id, port_id) if csrfw and csrfw['port_id']: # TODO(sridar): add check to see if the new port_id does not # have any associated firewall. # we only support a different port if associated # with the same router if router_id != csrfw['router_id']: raise csr_ext.InvalidRouterAssociationForCSRFW( port_id=port_id) _fw['port_id'] = port_id _fw['router_id'] = router_id else: _fw['port_id'] = csrfw['port_id'] if csrfw else None _fw['router_id'] = csrfw['router_id'] if csrfw else None if direction: _fw['direction'] = direction else: _fw['direction'] = csrfw['direction'] if csrfw else None _fw['acl_id'] = csrfw['acl_id'] if csrfw else None self.update_firewall_csr_association(context, fwid, _fw) firewall['firewall']['status'] = const.PENDING_UPDATE fw = super(ref_fw_plugin.FirewallPlugin, self).update_firewall( context, fwid, firewall) fw_with_rules = ( self._make_firewall_dict_with_rules(context, fw['id'])) if _fw['port_id'] and _fw['direction']: fw_with_rules['vendor_ext'] = self._get_hosting_info(context, port_id, csrfw['router_id'], direction) fw_with_rules['vendor_ext']['acl_id'] = csrfw['acl_id'] LOG.debug("CSR Plugin update: fw_with_rules: %s", fw_with_rules) self.agent_rpc.update_firewall(context, fw_with_rules) return fw @log_helpers.log_method_call def delete_firewall(self, context, fwid): self._ensure_update_firewall(context, fwid) status_update = {"firewall": {"status": const.PENDING_DELETE}} fw = super(ref_fw_plugin.FirewallPlugin, self).update_firewall( context, fwid, status_update) # given that we are not in a PENDING_CREATE we should have # an acl_id - since it is not present something bad has happened # on the backend and no sense in sending a msg to the agent. # Clean up ... csrfw = self.lookup_firewall_csr_association(context, fwid) if not csrfw or not csrfw['acl_id']: self.delete_db_firewall_object(context, fwid) return fw_with_rules = ( self._make_firewall_dict_with_rules(context, fw['id'])) fw_with_rules['vendor_ext'] = self._get_hosting_info(context, csrfw['port_id'], csrfw['router_id'], csrfw['direction']) fw_with_rules['vendor_ext']['acl_id'] = csrfw['acl_id'] self.agent_rpc.delete_firewall(context, fw_with_rules) @log_helpers.log_method_call def get_firewall(self, context, fwid, fields=None): res = super(ref_fw_plugin.FirewallPlugin, self).get_firewall( context, fwid, fields) csrfw = self.lookup_firewall_csr_association(context, res['id']) if not csrfw: return res res['port_id'] = csrfw['port_id'] res['direction'] = csrfw['direction'] res['router_id'] = csrfw['router_id'] return res neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/plugins/__init__.py0000664000567000056710000000000012701407720027534 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/0000775000567000056710000000000012701410073025425 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/linux/0000775000567000056710000000000012701410073026564 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/linux/__init__.py0000664000567000056710000000000012701407720030670 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/linux/iptables_fwaas.py0000664000567000056710000003331512701407720032134 0ustar jenkinsjenkins00000000000000# 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. from neutron.agent.linux import iptables_manager from oslo_log import log as logging from neutron_fwaas._i18n import _LE from neutron_fwaas.extensions import firewall as fw_ext from neutron_fwaas.services.firewall.drivers import fwaas_base LOG = logging.getLogger(__name__) FWAAS_DRIVER_NAME = 'Fwaas iptables driver' FWAAS_DEFAULT_CHAIN = 'fwaas-default-policy' FWAAS_TO_IPTABLE_ACTION_MAP = {'allow': 'ACCEPT', 'deny': 'DROP', 'reject': 'REJECT'} 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'} INTERNAL_DEV_PREFIX = 'qr-' SNAT_INT_DEV_PREFIX = 'sg-' ROUTER_2_FIP_DEV_PREFIX = 'rfp-' 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, agent_mode, 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(agent_mode, apply_list, firewall) else: self.apply_default_policy(agent_mode, apply_list, firewall) except (LookupError, RuntimeError): # catch known library exceptions and raise Fwaas generic exception LOG.exception(_LE("Failed to create firewall: %s"), firewall['id']) raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME) def _get_ipt_mgrs_with_if_prefix(self, agent_mode, router_info): """Gets the iptables manager along with the if prefix to apply rules. With DVR we can have differing namespaces depending on which agent (on Network or Compute node). Also, there is an associated i/f for each namespace. The iptables on the relevant namespace and matching i/f are provided. On the Network node we could have both the snat namespace and a fip so this is provided back as a list - so in that scenario rules can be applied on both. """ if not router_info.router.get('distributed'): return [{'ipt': router_info.iptables_manager, 'if_prefix': INTERNAL_DEV_PREFIX}] ipt_mgrs = [] # TODO(sridar): refactor to get strings to a common location. if agent_mode == 'dvr_snat': if router_info.snat_iptables_manager: ipt_mgrs.append({'ipt': router_info.snat_iptables_manager, 'if_prefix': SNAT_INT_DEV_PREFIX}) if router_info.dist_fip_count: # handle the fip case on n/w or compute node. ipt_mgrs.append({'ipt': router_info.iptables_manager, 'if_prefix': ROUTER_2_FIP_DEV_PREFIX}) return ipt_mgrs def delete_firewall(self, agent_mode, 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_if_prefix_list = self._get_ipt_mgrs_with_if_prefix( agent_mode, router_info) for ipt_if_prefix in ipt_if_prefix_list: ipt_mgr = ipt_if_prefix['ipt'] 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(_LE("Failed to delete firewall: %s"), fwid) raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME) def update_firewall(self, agent_mode, 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(agent_mode, apply_list, firewall) else: self.apply_default_policy(agent_mode, apply_list, firewall) except (LookupError, RuntimeError): # catch known library exceptions and raise Fwaas generic exception LOG.exception(_LE("Failed to update firewall: %s"), firewall['id']) raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME) def apply_default_policy(self, agent_mode, 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_if_prefix_list = self._get_ipt_mgrs_with_if_prefix( agent_mode, router_info) for ipt_if_prefix in ipt_if_prefix_list: # the following only updates local memory; no hole in FW ipt_mgr = ipt_if_prefix['ipt'] 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_if_prefix) # 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( _LE("Failed to apply default policy on firewall: %s"), fwid) raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME) def _setup_firewall(self, agent_mode, apply_list, firewall): fwid = firewall['id'] for router_info in apply_list: ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix( agent_mode, router_info) for ipt_if_prefix in ipt_if_prefix_list: ipt_mgr = ipt_if_prefix['ipt'] # 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_if_prefix) # 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_if_prefix): """Create Fwaas chain using the rules in the policy """ fw_rules_list = firewall['firewall_rule_list'] fwid = firewall['id'] ipt_mgr = ipt_if_prefix['ipt'] #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_if_prefix) 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'].remove_chain(chain_name) else: ipt_mgr.ipv6['filter'].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_if_prefix): bname = iptables_manager.binary_name ipt_mgr = ipt_if_prefix['ipt'] if_prefix = ipt_if_prefix['if_prefix'] 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 %s+ -j %s-%s' % (IPTABLES_DIR[direction], if_prefix, 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 %s+ -j %s-%s' % (if_prefix, 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 %s+ -j %s-%s' % (if_prefix, 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 = FWAAS_TO_IPTABLE_ACTION_MAP[rule.get('action')] 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' def _allow_established_rule(self): return '-m state --state ESTABLISHED,RELATED -j ACCEPT' def _action_arg(self, action): if action: return '-j %s' % action return '' def _protocol_arg(self, protocol): if protocol: return '-p %s' % protocol return '' def _port_arg(self, direction, protocol, port): if not (protocol in ['udp', 'tcp'] and port): return '' return '--%s %s' % (direction, port) def _ip_prefix_arg(self, direction, ip_prefix): if ip_prefix: return '-%s %s' % (direction, ip_prefix) return '' neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/fwaas_base.py0000664000567000056710000000702012701407720030076 0ustar jenkinsjenkins00000000000000# 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. 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. Argument agent_mode indicates the l3 agent in DVR or DVR_SNAT or LEGACY mode. """ @abc.abstractmethod def create_firewall(self, agent_mode, 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, agent_mode, 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, agent_mode, 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, agent_mode, apply_list, firewall): """Apply the default policy on all trusted interfaces. Remove current policy and apply the default policy on all trusted interfaces. """ pass neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/mcafee/0000775000567000056710000000000012701410073026645 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/mcafee/ngfw_fwaas.py0000664000567000056710000002667412701407720031365 0ustar jenkinsjenkins00000000000000# Copyright 2015 Intel Corporation. # Copyright 2015 Isaku Yamahata # # Copyright 2015 Yalei Wang # # 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 netaddr from neutron_lib import constants from oslo_config import cfg from oslo_log import helpers as log_helpers from oslo_log import log as logging from oslo_serialization import jsonutils from neutron_fwaas._i18n import _ from neutron_fwaas.services.firewall.drivers import fwaas_base from neutron_fwaas.services.firewall.drivers.mcafee import smc_api NGFWOpts = [ cfg.StrOpt( 'smc_url', default='', help=_("URL to contact SMC server") ), cfg.StrOpt( 'smc_api_auth_key', default='', help=_("Authentication key to SMC API") ), cfg.StrOpt( 'smc_api_version', default='', help=_("verion of SMC API") ), ] cfg.CONF.register_opts(NGFWOpts, 'ngfw') LOG = logging.getLogger(__name__) class NgfwFwaasDriver(fwaas_base.FwaasDriverBase): """Firewall driver for NGFW Fwaas of Mcafee """ def __init__(self): LOG.debug("Initializing FWaas Mcafee NGFW driver") super(NgfwFwaasDriver, self).__init__() self._host_list = [] self._network_list = [] self._smc_url = cfg.CONF.ngfw.smc_url self.fw_ips_template_ref = None self.fw_template_ref = None self.connection = smc_api.SMCAPIConnection( self._smc_url, cfg.CONF.ngfw.smc_api_version, cfg.CONF.ngfw.smc_api_auth_key) @log_helpers.log_method_call def create_firewall(self, agent_mode, apply_list, firewall): # call update_firewall, because one tenant only support # one firewall return self.update_firewall(agent_mode, apply_list, firewall) @log_helpers.log_method_call def delete_firewall(self, agent_mode, apply_list, firewall): # tell SMC server to remove the ngfw policy return self._delete_policy(apply_list, firewall) @log_helpers.log_method_call def update_firewall(self, agent_mode, apply_list, firewall): for router_info in apply_list: rt = router_info.router # only update the policy when the router is active if (rt['tenant_id'] == firewall['tenant_id'] and rt['status'] == 'ACTIVE'): self._update_policy(rt, firewall) def _delete_policy(self, apply_list, firewall): for router_info in apply_list: rt = router_info.router self._clear_policy(rt, firewall) @log_helpers.log_method_call def apply_default_policy(self, apply_list, firewall): return self._delete_policy(apply_list, firewall) def _update_policy(self, router, firewall): # clear all the policy first self._clear_policy(router, firewall) if firewall['admin_state_up']: self._setup_policy(router, firewall) def _is_ips_policy(self, policy_name): return policy_name[len(policy_name) - 4:].lower() == '-ips' def _get_policy_ref(self, policy_name): # get the template ref at the first time if not self.fw_ips_template_ref or not self.fw_template_ref: r = self.connection.get('elements/fw_template_policy') fw_template_list = r[0]['result'] for tplt in fw_template_list: if tplt['name'] == "Firewall Inspection Template": self.fw_ips_template_ref = tplt['href'].replace( self._smc_url + "/%s/" % cfg.CONF.ngfw.smc_api_version, '') elif tplt['name'] == "Firewall Template": self.fw_template_ref = tplt['href'].replace( self._smc_url + "/%s/" % cfg.CONF.ngfw.smc_api_version, '') # use different template base on the policy name if self._is_ips_policy(policy_name): template = self.fw_ips_template_ref else: template = self.fw_template_ref # create the policy in SMC server fw_policy = { "name": policy_name, "template": template } ref = self._get_ref_from_service_data('fw_policy', fw_policy) return ref def _parse_port(self, source_port): min_port = '' max_port = '' if source_port is None: min_port = 0 max_port = 65535 elif ':' in source_port: ports = source_port.split(':') min_port = int(ports[0]) max_port = int(ports[1]) else: min_port = int(source_port) max_port = '' return min_port, max_port def _get_ref_from_addr(self, addr): if addr == 'None': return addr ip = netaddr.IPNetwork(addr) if str(ip.netmask) != "255.255.255.255": # create network objects ref = self._create_network(addr) else: # create host objects ref = self._create_host(str(ip.ip)) return ref def _get_ref_from_service_data(self, service_path, service_data): json_data = jsonutils.dumps(service_data) r = self.connection.post_element(service_path, json_data) srv_ref = r.headers['location'] return srv_ref def _convert_ipv4_to_ngfw_rule(self, rule): # convert the ipv4 rule into ngfw rules # create src/dst of hosts or networks src_ref = self._get_ref_from_addr(str(rule['source_ip_address'])) dst_ref = self._get_ref_from_addr(str(rule['destination_ip_address'])) # create service srv_ref = '' service_dict = {} service = "%s_service" % rule['protocol'] if rule['protocol'] in (constants.PROTO_NAME_TCP, constants.PROTO_NAME_UDP): source_port = rule['source_port'] dest_port = rule['destination_port'] min_src_port, max_src_port = self._parse_port(source_port) min_dst_port, max_dst_port = self._parse_port(dest_port) service_data = { "name": "service-%s" % rule['name'], "min_src_port": min_src_port, "max_src_port": (min_src_port if max_src_port == '' else max_src_port), "min_dst_port": min_dst_port, "max_dst_port": (min_dst_port if max_dst_port == '' else max_dst_port) } srv_ref = self._get_ref_from_service_data(service, service_data) service_dict = {"service": [srv_ref]} elif rule['protocol'] == constants.PROTO_NAME_ICMP: # only ping is supported service_data = { "name": "service%s" % "22", "icmp_type": 0, "icmp_code": 0 } srv_ref = self._get_ref_from_service_data(service, service_data) service_dict = {"service": [srv_ref]} elif rule['protocol'] is None: # protocol "ANY" is translated to accept all, no service create # here # TODO(yalie): add rules for different protocol, not ignore the # other value like ports. service_dict = {"any": True} else: raise NotImplementedError( _("not support %s protocol now") % rule['protocol']) # create fw rule action = "discard" if rule["action"] == "deny" else "allow" payload = { "name": rule['name'], "action": { "action": action, "connection_tracking_options": {} }, "destinations": {"dst": [dst_ref]}, "services": service_dict, "sources": {"src": [src_ref]} } json_data = jsonutils.dumps(payload) return json_data def _get_policy_name(self, router, fw): # SMC server would bind the different NGFW policy with different # routers(sg-engine) in a tenant return "%s_%s_%s" % ( fw['id'][0:7], fw['firewall_policy_id'][0:7], router['id'][0:7]) def _setup_policy(self, router, fw): # one tenant should use only one policy with self.connection.login_server(): # create policy ref policy_name = self._get_policy_name(router, fw) policy_ref = self._get_policy_ref(policy_name) # post service for rule in fw['firewall_rule_list']: if not rule['enabled']: continue if rule['ip_version'] == 4: json_data = self._convert_ipv4_to_ngfw_rule(rule) self.connection.post(policy_ref + "/fw_ipv4_access_rule", json_data, raw=True) else: msg = (_('Unsupported IP version rule. %(version)') % {'version': rule['ip_version']}) raise ValueError(msg) # upload the policy self.connection.post(policy_ref + "/upload", '', raw=True) def _clear_policy(self, router, fw): # find the policy used by the tenant and firewall policy_name = self._get_policy_name(router, fw) path_policy_filter = 'elements/fw_policy?filter=%s' % policy_name with self.connection.login_server(): r = self.connection.get(path=path_policy_filter) fw_list = r[0]['result'] for f in fw_list: if f['name'] == policy_name: self.connection.delete(f['href'], raw=True) # Warning, find unused elements and delete them. r = self.connection.get(path='elements/search_unused') element_list = r[0]['result'] for element in element_list: self.connection.delete(element['href'], raw=True) def _create_host(self, ip): ref = None host_json_def = { "name": "host-%s" % str(ip), "address": ip } with self.connection.login_server(): ref = self._get_ref_from_service_data('host', host_json_def) return ref def _create_network(self, cidr): ref = None net_json_def = { "name": "network-%s" % str(cidr), "ipv4_network": cidr } with self.connection.login_server(): # some network maybe pre-created by router-plugin r = self.connection.get("elements/network") networks = r[0]['result'] for net in networks: if net['name'] == "network-%s" % cidr: ref = net['href'] return ref ref = self._get_ref_from_service_data('network', net_json_def) return ref neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/mcafee/constants.py0000664000567000056710000002166512701407720031252 0ustar jenkinsjenkins00000000000000# Copyright 2015 Intel Corporation. # Copyright 2015 Yalei Wang # # 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. JSON_PHY_INTERFACES = 'physicalInterfaces' JSON_NAME = 'name' JSON_NODES = 'nodes' JSON_LOG_SERVER_REF = 'log_server_ref' JSON_NODE_NET_VALUE = 'network_value' JSON_NODE_NET_ADDR = 'address' JSON_PHY_INTF = 'physical_interface' L2_ELEMENT_TEMPLATE = (""" { 'log_server_ref': 'http://localhost:8082/5.7/elements/log_server/1441', 'name': '@PLACE_HOLDER@ L2 FW', 'nodes': [ { 'fwlayer2_node': { 'name': '@PLACE_HOLDER@ L2 FW node 1', 'nodeid': 1 } } ], 'physicalInterfaces': [ { 'physical_interface': { 'interface_id': '1', 'interfaces': [ { 'inline_interface': { 'failure_mode': 'normal', 'logical_interface_ref': 'http://localhost:8082/5.7/elements/logical_interface/1', 'nicid': '1-2' } } ] } }, { 'physical_interface': { 'interface_id': '0', 'interfaces': [ { 'node_interface': { 'address': '192.168.2.10', 'network_value': '192.168.2.0/24', 'nicid': '0', 'nodeid': 1, 'outgoing': true, 'primary_mgt': true } } ] } }, { 'physical_interface': { 'interface_id': '3', 'interfaces': [ { 'capture_interface': { 'logical_interface_ref': 'http://localhost:8082/5.7/elements/logical_interface/1073741835', 'nicid': '3' } } ] } } ] } """) L3_ELEMENT_TEMPLATE = (""" { "alias_value": [ ], "antivirus": { "antivirus_enabled": false, "virus_log_level": "none", "virus_mirror": "database.clamav.net" }, "auto_reboot_timeout": 10, "connection_limit": 0, "connection_timeout": [ { "protocol": "icmp", "timeout": 5 }, { "protocol": "other", "timeout": 180 }, { "protocol": "tcp", "timeout": 1800 }, { "protocol": "udp", "timeout": 50 } ], "contact_timeout": 60000, "default_nat": false, "domain_server_address": [ ], "dos_protection": "always_off", "excluded_interface": -1, "is_cert_auto_renewal": true, "is_config_encrypted": true, "is_fips_compatible_operating_mode": false, "is_loopback_tunnel_ip_address_enforced": false, "is_virtual_defrag": true, "log_moderation": [ { "burst": 1000, "log_event": "1", "rate": 100 }, { "log_event": "2" } ], "log_server_ref": "@PLACE_HOLDER@", "log_spooling_policy": "discard", "loopback_cluster_virtual_interface": [ ], "name": "@PLACE_HOLDER@", "nodes": [ { "firewall_node": { "activate_test": true, "disabled": false, "loopback_node_dedicated_interface": [ ], "name": "@NODE_NAME_PLACE_HOLDER@", "nodeid": 1 } } ], "passive_discard_mode": false, "physicalInterfaces": [ ], "read_only": false, "rollback_timeout": 60, "scan_detection": { "scan_detection_icmp_events": 252, "scan_detection_icmp_timewindow": 60, "scan_detection_tcp_events": 252, "scan_detection_tcp_timewindow": 60, "scan_detection_type": "default off", "scan_detection_udp_events": 252, "scan_detection_udp_timewindow": 60 }, "slow_request_blacklist_timeout": 300, "slow_request_sensitivity": "off", "strict_tcp_mode": false, "syn_flood_sensitivity": "off", "syn_mode": "off", "system": false, "tcp_reset_sensitivity": "OFF", "tester_parameters": { "alert_interval": 3600, "auto_recovery": true, "boot_delay": 30, "boot_recovery": true, "restart_delay": 5, "status_delay": 5 }, "tracking_mode": "normal" } """) PHYSICAL_INTERFACE_TEMPLATE = (""" { "physical_interface": { "aggregate_mode": "none", "arp_entry": [ ], "cvi_mode": "none", "dhcp_server_on_interface": { "dhcp_range_per_node": [ ] }, "interface_id": "@PLACE_HODLER@", "interfaces": [ { "single_node_interface": { "address": "@PLACE_HOLDER_IP@", "auth_request": false, "auth_request_source": false, "backup_heartbeat": false, "backup_mgt": false, "dynamic_ip": false, "igmp_mode": "none", "key": 200, "modem": false, "network_value": "@PLACE_HOLDER_IP_NETWORK@", "nicid": "0", "nodeid": 1, "outgoing": false, "pppoa": false, "pppoe": false, "primary_heartbeat": false, "primary_mgt": false, "relayed_by_dhcp": false, "reverse_connection": false, "vrrp": false, "vrrp_id": -1, "vrrp_priority": -1 } } ], "log_moderation": [ { "burst": 1000, "log_event": "1", "rate": 100 }, { "log_event": "2" } ], "managed_address_flag": false, "mtu": -1, "other_configuration_flag": false, "qos_limit": -1, "qos_mode": "no_qos", "router_advertisement": false, "syn_mode": "default", "virtual_engine_vlan_ok": false, "vlanInterfaces": [ ] } } """) neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/mcafee/smc_api.py0000664000567000056710000004066212701407721030650 0ustar jenkinsjenkins00000000000000# Copyright 2015 Intel Corporation. # Copyright 2015 Isaku Yamahata # # Copyright 2015 Yalei Wang # # 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. # # This script uses SMC-API to get/post elements from SMC server # import abc import netaddr import requests import six from contextlib import contextmanager from neutron.common import exceptions as n_exc from oslo_log import log as logging from oslo_serialization import jsonutils from neutron_fwaas._i18n import _, _LE, _LI, _LW from neutron_fwaas.services.firewall.drivers.mcafee import constants as const LOG = logging.getLogger(__name__) class SMCAPIResult(object): """Class for returning result to API caller""" def __init__(self, tp): self.type = tp self.result = "N/A" self.code = "200" self.headers = None def is_json(self): return self.type == "json" def is_text(self): return self.type == "text" def __str__(self): return self.result class SMCAPIConnection(object): """Provide the REST API method to connect to the SMC server. For login/logout operation, users should set server IP, API version and auth key first. For get/put/delete operation, users should provide the target element's path and special json format data section following "SMC API User's Guide". """ def __init__(self, host, api_version, authentication_key): self.cookies = {} self.host = host self.api_version = api_version self.host_api_url = self.host + "/" + self.api_version self.auth_key = authentication_key self.session = None @contextmanager def login_server(self): if self.session: yield else: ret = self.login() LOG.debug("SMC server LOGIN successfully.") if ret: try: yield except Exception: LOG.exception(_LE("exception while connect to server!")) raise n_exc.ServiceUnavailable(resource='SMC server', msg=_("OPERATION failed")) finally: self.logout() else: raise n_exc.BadRequest(resource='SMC server', msg=_("LOGIN failed!")) def login(self): self.session = requests.session() post_addr = ("%s/login?authenticationkey=%s&beta=true" % (self.host_api_url, self.auth_key)) res = self.session.post(post_addr) if res.status_code == 200: return True LOG.error(_LE("connect to %(host)s failed" " (%(msg)s/ code %(code)s)"), {'host': post_addr, 'msg': res.reason, 'code': res.status_code}) return False def logout(self): result = self.session.put("%s/logout" % (self.host_api_url)) self.session = None LOG.debug("LOGOUT from SMC server result %s", result) def session_op(self, attr, path, raw=False, data=None, headers=None): op = getattr(self.session, attr) if raw: result = op(path, headers=headers, data=data) else: result = op("%s/%s" % (self.host_api_url, path), headers=headers, data=data) if result.status_code == "404": LOG.error(_LE("SMC Error 404 %s"), result.reason) return result def get(self, path, etag=None, raw=False): json_result = None etag_out = None headers = {'accept': 'application/json', 'content-type': 'application/json'} if etag: headers['ETag'] = etag try: result = self.session_op("get", path, raw, headers=headers) if 'etag' in result.headers: etag_out = result.headers['etag'] json_result = result.json() if result.status_code == "404": LOG.error(_LE("%(msg)s %(detail)s"), {'msg': json_result["message"], 'detail': json_result["details"]}) except Exception: LOG.error(_LE("exception when GET operation")) raise r = [json_result] if etag_out: r.append(etag_out) return [json_result] def check_ret(self, string, path, ret, updated_result): if ret.status_code != 200: LOG.info(_LI("%(str)s ELEMENT result code: %(stat)d " "%(path)s %(reason)s text=%(text)s"), {'str': string, 'path': path, 'stat': ret.status_code, 'reason': ret.reason, 'text': ret.text}) updated_result.type = "text" updated_result.result = ret.text else: if ret.headers.get('content-type') == "application/json": updated_result.type = "json" updated_result.result = ret.json else: updated_result.type = "text" updated_result.result = ret.content updated_result.code = ret.status_code def delete(self, path, raw=False): del_result = SMCAPIResult("text") try: result = self.session_op("delete", path, raw) self.check_ret("DELETE", path, result, del_result) except Exception: LOG.error(_LE("exception when DELETE operation")) raise return del_result def post(self, path, json_element, raw=False): headers = {'accept': '*/*', 'content-type': 'application/json'} post_result = SMCAPIResult("text") try: result = self.session_op( "post", path, raw, headers=headers, data=json_element) self.check_ret("POST", path, result, post_result) post_result.headers = result.headers except Exception: LOG.error(_LE("exception when POST operation")) raise return post_result def post_element(self, element_type, json_element): return self.post("elements/%s" % (element_type), json_element) @six.add_metaclass(abc.ABCMeta) class SMCAPIElement(object): """ Base class of elements, used by L2/L3 single firewall class """ element_type = "N/A" @staticmethod def usage(extra_info=None): if extra_info: LOG.error(_LE("Error -> %s"), extra_info) raise ValueError(_('Wrong initial data!')) def __init__(self, name, smc_api_connection, control_ip=None): if not name: self.usage("name of element missing.") self.name = name self.element_id = 0 self.json_element = None self.element_template = None self.smc_api_connection = smc_api_connection self.keyboard = None self.timezone = None if control_ip: self.control_ip = netaddr.IPNetwork(control_ip) if self.control_ip.prefixlen == 32: self.usage( "Control_ip %s needs to netmask bits e.g x.x.x.x/yy" % (self.control_ip)) else: self.control_ip = None def to_json(self): return jsonutils.dumps(self.json_element) @abc.abstractmethod def create(self): raise NotImplementedError( "not support SMCAPIElement create") @abc.abstractmethod def update(self): raise NotImplementedError( "not support SMCAPIElement update") @abc.abstractmethod def delete(self): raise NotImplementedError( "not support SMCAPIElement delete") def get_element(self, path): LOG.debug("Getting path: %s", path) return self.smc_api_connection.get("elements/%s" % (path)) def get_elements(self, element_type=None): if not element_type: element_type = self.element_type return self.smc_api_connection.get("elements/%s" % (element_type)) def fetch_element_id(self): json_result = self.get_elements() if not json_result[0]['result']: LOG.warning(_LW("No #{element_type} defined in SMC")) else: for element in json_result[0]['result']: href = element['href'] self.element_id = int(href.split('/')[-1]) if element['name'] == self.name: LOG.debug("%(type)s element with name %(name)s FOUND " "%(href)s", {'type': self.element_type, 'name': self.name, 'href': href}) break LOG.debug("Got ID %s", self.element_id) return self.element_id def get_initial_contact_data(self): """Get the element's configuration data used to contact to SMC server. Contact data is a configuration string including the SMC server's IP, interfaces defined and special one-time password. eg. first create the L3 element on behalf of sg-engine in SMC server and generate the contact data, then boot the sg-engine with it and engine will init properly and connect to SMC server finally. """ data = None result = self.get_element("%s/%s/node" % (self.element_type, self.element_id)) LOG.debug("resule = %s", result) node_ref = result[0]['result'][0]['href'].replace( self.smc_api_connection.host_api_url + "/elements/", "") LOG.debug("Node ref is %s", node_ref) extra_options = [] if self.keyboard: extra_options.append("keyboard=%s" % (self.keyboard)) if self.timezone: extra_options.append("time_zone=%s" % (self.timezone)) if extra_options: extra_options = "&" + extra_options else: extra_options = "" result = self.smc_api_connection.post_element( "%s/initial_contact?enable_ssh=true%s" % (node_ref, extra_options), "") if result.is_text(): d1 = str(result).split("\n") idx = 0 for l in d1: if l.find("ssh/enabled") != -1: l = l.replace("false", "true") d1[idx] = l idx += 1 result.result = "\n".join(d1) data = result result = self.smc_api_connection.post_element( "%s/bind_license" % (node_ref), "") if result.code != 200: LOG.error(_LE("Could not bind license. " "Maybe SMC license pool is empty. " "SMC API details: %s"), result) return data class SMCAPIElementL2FWSingle(SMCAPIElement): """L2 single firewall element.""" element_type = "single_layer2" def __init__(self, name, smc_api_connection, control_ip): SMCAPIElement.__init__(self, name, smc_api_connection, control_ip) self.element_id = 0 self.json_element = None def create(self): json_result = self.get_elements("log_server") log_server_ref = json_result[0]['result'][0]['href'] LOG.debug("Using log server '%(name)s', ref %(ref)s", {'name': json_result[0]['result'][0]['name'], 'ref': log_server_ref}) json_result = self.get_elements("logical_interface") logical_interfaces = dict((logical_iface['name'], logical_iface['href']) for logical_iface in json_result[0]['result'] if logical_iface['name'] in ('default_eth', 'capture')) for name, ref in six.iteritems(logical_interfaces): LOG.debug("Using logical interface %(name)s ref %(href)s", {'name': name, 'href': ref}) json_data = jsonutils.loads(const.L2_ELEMENT_TEMPLATE) json_data[const.JSON_LOG_SERVER_REF] = log_server_ref json_data[const.JSON_NAME] = self.name json_data[const.JSON_NODES][0]['fwlayer2_node']['name'] = (self.name + " node 1") physical_ifaces = json_data[const.JSON_PHY_INTERFACES] for phys_iface in physical_ifaces: for iface in phys_iface[const.JSON_PHY_INTF]['interfaces']: if 'inline_interface' in iface: inline_iface = iface['inline_interface'] inline_iface['logical_interface_ref'] = ( logical_interfaces['default_eth']['href']) elif 'capture_interface' in iface: capture_iface = iface['capture_interface'] capture_iface['logical_interface_ref'] = ( logical_interfaces['capture']['href']) elif 'node_interface' in iface: node_iface = iface['node_interface'] if not node_iface['primary_mgt']: continue node_iface[const.JSON_NODE_NET_ADDR] = ( str(self.control_ip.ip)) node_iface[const.JSON_NODE_NET_VALUE] = ( str(self.control_ip.cidr)) self.json_element = json_data self.smc_api_connection.post_element(self.element_type, self.to_json()) self.fetch_element_id() def update(self): """Update element """ pass def delete(self): """Delete element """ pass class SMCAPIElementL3FWSingle(SMCAPIElement): """L3 single firewall element.""" element_type = "single_fw" def __init__(self, name, smc_api_connection, control_ip): super(SMCAPIElementL3FWSingle, self).__init__(self, name, smc_api_connection, control_ip) self.element_id = 0 self.json_element = None self.physical_interfaces = [] def modify_interface_property(self, physical_interface, name, value): iface = physical_interface[const.JSON_PHY_INTF] iface = iface['interfaces'][0]['single_node_interface'] iface[name] = value def add_physical_interface(self, ip_and_network, interface_id): ip = netaddr.IPNetwork(ip_and_network) json_data = jsonutils.loads(const.PHYSICAL_INTERFACE_TEMPLATE) phys_iface = json_data[const.JSON_PHY_INTF] phys_iface['interface_id'] = interface_id iface = json_data[const.JSON_PHY_INTF]['interfaces'][0] iface = iface['single_node_interface'] iface[const.JSON_NODE_NET_ADDR] = str(ip.ip) iface[const.JSON_NODE_NET_VALUE] = str(ip.cidr) self.physical_interfaces.append(json_data) return json_data def create(self): json_result = self.get_elements("log_server") log_server_ref = json_result[0]['result'][0]['href'] LOG.debug( "Using log server '%(name)s' ref %(ref)s", {'name': json_result[0]['result'][0]['name'], 'ref': log_server_ref}) json_data = jsonutils.loads(const.L3_ELEMENT_TEMPLATE) json_data[const.JSON_LOG_SERVER_REF] = log_server_ref json_data[const.JSON_NAME] = self.name json_data[const.JSON_NODES][0]['firewall_node']['name'] = (self.name + " node 1") iface = self.add_physical_interface(self.control_ip, 0) self.modify_interface_property(iface, "primary_mgt", True) for phys_iface in self.physical_interfaces: json_data[const.JSON_PHY_INTERFACES].append(phys_iface) LOG.debug("%s", jsonutils.dumps(json_data, sort_keys=False, indent=2, separators=(',', ': '))) self.json_element = json_data self.smc_api_connection.post_element(self.element_type, self.to_json()) self.fetch_element_id() neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/mcafee/__init__.py0000664000567000056710000000000012701407720030751 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/mcafee/README.rst0000664000567000056710000000051512701407720030342 0ustar jenkinsjenkins00000000000000Mcafee NGFW Firewall as a Service Driver * For more information, refer to: https://wiki.openstack.org/wiki/Mcafee_NGFW_Firewall_driver * For information on Intel NGFW CI, refer to: https://wiki.openstack.org/wiki/ThirdPartySystems/Intel_NGFW_CI * Intel NGFW CI contact: - yalei.wang@intel.com - rui.zang@intel.com neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/varmour/0000775000567000056710000000000012701410073027120 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/varmour/__init__.py0000775000567000056710000000000012701407720031227 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/varmour/varmour_fwaas.py0000775000567000056710000001643712701407720032371 0ustar jenkinsjenkins00000000000000# 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. from oslo_log import log as logging from neutron_fwaas._i18n import _LW from neutron_fwaas.services.firewall.agents.varmour import varmour_api from neutron_fwaas.services.firewall.agents.varmour \ import varmour_utils as va_utils from neutron_fwaas.services.firewall.drivers import fwaas_base LOG = logging.getLogger(__name__) class vArmourFwaasDriver(fwaas_base.FwaasDriverBase): def __init__(self): LOG.debug("Initializing fwaas vArmour driver") self.fake_agent_mode = None self.rest = varmour_api.vArmourRestAPI() def create_firewall(self, agent_mode, apply_list, firewall): LOG.debug('create_firewall (%s)', firewall['id']) return self.update_firewall(self.fake_agent_mode, apply_list, firewall) def update_firewall(self, agent_mode, apply_list, firewall): LOG.debug("update_firewall (%s)", firewall['id']) if firewall['admin_state_up']: return self._update_firewall(apply_list, firewall) else: return self.apply_default_policy(apply_list, firewall) def delete_firewall(self, agent_mode, apply_list, firewall): LOG.debug("delete_firewall (%s)", firewall['id']) return self.apply_default_policy(self.fake_agent_mode, apply_list, firewall) def apply_default_policy(self, agent_mode, apply_list, firewall): LOG.debug("apply_default_policy (%s)", firewall['id']) self.rest.auth() for ri in apply_list: self._clear_policy(ri, firewall) return True def _update_firewall(self, apply_list, firewall): LOG.debug("Updating firewall (%s)", firewall['id']) self.rest.auth() for ri in apply_list: self._clear_policy(ri, firewall) self._setup_policy(ri, firewall) return True def _setup_policy(self, ri, fw): # create zones no matter if they exist. Interfaces are added by router body = { 'type': 'L3', 'interface': [] } body['name'] = va_utils.get_trusted_zone_name(ri) self.rest.rest_api('POST', va_utils.REST_URL_CONF_ZONE, body) body['name'] = va_utils.get_untrusted_zone_name(ri) self.rest.rest_api('POST', va_utils.REST_URL_CONF_ZONE, body) self.rest.commit() servs = dict() addrs = dict() for rule in fw['firewall_rule_list']: if not rule['enabled']: continue if rule['ip_version'] == 4: service = self._make_service(ri, fw, rule, servs) s_addr = self._make_address(ri, fw, rule, addrs, True) d_addr = self._make_address(ri, fw, rule, addrs, False) policy = va_utils.get_firewall_policy_name(ri, fw, rule) z0 = va_utils.get_trusted_zone_name(ri) z1 = va_utils.get_untrusted_zone_name(ri) body = self._make_policy(policy + '_0', rule, z0, z0, s_addr, d_addr, service) self.rest.rest_api('POST', va_utils.REST_URL_CONF_POLICY, body) body = self._make_policy(policy + '_1', rule, z0, z1, s_addr, d_addr, service) self.rest.rest_api('POST', va_utils.REST_URL_CONF_POLICY, body) body = self._make_policy(policy + '_2', rule, z1, z0, s_addr, d_addr, service) self.rest.rest_api('POST', va_utils.REST_URL_CONF_POLICY, body) self.rest.commit() else: LOG.warning(_LW("Unsupported IP version rule.")) def _clear_policy(self, ri, fw): prefix = va_utils.get_firewall_object_prefix(ri, fw) self.rest.del_cfg_objs(va_utils.REST_URL_CONF_POLICY, prefix) self.rest.del_cfg_objs(va_utils.REST_URL_CONF_ADDR, prefix) self.rest.del_cfg_objs(va_utils.REST_URL_CONF_SERVICE, prefix) def _make_service(self, ri, fw, rule, servs): prefix = va_utils.get_firewall_object_prefix(ri, fw) if rule.get('protocol'): key = rule.get('protocol') if rule.get('source_port'): key += '-' + rule.get('source_port') if rule.get('destination_port'): key += '-' + rule.get('destination_port') else: return if key in servs: name = '%s_%d' % (prefix, servs[key]) else: # create new service object with index idx = len(servs) servs[key] = idx name = '%s_%d' % (prefix, idx) body = {'name': name} self.rest.rest_api('POST', va_utils.REST_URL_CONF_SERVICE, body) body = self._make_service_rule(rule) self.rest.rest_api('POST', va_utils.REST_URL_CONF + va_utils.REST_SERVICE_NAME % name, body) self.rest.commit() return name def _make_service_rule(self, rule): body = { 'name': '1', 'protocol': rule.get('protocol') } if 'source_port' in rule: body['source-start'] = rule['source_port'] body['source-end'] = rule['source_port'] if 'destination_port' in rule: body['dest-start'] = rule['destination_port'] body['dest-end'] = rule['destination_port'] return body def _make_address(self, ri, fw, rule, addrs, is_src): prefix = va_utils.get_firewall_object_prefix(ri, fw) if is_src: key = rule.get('source_ip_address') else: key = rule.get('destination_ip_address') if not key: return if key in addrs: name = '%s_%d' % (prefix, addrs[key]) else: # create new address object with idx idx = len(addrs) addrs[key] = idx name = '%s_%d' % (prefix, idx) body = { 'name': name, 'type': 'ipv4', 'ipv4': key } self.rest.rest_api('POST', va_utils.REST_URL_CONF_ADDR, body) self.rest.commit() return name def _make_policy(self, name, rule, zone0, zone1, s_addr, d_addr, service): body = { 'name': name, 'action': 'permit' if rule.get('action') == 'allow' else 'deny', 'from': zone0, 'to': zone1, 'match-source-address': [s_addr or 'Any'], 'match-dest-address': [d_addr or 'Any'], 'match-service': [service or 'Any'] } return body neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/cisco/0000775000567000056710000000000012701410073026525 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/cisco/csr_acl_driver.py0000664000567000056710000003252312701407720032072 0ustar jenkinsjenkins00000000000000# Copyright 2014 Cisco Systems, 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 requests from networking_cisco.plugins.cisco.cfg_agent.device_drivers import ( cisco_csr_rest_client) from oslo_log import log as logging from neutron_fwaas._i18n import _LE from neutron_fwaas.services.firewall.drivers import fwaas_base LOG = logging.getLogger(__name__) #----- ACL REST URL definitions ------------------------------------------- ACL_API = 'acl' ACL_API_ACLID = 'acl/%s' # ACLID ACL_API_ACLID_IF = 'acl/%s/interfaces' # ACLID ACL_API_ACLID_IFID_DIR = 'acl/%s/interfaces/%s_%s' # ACLID, IF_DIRECTION class CsrAclDriver(fwaas_base.FwaasDriverBase): """Cisco CSR ACL driver for FWaaS. This driver will send ACL configuration via RESTAPI to CSR1kv. This driver will return error to the caller function in case of error such as validation failures, sending configuration failures. The caller function will handle the error return properly. """ def __init__(self): LOG.debug("Initializing fwaas CSR ACL driver") def _get_csr_host(self, firewall_vendor_ext): settings = { 'rest_mgmt_ip': firewall_vendor_ext['host_mngt_ip'], 'username': firewall_vendor_ext['host_usr_nm'], 'password': firewall_vendor_ext['host_usr_pw'], 'timeout': 30, } return cisco_csr_rest_client.CsrRestClient(settings) def _validate_firewall_rule_data(self, firewall): if 'firewall_rule_list' not in firewall: LOG.error(_LE("no rule list")) return False for rule in firewall['firewall_rule_list']: if 'name' not in rule: LOG.error(_LE("CsrAcl: no rule name")) return False ip_version = rule.get('ip_version') if ip_version != 4: LOG.error(_LE("invalid ip version %(ip_version)s in " "rule %(rule)s"), {'ip_version': ip_version, 'rule': rule['name']}) return False if 'protocol' not in rule: LOG.error(_LE("no protocol in rule [%s]"), rule['name']) return False if rule.get('action', '').lower() not in ('allow', 'deny'): LOG.error(_LE("invalid action in rule [%s]"), rule['name']) return False return True def _validate_firewall_data(self, firewall): data = ('admin_state_up', 'vendor_ext') is_valid = all(x in firewall for x in data) if not is_valid: LOG.error(_LE("missing data in firewall")) return is_valid data = ('host_mngt_ip', 'host_usr_nm', 'host_usr_pw', 'if_list') is_valid = all(x in firewall['vendor_ext'] for x in data) if not is_valid: LOG.error(_LE("missing data in firewall vendor_ext")) return is_valid for firewall_interface in firewall['vendor_ext']['if_list']: if firewall_interface.get('direction', '') not in ( 'inside', 'outside', 'both'): LOG.error(_LE("invalid direction")) return False if 'port' not in firewall_interface: LOG.error(_LE("no port")) return False port = firewall_interface['port'] if 'id' not in port: LOG.error(_LE("no port id")) return False if 'hosting_info' not in port: LOG.error(_LE("no hosting_info")) return False if 'segmentation_id' not in port['hosting_info']: LOG.error(_LE("no segmentation_id")) return False if 'hosting_port_name' not in port['hosting_info']: LOG.error(_LE("hosting_port_name")) return False interface_type = port['hosting_info'][ 'hosting_port_name'].split(':')[0] + ':' if interface_type not in ('t1_p:', 't2_p:'): LOG.error(_LE("invalide interface type %s"), interface_type) return False return True def _get_acl_l4_port(self, rule_port_name, rule, l4_opt): if rule.get(rule_port_name): ports = rule[rule_port_name].split(':') if rule_port_name == 'source_port': port_prefix = 'src' else: port_prefix = 'dest' l4_opt[port_prefix + '-port-start'] = ports[0] if len(ports) == 2: l4_opt[port_prefix + '-port-end'] = ports[1] def _get_acl_rule_data(self, firewall): """Get ACL RESTAPI request data from firewall dictionary. :return: ACL RESTAPI request data based on data from plugin. :return: {} if there is any error. """ acl_rules_list = [] seq = 100 for rule in firewall['firewall_rule_list']: if not rule['enabled']: continue ace_rule = {'sequence': str(seq)} seq += 1 if rule.get('protocol'): ace_rule['protocol'] = rule['protocol'] else: ace_rule['protocol'] = 'all' if rule['action'].lower() == 'allow': ace_rule['action'] = 'permit' else: ace_rule['action'] = 'deny' if rule.get('source_ip_address'): ace_rule['source'] = rule['source_ip_address'] else: ace_rule['source'] = 'any' if rule.get('destination_ip_address'): ace_rule['destination'] = rule['destination_ip_address'] else: ace_rule['destination'] = 'any' l4_opt = {} self._get_acl_l4_port('source_port', rule, l4_opt) self._get_acl_l4_port('destination_port', rule, l4_opt) if l4_opt: ace_rule['l4-options'] = l4_opt acl_rules_list.append(ace_rule) return {'rules': acl_rules_list} def _get_interface_name_from_hosting_port(self, port): vlan = port['hosting_info']['segmentation_id'] interface_type, interface_num = port[ 'hosting_info']['hosting_port_name'].split(':') offset = 0 if interface_type == 't1_p' else 1 interface_num = str(int(interface_num) * 2 + offset) return 'GigabitEthernet%s.%s' % (interface_num, vlan) def _post_acl_to_interfaces(self, firewall, csr, acl_id, status_data): acl_interface_url = ACL_API_ACLID_IF % acl_id for firewall_interface in firewall['vendor_ext']['if_list']: if_name = self._get_interface_name_from_hosting_port( firewall_interface['port']) acl_interface_req = { 'if-id': if_name, 'direction': firewall_interface['direction'] } LOG.debug("acl_interface_url %s", acl_interface_url) csr.post_request(acl_interface_url, acl_interface_req) if csr.status == requests.codes.CREATED: status_data['if_list'].append( {'port_id': firewall_interface['port']['id'], 'status': 'OK'}) else: LOG.error(_LE("status %s"), csr.status) status_data['if_list'].append( {'port_id': firewall_interface['port']['id'], 'status': 'ERROR'}) def _delete_acl_on_interface(self, csr, acl_id, csr_firewall_interface_list): for interface in csr_firewall_interface_list: my_api = ACL_API_ACLID_IFID_DIR % ( acl_id, interface['if-id'], interface['direction']) csr.delete_request(my_api) if csr.status != requests.codes.NO_CONTENT: LOG.error(_LE("status %s"), csr.status) def _get_acl_interface(self, csr, acl_id): my_api = ACL_API_ACLID_IF % acl_id response = csr.get_request(my_api) if csr.status == requests.codes.OK: return response['items'] LOG.error(_LE("status %s"), csr.status) return '' def _post_acl(self, csr, acl_data): response = csr.post_request(ACL_API, acl_data) if csr.status == requests.codes.CREATED: return response[response.rfind('/') + 1:] LOG.error(_LE("status %s"), csr.status) return '' def _delete_acl(self, csr, acl_id): my_api = ACL_API_ACLID % acl_id csr.delete_request(my_api) if csr.status == requests.codes.NO_CONTENT: return True LOG.error(_LE("status %s"), csr.status) return False def _put_acl(self, csr, acl_id, acl_data): my_api = ACL_API_ACLID % acl_id csr.put_request(my_api, acl_data) if csr.status == requests.codes.NO_CONTENT: return True LOG.error(_LE("status %s"), csr.status) return False def _create_firewall(self, firewall): """Create ACL and apply ACL to interfaces. :param firewall: firewall dictionary :return: True and status_data if OK :return: False and status_data if there is an error """ LOG.debug("firewall %s", firewall) if not self._validate_firewall_data(firewall): return False, {} if not self._validate_firewall_rule_data(firewall): return False, {} csr = self._get_csr_host(firewall['vendor_ext']) acl_data = self._get_acl_rule_data(firewall) LOG.debug("acl_data %s", acl_data) acl_id = self._post_acl(csr, acl_data) if not acl_id: LOG.debug("No acl_id created, acl_data %s", acl_data) return False, {} LOG.debug("new ACL ID: %s", acl_id) status_data = { 'fw_id': firewall['id'], 'acl_id': acl_id, 'if_list': [] } if not firewall['admin_state_up']: LOG.debug("status %s", status_data) return True, status_data # apply ACL to interfaces self._post_acl_to_interfaces(firewall, csr, acl_id, status_data) LOG.debug("status %s", status_data) return True, status_data def _delete_firewall(self, firewall): """Delete ACL. :param firewall: firewall dictionary :return: True if OK :return: False if there is an error """ if not self._validate_firewall_data(firewall): return False acl_id = firewall['vendor_ext'].get('acl_id') if not acl_id: LOG.error(_LE("firewall (%s) has no acl_id"), firewall['id']) return False csr = self._get_csr_host(firewall['vendor_ext']) return self._delete_acl(csr, acl_id) def _update_firewall(self, firewall): """Update ACL and associated interfaces. :param firewall: firewall dictionary :return: True and status_data if OK :return: False and {} if there is an error """ if not self._validate_firewall_data(firewall): return False, {} if not self._validate_firewall_rule_data(firewall): return False, {} acl_id = firewall['vendor_ext'].get('acl_id') if not acl_id: LOG.error(_LE("firewall (%s) has no acl_id"), firewall['id']) return False, {} csr = self._get_csr_host(firewall['vendor_ext']) rest_acl_rules = self._get_acl_rule_data(firewall) rest_acl_rules['acl-id'] = acl_id # update ACL rules response = self._put_acl(csr, acl_id, rest_acl_rules) if not response: return False, {} status_data = { 'fw_id': firewall['id'], 'acl_id': acl_id, 'if_list': [] } # update ACL interface # get all interfaces with this acl_id csr_fw_interface_list = self._get_acl_interface(csr, acl_id) self._delete_acl_on_interface(csr, acl_id, csr_fw_interface_list) if not firewall['admin_state_up']: return True, status_data self._post_acl_to_interfaces(firewall, csr, acl_id, status_data) return True, status_data def create_firewall(self, agent_mode, apply_list, firewall): """Create firewall on CSR.""" LOG.debug("create_firewall: firewall %s", firewall) return self._create_firewall(firewall) def delete_firewall(self, agent_mode, apply_list, firewall): """Delete firewall on CSR.""" LOG.debug("delete_firewall: firewall %s", firewall) return self._delete_firewall(firewall) def update_firewall(self, agent_mode, apply_list, firewall): """Update firewall on CSR.""" LOG.debug("update_firewall: firewall %s", firewall) return self._update_firewall(firewall) def apply_default_policy(self, agent_mode, apply_list, firewall): # CSR firewall driver does not support this for now LOG.debug("apply_default_policy") neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/cisco/__init__.py0000664000567000056710000000000012701407720030631 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/cisco/csr_firewall_svc_helper.py0000664000567000056710000002350512701407720033777 0ustar jenkinsjenkins00000000000000# Copyright 2014 Cisco Systems, 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. from networking_cisco.plugins.cisco.cfg_agent.service_helpers import ( service_helper) from neutron.common import rpc as n_rpc from neutron import context as n_context from neutron.plugins.common import constants from oslo_log import helpers as log_helpers from oslo_log import log as logging import oslo_messaging from neutron_fwaas._i18n import _LE from neutron_fwaas.services.firewall.drivers.cisco import csr_acl_driver LOG = logging.getLogger(__name__) CSR_FW_EVENT_Q_NAME = 'csr_fw_event_q' CSR_FW_EVENT_CREATE = 'FW_EVENT_CREATE' CSR_FW_EVENT_UPDATE = 'FW_EVENT_UPDATE' CSR_FW_EVENT_DELETE = 'FW_EVENT_DELETE' class CsrFirewalllPluginApi(object): """CsrFirewallServiceHelper (Agent) side of the ACL RPC API.""" @log_helpers.log_method_call def __init__(self, topic, host): self.host = host target = oslo_messaging.Target(topic=topic, version='1.0') self.client = n_rpc.get_client(target) @log_helpers.log_method_call def get_firewalls_for_device(self, context, **kwargs): """Get Firewalls with rules for a device from Plugin.""" cctxt = self.client.prepare() return cctxt.call(context, 'get_firewalls_for_device', host=self.host) @log_helpers.log_method_call def get_firewalls_for_tenant(self, context, **kwargs): """Get Firewalls with rules for a tenant from the Plugin.""" cctxt = self.client.prepare() return cctxt.call(context, 'get_firewalls_for_tenant', host=self.host) @log_helpers.log_method_call def get_tenants_with_firewalls(self, context, **kwargs): """Get Tenants that have Firewalls configured from plugin.""" cctxt = self.client.prepare() return cctxt.call(context, 'get_tenants_with_firewalls', host=self.host) @log_helpers.log_method_call def set_firewall_status(self, context, fw_id, status, status_data=None): """Make a RPC to set the status of a firewall.""" cctxt = self.client.prepare() return cctxt.call(context, 'set_firewall_status', host=self.host, firewall_id=fw_id, status=status, status_data=status_data) def firewall_deleted(self, context, firewall_id): """Make a RPC to indicate that the firewall resources are deleted.""" cctxt = self.client.prepare() return cctxt.call(context, 'firewall_deleted', host=self.host, firewall_id=firewall_id) class CsrFirewallServiceHelper(object): @log_helpers.log_method_call def __init__(self, host, conf, cfg_agent): super(CsrFirewallServiceHelper, self).__init__() self.conf = conf self.cfg_agent = cfg_agent self.fullsync = True self.event_q = service_helper.QueueMixin() self.fw_plugin_rpc = CsrFirewalllPluginApi( 'CISCO_FW_PLUGIN', conf.host) self.topic = 'CISCO_FW' self._setup_rpc() self.acl_driver = csr_acl_driver.CsrAclDriver() def _setup_rpc(self): self.conn = n_rpc.create_connection() self.endpoints = [self] self.conn.create_consumer(self.topic, self.endpoints, fanout=True) self.conn.consume_in_threads() ### Notifications from Plugin #### def create_firewall(self, context, firewall, host): """Handle Rpc from plugin to create a firewall.""" LOG.debug("create_firewall: firewall %s", firewall) event_data = {'event': CSR_FW_EVENT_CREATE, 'context': context, 'firewall': firewall, 'host': host} self.event_q.enqueue(CSR_FW_EVENT_Q_NAME, event_data) def update_firewall(self, context, firewall, host): """Handle Rpc from plugin to update a firewall.""" LOG.debug("update_firewall: firewall %s", firewall) event_data = {'event': CSR_FW_EVENT_UPDATE, 'context': context, 'firewall': firewall, 'host': host} self.event_q.enqueue(CSR_FW_EVENT_Q_NAME, event_data) def delete_firewall(self, context, firewall, host): """Handle Rpc from plugin to delete a firewall.""" LOG.debug("delete_firewall: firewall %s", firewall) event_data = {'event': CSR_FW_EVENT_DELETE, 'context': context, 'firewall': firewall, 'host': host} self.event_q.enqueue(CSR_FW_EVENT_Q_NAME, event_data) def _invoke_firewall_driver(self, context, firewall, func_name): LOG.debug("_invoke_firewall_driver: %s", func_name) try: if func_name == 'delete_firewall': return_code = self.acl_driver.__getattribute__(func_name)( None, None, firewall) if not return_code: LOG.debug("firewall %s", firewall['id']) self.fw_plugin_rpc.set_firewall_status( context, firewall['id'], constants.ERROR) else: self.fw_plugin_rpc.firewall_deleted( context, firewall['id']) else: return_code, status = self.acl_driver.__getattribute__( func_name)(None, None, firewall) if not return_code: LOG.debug("firewall %s", firewall['id']) self.fw_plugin_rpc.set_firewall_status( context, firewall['id'], constants.ERROR) else: LOG.debug("status %s", status) self.fw_plugin_rpc.set_firewall_status( context, firewall['id'], constants.ACTIVE, status) except Exception: LOG.debug("_invoke_firewall_driver: PRC failure") self.fullsync = True def _process_firewall_pending_op(self, context, firewall_list): for firewall in firewall_list: firewall_status = firewall['status'] if firewall_status == 'PENDING_CREATE': self._invoke_firewall_driver( context, firewall, 'create_firewall') elif firewall_status == 'PENDING_UPDATE': self._invoke_firewall_driver( context, firewall, 'update_firewall') elif firewall_status == 'PENDING_DELETE': self._invoke_firewall_driver( context, firewall, 'delete_firewall') def _process_fullsync(self): LOG.debug("_process_fullsync") try: context = n_context.get_admin_context() tenants = self.fw_plugin_rpc.get_tenants_with_firewalls( context) LOG.debug("tenants with firewall: %s", tenants) for tenant_id in tenants: ctx = n_context.Context('', tenant_id) firewall_list = self.fw_plugin_rpc.get_firewalls_for_tenant( ctx) self._process_firewall_pending_op(ctx, firewall_list) except Exception: LOG.debug("_process_fullsync: RPC failure") self.fullsync = True def _process_devices(self, device_ids): LOG.debug("_process_devices: device_ids %s", device_ids) try: for device_id in device_ids: ctx = n_context.Context('', device_id) firewall_list = self.fw_plugin_rpc.get_firewalls_for_device( ctx) self._process_firewall_pending_op(ctx, firewall_list) except Exception: LOG.debug("_process_devices: RPC failure") self.fullsync = True def _process_event_q(self): while True: try: event_data = self.event_q.dequeue(CSR_FW_EVENT_Q_NAME) if not event_data: return except ValueError: LOG.debug("_process_event_q: no queue yet") return LOG.debug("_process_event_q: event_data %s", event_data) event = event_data['event'] context = event_data['context'] firewall = event_data['firewall'] if event == CSR_FW_EVENT_CREATE: self._invoke_firewall_driver( context, firewall, 'create_firewall') elif event == CSR_FW_EVENT_UPDATE: self._invoke_firewall_driver( context, firewall, 'update_firewall') elif event == CSR_FW_EVENT_DELETE: self._invoke_firewall_driver( context, firewall, 'delete_firewall') else: LOG.error(_LE("invalid event %s"), event) def process_service(self, device_ids=None, removed_devices_info=None): try: if self.fullsync: self.fullsync = False self._process_fullsync() else: if device_ids: self._process_devices(device_ids) if removed_devices_info: LOG.debug("process_service: removed_devices_info %s", removed_devices_info) # do nothing for now else: self._process_event_q() except Exception: LOG.exception(_LE('process_service exception ERROR')) neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/__init__.py0000664000567000056710000000000012701407720027531 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/vyatta/0000775000567000056710000000000012701410073026735 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/vyatta/__init__.py0000664000567000056710000000000012701407720031041 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/vyatta/vyatta_fwaas.py0000664000567000056710000001603412701407720032011 0ustar jenkinsjenkins00000000000000# Copyright 2015 Brocade Communications System, 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. from networking_brocade.vyatta.common import config as vyatta_config from networking_brocade.vyatta.vrouter import client as vyatta_client from neutron import context as neutron_context from novaclient import client as nova_client from oslo_log import log as logging from six.moves.urllib import parse from neutron_fwaas._i18n import _LW from neutron_fwaas.services.firewall.agents.vyatta import vyatta_utils from neutron_fwaas.services.firewall.drivers import fwaas_base LOG = logging.getLogger(__name__) FW_NAME = 'firewall/name/{0}' FW_DESCRIPTION = 'firewall/name/{0}/description/{1}' FW_ESTABLISHED_ACCEPT = 'firewall/state-policy/established/action/accept' FW_RELATED_ACCEPT = 'firewall/state-policy/related/action/accept' FW_RULE_DESCRIPTION = 'firewall/name/{0}/rule/{1}/description/{2}' FW_RULE_PROTOCOL = 'firewall/name/{0}/rule/{1}/protocol/{2}' FW_RULE_SRC_PORT = 'firewall/name/{0}/rule/{1}/source/port/{2}' FW_RULE_DEST_PORT = 'firewall/name/{0}/rule/{1}/destination/port/{2}' FW_RULE_SRC_ADDR = 'firewall/name/{0}/rule/{1}/source/address/{2}' FW_RULE_DEST_ADDR = 'firewall/name/{0}/rule/{1}/destination/address/{2}' FW_RULE_ACTION = 'firewall/name/{0}/rule/{1}/action/{2}' NOVACLIENT_VERSION = '2' class VyattaFirewallDriver(fwaas_base.FwaasDriverBase): def __init__(self): LOG.debug("Vyatta vRouter Fwaas:: Initializing fwaas driver") compute_client = nova_client.Client( NOVACLIENT_VERSION, vyatta_config.VROUTER.tenant_admin_name, vyatta_config.VROUTER.tenant_admin_password, auth_url=vyatta_config.CONF.nova_admin_auth_url, service_type="compute", tenant_id=vyatta_config.VROUTER.tenant_id) self._vyatta_clients_pool = vyatta_client.ClientsPool(compute_client) def create_firewall(self, agent_mode, apply_list, firewall): LOG.debug('Vyatta vRouter Fwaas::Create_firewall (%s)', firewall) return self.update_firewall(agent_mode, apply_list, firewall) def update_firewall(self, agent_mode, apply_list, firewall): LOG.debug('Vyatta vRouter Fwaas::Update_firewall (%s)', firewall) if firewall['admin_state_up']: return self._update_firewall(apply_list, firewall) else: return self.apply_default_policy(agent_mode, apply_list, firewall) def delete_firewall(self, agent_mode, apply_list, firewall): LOG.debug('Vyatta vRouter Fwaas::Delete_firewall (%s)', firewall) return self.apply_default_policy(agent_mode, apply_list, firewall) def apply_default_policy(self, agent_mode, apply_list, firewall): LOG.debug('Vyatta vRouter Fwaas::apply_default_policy (%s)', firewall) for ri in apply_list: self._delete_firewall(ri, firewall) return True def _update_firewall(self, apply_list, firewall): LOG.debug("Updating firewall (%s)", firewall['id']) for ri in apply_list: self._delete_firewall(ri, firewall) self._setup_firewall(ri, firewall) return True def _setup_firewall(self, ri, fw): client = self._get_vyatta_client(ri.router) fw_cmd_list = [] # Create firewall fw_name = vyatta_utils.get_firewall_name(ri, fw) fw_cmd_list.append( vyatta_client.SetCmd( FW_NAME.format(parse.quote_plus(fw_name)))) if fw.get('description'): fw_cmd_list.append(vyatta_client.SetCmd( FW_DESCRIPTION.format( parse.quote_plus(fw_name), parse.quote_plus(fw['description'])))) # Set firewall state policy fw_cmd_list.append(vyatta_client.SetCmd(FW_ESTABLISHED_ACCEPT)) fw_cmd_list.append(vyatta_client.SetCmd(FW_RELATED_ACCEPT)) # Create firewall rules rule_num = 0 for rule in fw['firewall_rule_list']: if not rule['enabled']: continue if rule['ip_version'] == 4: rule_num += 1 fw_cmd_list += self._set_firewall_rule(fw_name, rule_num, rule) else: LOG.warning(_LW("IPv6 rules are not supported.")) # Configure router zones zone_cmd_list = vyatta_utils.get_zone_cmds(client, ri, fw_name) client.exec_cmd_batch(fw_cmd_list + zone_cmd_list) def _delete_firewall(self, ri, fw): client = self._get_vyatta_client(ri.router) cmd_list = [] # Delete zones cmd_list.append(vyatta_client.DeleteCmd("zone-policy")) # Delete firewall fw_name = vyatta_utils.get_firewall_name(ri, fw) cmd_list.append(vyatta_client.DeleteCmd( FW_NAME.format(parse.quote_plus(fw_name)))) # Delete firewall state policy cmd_list.append(vyatta_client.DeleteCmd("firewall/state-policy")) client.exec_cmd_batch(cmd_list) def _set_firewall_rule(self, fw_name, rule_num, rule): cmd_list = [] if 'description' in rule and len(rule['description']) > 0: cmd_list.append(vyatta_client.SetCmd( FW_RULE_DESCRIPTION.format( parse.quote_plus(fw_name), rule_num, parse.quote_plus(rule['description'])))) rules = [ ('protocol', FW_RULE_PROTOCOL), ('source_port', FW_RULE_SRC_PORT), ('destination_port', FW_RULE_DEST_PORT), ('source_ip_address', FW_RULE_SRC_ADDR), ('destination_ip_address', FW_RULE_DEST_ADDR), ] for key, url in rules: field = rule.get(key) if field is None: continue # For safety and extensibility we need to use quote_plus # for all data retrieved from external sources. cmd_list.append(vyatta_client.SetCmd( url.format( parse.quote_plus(fw_name), rule_num, parse.quote_plus(field)))) if 'action' in rule: if rule['action'] == 'allow': action = 'accept' else: action = 'drop' cmd_list.append(vyatta_client.SetCmd( FW_RULE_ACTION.format( parse.quote_plus(fw_name), rule_num, action))) return cmd_list def _get_vyatta_client(self, router): ctx = neutron_context.Context(None, router['tenant_id']) return self._vyatta_clients_pool.get_by_db_lookup(router['id'], ctx) neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/drivers/vyatta/README.rst0000664000567000056710000000054212701407720030432 0ustar jenkinsjenkins00000000000000Brocade Firewall as a Service Driver * For more information, refer to: https://wiki.openstack.org/wiki/Brocade_Vyatta_Firewall_driver * For information on Brocade Vyatta CI, refer to: https://wiki.openstack.org/wiki/ThirdPartySystems/Brocade_Vyatta_CI * Brocade Vyatta CI contact: - DL-GRP-VYATTA-OSS@Brocade.com - vjayara@Brocade.com neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/0000775000567000056710000000000012701410073025230 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/firewall_agent_api.py0000664000567000056710000000466112701407720031432 0ustar jenkinsjenkins00000000000000# 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. from neutron.common import rpc as n_rpc from oslo_config import cfg import oslo_messaging from neutron_fwaas._i18n import _ 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(object): """Agent side of the FWaaS agent to FWaaS Plugin RPC API.""" def __init__(self, topic, host): self.host = host target = oslo_messaging.Target(topic=topic, version='1.0') self.client = n_rpc.get_client(target) def set_firewall_status(self, context, firewall_id, status): """Make a RPC to set the status of a firewall.""" cctxt = self.client.prepare() return cctxt.call(context, 'set_firewall_status', host=self.host, firewall_id=firewall_id, status=status) def firewall_deleted(self, context, firewall_id): """Make a RPC to indicate that the firewall resources are deleted.""" cctxt = self.client.prepare() return cctxt.call(context, 'firewall_deleted', host=self.host, firewall_id=firewall_id) 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 neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/l3reference/0000775000567000056710000000000012701410073027425 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/l3reference/firewall_l3_agent.py0000664000567000056710000004173312701407720033375 0ustar jenkinsjenkins00000000000000# 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. from neutron.agent.linux import ip_lib from neutron import context from neutron.plugins.common import constants as n_const from oslo_config import cfg from oslo_log import helpers as log_helpers from oslo_log import log as logging from neutron_fwaas._i18n import _, _LE from neutron_fwaas.common import fwaas_constants as f_const from neutron_fwaas.extensions import firewall as fw_ext from neutron_fwaas.services.firewall.agents import firewall_agent_api as api from neutron_fwaas.services.firewall.agents import firewall_service 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") cctxt = self.client.prepare() return cctxt.call(context, 'get_firewalls_for_tenant', host=self.host) 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") cctxt = self.client.prepare() return cctxt.call(context, 'get_tenants_with_firewalls', host=self.host) 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 self.fwaas_enabled = cfg.CONF.fwaas.enabled # None means l3-agent has no information on the server # configuration due to the lack of RPC support. if self.neutron_service_plugins is not None: fwaas_plugin_configured = (n_const.FIREWALL in self.neutron_service_plugins) if fwaas_plugin_configured and not self.fwaas_enabled: msg = _("FWaaS plugin is configured in the server side, but " "FWaaS is disabled in L3-agent.") LOG.error(msg) raise SystemExit(1) self.fwaas_enabled = self.fwaas_enabled and fwaas_plugin_configured if self.fwaas_enabled: # NOTE: Temp location for creating service and loading driver self.fw_service = firewall_service.FirewallService() self.fwaas_driver = self.fw_service.load_device_drivers() self.services_sync_needed = False # setup RPC to msg fwaas plugin self.fwplugin_rpc = FWaaSL3PluginApi(f_const.FIREWALL_PLUGIN, conf.host) super(FWaaSL3AgentRpcCallback, self).__init__(host=conf.host) def _has_router_insertion_fields(self, fw): return 'add-router-ids' in fw def _get_router_ids_for_fw(self, context, fw, to_delete=False): """Return the router_ids either from fw dict or tenant routers.""" if self._has_router_insertion_fields(fw): # it is a new version of plugin return (fw['del-router-ids'] if to_delete else fw['add-router-ids']) else: # we are in a upgrade and msg from older version of plugin try: routers = self.plugin_rpc.get_routers(context) except Exception: LOG.exception( _LE("FWaaS RPC failure in _get_router_ids_for_fw " "for firewall: %(fwid)s"), {'fwid': fw['id']}) self.services_sync_needed = True return [ router['id'] for router in routers if router['tenant_id'] == fw['tenant_id']] def _get_router_info_list_for_tenant(self, router_ids, tenant_id): """Returns the list of router info objects on which to apply the fw.""" root_ip = ip_lib.IPWrapper() local_ns_list = root_ip.get_namespaces() 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 router_ns = self.router_info[rid].ns_name if router_ns in local_ns_list: router_info_list.append(self.router_info[rid]) return router_info_list 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'] == n_const.PENDING_DELETE: try: self.fwaas_driver.delete_firewall( self.conf.agent_mode, router_info_list, fw) self.fwplugin_rpc.firewall_deleted( ctx, fw['id']) except fw_ext.FirewallInternalDriverError: LOG.error(_LE("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'], n_const.ERROR) else: # PENDING_UPDATE, PENDING_CREATE, ... try: self.fwaas_driver.update_firewall( self.conf.agent_mode, router_info_list, fw) if fw['admin_state_up']: status = n_const.ACTIVE else: status = n_const.DOWN except fw_ext.FirewallInternalDriverError: LOG.error(_LE("Firewall Driver Error on fw state %(fwmsg)s " "for fw: %(fwid)s"), {'fwmsg': fw['status'], 'fwid': fw['id']}) status = n_const.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']) router_ids = ri.router['id'] router_info_list = self._get_router_info_list_for_tenant( [router_ids], 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) for fw in fw_list: if self._has_router_insertion_fields(fw): # if router extension present apply only if router in fw if (not (router_ids in fw['add-router-ids']) and not (router_ids in fw['del-router-ids'])): continue self._invoke_driver_for_sync_from_plugin( ctx, router_info_list, fw) # router can be present only on one fw return def process_router_add(self, ri): """On router add, get fw with rules from plugin and update driver. Handles agent restart, when a router is added, query the plugin to check if this router is in the router list for any firewall. If so install firewall rules on this router. """ # avoid msg to plugin when fwaas is not configured if not self.fwaas_enabled: return try: # TODO(sridar): as per discussion with pc_m, we may want to hook # this up to the l3 agent observer notification self._process_router_add(ri) except Exception: LOG.exception( _LE("FWaaS RPC info call failed for '%s'."), ri.router['id']) self.services_sync_needed = True def process_services_sync(self, ctx): if not self.services_sync_needed: return """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 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) for fw in fw_list: if fw['status'] == n_const.PENDING_DELETE: self.delete_firewall(ctx, fw, self.host) # no need to apply sync data for ACTIVE fw elif fw['status'] != n_const.ACTIVE: self.update_firewall(ctx, fw, self.host) self.services_sync_needed = False except Exception: LOG.exception(_LE("Failed fwaas process services sync")) self.services_sync_needed = True @log_helpers.log_method_call def create_firewall(self, context, firewall, host): """Handle Rpc from plugin to create a firewall.""" router_ids = self._get_router_ids_for_fw(context, firewall) if not router_ids: return router_info_list = self._get_router_info_list_for_tenant( router_ids, firewall['tenant_id']) LOG.debug("Create: Add firewall on Router List: '%s'", [ri.router['id'] for ri in router_info_list]) # call into the driver try: self.fwaas_driver.create_firewall( self.conf.agent_mode, router_info_list, firewall) if firewall['admin_state_up']: status = n_const.ACTIVE else: status = n_const.DOWN except fw_ext.FirewallInternalDriverError: LOG.error(_LE("Firewall Driver Error for create_firewall " "for firewall: %(fwid)s"), {'fwid': firewall['id']}) status = n_const.ERROR try: # send status back to plugin self.fwplugin_rpc.set_firewall_status( context, firewall['id'], status) except Exception: LOG.exception( _LE("FWaaS RPC failure in create_firewall " "for firewall: %(fwid)s"), {'fwid': firewall['id']}) self.services_sync_needed = True @log_helpers.log_method_call def update_firewall(self, context, firewall, host): """Handle Rpc from plugin to update a firewall.""" status = "" if self._has_router_insertion_fields(firewall): # with the router_ids extension, we may need to delete and add # based on the list of routers. On the older version, we just # update (add) all routers on the tenant - delete not needed. router_ids = self._get_router_ids_for_fw( context, firewall, to_delete=True) if router_ids: router_info_list = self._get_router_info_list_for_tenant( router_ids, firewall['tenant_id']) # remove the firewall from this set of routers # but no ack sent yet, check if we need to add LOG.debug("Update: Delete firewall on Router List: '%s'", [ri.router['id'] for ri in router_info_list]) try: self.fwaas_driver.delete_firewall( self.conf.agent_mode, router_info_list, firewall) if firewall['last-router']: status = n_const.INACTIVE elif firewall['admin_state_up']: status = n_const.ACTIVE else: status = n_const.DOWN except fw_ext.FirewallInternalDriverError: LOG.error(_LE("Firewall Driver Error for " "update_firewall for firewall: " "%(fwid)s"), {'fwid': firewall['id']}) status = n_const.ERROR # handle the add router and/or rule, policy, firewall # attribute updates if status not in (n_const.ERROR, n_const.INACTIVE): router_ids = self._get_router_ids_for_fw(context, firewall) if router_ids or firewall['router_ids']: router_info_list = self._get_router_info_list_for_tenant( router_ids + firewall['router_ids'], firewall['tenant_id']) LOG.debug("Update: Add firewall on Router List: '%s'", [ri.router['id'] for ri in router_info_list]) # call into the driver try: self.fwaas_driver.update_firewall( self.conf.agent_mode, router_info_list, firewall) if firewall['admin_state_up']: status = n_const.ACTIVE else: status = n_const.DOWN except fw_ext.FirewallInternalDriverError: LOG.error(_LE("Firewall Driver Error for " "update_firewall for firewall: " "%(fwid)s"), {'fwid': firewall['id']}) status = n_const.ERROR else: status = n_const.INACTIVE try: # send status back to plugin self.fwplugin_rpc.set_firewall_status( context, firewall['id'], status) except Exception: LOG.exception( _LE("FWaaS RPC failure in update_firewall " "for firewall: %(fwid)s"), {'fwid': firewall['id']}) self.services_sync_needed = True @log_helpers.log_method_call def delete_firewall(self, context, firewall, host): """Handle Rpc from plugin to delete a firewall.""" router_ids = self._get_router_ids_for_fw( context, firewall, to_delete=True) if router_ids: router_info_list = self._get_router_info_list_for_tenant( router_ids, firewall['tenant_id']) LOG.debug( "Delete firewall %(fw)s on routers: '%(routers)s'" % {'fw': firewall['id'], 'routers': [ri.router['id'] for ri in router_info_list]}) # call into the driver try: self.fwaas_driver.delete_firewall( self.conf.agent_mode, router_info_list, firewall) if firewall['admin_state_up']: status = n_const.ACTIVE else: status = n_const.DOWN except fw_ext.FirewallInternalDriverError: LOG.error(_LE("Firewall Driver Error for delete_firewall " "for firewall: %(fwid)s"), {'fwid': firewall['id']}) status = n_const.ERROR try: # send status back to plugin if status in [n_const.ACTIVE, n_const.DOWN]: self.fwplugin_rpc.firewall_deleted(context, firewall['id']) else: self.fwplugin_rpc.set_firewall_status( context, firewall['id'], status) except Exception: LOG.exception( _LE("FWaaS RPC failure in delete_firewall " "for firewall: %(fwid)s"), {'fwid': firewall['id']}) self.services_sync_needed = True neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/l3reference/__init__.py0000664000567000056710000000000012701407720031531 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/varmour/0000775000567000056710000000000012701410073026723 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/varmour/varmour_api.py0000775000567000056710000001141112701407720031627 0ustar jenkinsjenkins00000000000000# 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. import base64 import httplib2 from oslo_config import cfg from oslo_log import log as logging from oslo_serialization import jsonutils from neutron_fwaas._i18n import _, _LE from neutron_fwaas.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 = jsonutils.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': jsonutils.loads(resp_str)} except Exception: LOG.error(_LE('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 neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/varmour/__init__.py0000775000567000056710000000000012701407720031032 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/varmour/varmour_router.py0000775000567000056710000003145412701407720032407 0ustar jenkinsjenkins00000000000000# 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. import sys import eventlet eventlet.monkey_patch() import netaddr from neutron.agent.common import config from neutron.agent.l3 import agent from neutron.agent.l3 import config as l3_config from neutron.agent.l3 import ha from neutron.agent.l3 import router_info 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 import service as neutron_service from neutron_lib import constants as l3_constants from oslo_config import cfg from oslo_log import log as logging from oslo_service import service from neutron_fwaas._i18n import _, _LW from neutron_fwaas.common import fwaas_constants as f_const from neutron_fwaas.services.firewall.agents.l3reference \ import firewall_l3_agent from neutron_fwaas.services.firewall.agents.varmour import varmour_api from neutron_fwaas.services.firewall.agents.varmour \ import varmour_utils as va_utils LOG = logging.getLogger(__name__) class vArmourL3NATAgent(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_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 = router_info.RouterInfo(router_id=router_id, router=router, agent_conf=self.conf, interface_driver=self.driver) 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']) if len(ips) > 1: LOG.warning(_LW("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.warning(_LW("Unable to parse interface mapping.")) return else: LOG.warning(_LW("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, 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, 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=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, agent.L3NATAgentWithStateReport): pass def main(): conf = cfg.CONF conf.register_opts(l3_config.OPTS) conf.register_opts(ha.OPTS) config.register_interface_driver_opts_helper(conf) config.register_agent_state_opts_helper(conf) conf.register_opts(interface.OPTS) conf.register_opts(external_process.OPTS) common_config.init(sys.argv[1:]) config.setup_logging() server = neutron_service.Service.create( binary='neutron-l3-agent', topic=f_const.L3_AGENT, report_interval=cfg.CONF.AGENT.report_interval, manager='neutron_fwaas.services.firewall.agents.varmour.' 'varmour_router.vArmourL3NATAgentWithStateReport') service.launch(conf, server).wait() neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/varmour/varmour_utils.py0000775000567000056710000000406412701407720032224 0ustar jenkinsjenkins00000000000000# 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. 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] neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/__init__.py0000664000567000056710000000000012701407720027334 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/vyatta/0000775000567000056710000000000012701410073026540 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/vyatta/fwaas_agent.py0000664000567000056710000000277212701407720031406 0ustar jenkinsjenkins00000000000000# Copyright 2015 Brocade Communications System, 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. # from networking_brocade.vyatta.common import l3_agent as vyatta_l3 from neutron.agent import l3_agent from neutron_fwaas.services.firewall.agents.vyatta import firewall_service class VyattaFirewallAgent(vyatta_l3.L3AgentMiddleware): """Brocade Neutron Firewall agent for Vyatta vRouter. The base class FWaaSL3AgentRpcCallback of the VyattaFirewallAgent creates the reference FirewallService object that loads the VyattaFirewallDriver class.The VyattaFirewallService class registers callbacks and subscribes to router events. """ def __init__(self, host, conf=None): super(VyattaFirewallAgent, self).__init__(host, conf) self.service = firewall_service.VyattaFirewallService(self) def main(): l3_agent.main( manager='neutron_fwaas.services.firewall.agents.vyatta.' 'fwaas_agent.VyattaFirewallAgent') neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/vyatta/__init__.py0000664000567000056710000000000012701407720030644 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/vyatta/firewall_service.py0000664000567000056710000000426712701407720032455 0ustar jenkinsjenkins00000000000000# Copyright 2015 Brocade Communications System, 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. # from neutron.callbacks import events from neutron.callbacks import registry from neutron.callbacks import resources from neutron import context from oslo_log import log as logging from neutron_fwaas.services.firewall.agents.vyatta import vyatta_utils LOG = logging.getLogger(__name__) class VyattaFirewallService(object): # TODO(vishwanathj): Code to be revised in Liberty release to use # the base class firewall_service.FirewallService for registrations def __init__(self, l3_agent): self.conf = l3_agent.conf registry.subscribe( sync_firewall_zones, resources.ROUTER, events.AFTER_CREATE) registry.subscribe( sync_firewall_zones, resources.ROUTER, events.AFTER_DELETE) registry.subscribe( sync_firewall_zones, resources.ROUTER, events.AFTER_UPDATE) def sync_firewall_zones(resource, event, l3_agent, **kwargs): LOG.debug('VyattaFirewallService:: sync_firewall_zones() called') ri = kwargs['router'] ctx = context.Context(None, ri.router['tenant_id']) client = l3_agent._vyatta_clients_pool.get_by_db_lookup( ri.router['id'], ctx) fw_list = l3_agent.fwplugin_rpc.get_firewalls_for_tenant(ctx) if fw_list: zone_cmds = [] for fw in fw_list: if ri.router['id'] in fw['router_ids']: fw_name = vyatta_utils.get_firewall_name(ri, fw) zone_cmds.extend(vyatta_utils.get_zone_cmds(client, ri, fw_name)) client.exec_cmd_batch(zone_cmds) neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/vyatta/vyatta_utils.py0000775000567000056710000000610712701407720031656 0ustar jenkinsjenkins00000000000000# Copyright 2015 Brocade Communications System, 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. # from networking_brocade.vyatta.vrouter import client as vyatta_client from neutron_lib import constants as l3_constants from six.moves.urllib import parse TRUST_ZONE = 'Internal_Trust' UNTRUST_ZONE = 'External_Untrust' ZONE_INTERFACE_CMD = 'zone-policy/zone/{0}/interface/{1}' ZONE_FIREWALL_CMD = 'zone-policy/zone/{0}/from/{1}/firewall/name/{2}' def get_firewall_name(ri, fw): """Make firewall name for Vyatta vRouter Vyatta vRouter REST API allows firewall name length up to 28 characters. """ return fw['id'].replace('-', '')[:28] def get_trusted_zone_name(ri): return TRUST_ZONE def get_untrusted_zone_name(ri): return UNTRUST_ZONE def get_zone_cmds(rest_api, ri, fw_name): """Return zone update commands for Vyatta vRouter. Commands chain drops all zone-policy zones and create new zones based on internal interfaces and external gateway. """ cmd_list = [] # Delete the zone policies cmd_list.append(vyatta_client.DeleteCmd("zone-policy")) # Configure trusted zone trusted_zone_name = None # Add internal ports to trusted zone if l3_constants.INTERFACE_KEY in ri.router: trusted_zone_name = parse.quote_plus(get_trusted_zone_name(ri)) for port in ri.router[l3_constants.INTERFACE_KEY]: eth_if_id = rest_api.get_ethernet_if_id(port['mac_address']) cmd_list.append(vyatta_client.SetCmd( ZONE_INTERFACE_CMD.format(trusted_zone_name, eth_if_id))) # Configure untrusted zone untrusted_zone_name = get_untrusted_zone_name(ri) if untrusted_zone_name is not None: # Add external ports to untrusted zone if 'gw_port' in ri.router: gw_port = ri.router['gw_port'] eth_if_id = rest_api.get_ethernet_if_id(gw_port['mac_address']) cmd_list.append(vyatta_client.SetCmd( ZONE_INTERFACE_CMD.format(untrusted_zone_name, eth_if_id))) if trusted_zone_name is not None: # Associate firewall to zone cmd_list.append(vyatta_client.SetCmd( ZONE_FIREWALL_CMD.format( trusted_zone_name, untrusted_zone_name, parse.quote_plus(fw_name)))) cmd_list.append(vyatta_client.SetCmd( ZONE_FIREWALL_CMD.format( untrusted_zone_name, trusted_zone_name, parse.quote_plus(fw_name)))) return cmd_list neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/agents/firewall_service.py0000664000567000056710000000314312701407720031135 0ustar jenkinsjenkins00000000000000# Copyright 2014 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. from neutron.services import provider_configuration as provconf from oslo_config import cfg from oslo_log import log as logging from oslo_utils import importutils from neutron_fwaas._i18n import _ LOG = logging.getLogger(__name__) FIREWALL_DRIVERS = 'firewall_drivers' class FirewallService(object): """Firewall Service observer.""" def load_device_drivers(self): """Loads a single device driver for FWaaS.""" device_driver = provconf.get_provider_driver_class( cfg.CONF.fwaas.driver, FIREWALL_DRIVERS) try: driver = importutils.import_object(device_driver) LOG.debug('Loaded FWaaS device driver: %s', device_driver) return driver except ImportError: msg = _('Error importing FWaaS device driver: %s') raise ImportError(msg % device_driver) except ValueError: msg = _('Configuration error - no FWaaS device_driver specified') raise ValueError(msg) neutron-fwaas-8.0.0/neutron_fwaas/services/firewall/fwaas_plugin.py0000664000567000056710000004154112701407720027012 0ustar jenkinsjenkins00000000000000# Copyright 2013 Big Switch 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. from neutron.api.v2 import attributes as attr from neutron.common import rpc as n_rpc from neutron import context as neutron_context from neutron import manager from neutron.plugins.common import constants as n_const from oslo_config import cfg from oslo_log import log as logging import oslo_messaging from neutron_fwaas._i18n import _LW from neutron_fwaas.common import fwaas_constants as f_const from neutron_fwaas.db.firewall import firewall_db from neutron_fwaas.db.firewall import firewall_router_insertion_db from neutron_fwaas.extensions import firewall as fw_ext LOG = logging.getLogger(__name__) class FirewallCallbacks(object): target = oslo_messaging.Target(version='1.0') def __init__(self, plugin): super(FirewallCallbacks, self).__init__() self.plugin = plugin def set_firewall_status(self, context, firewall_id, status, **kwargs): """Agent uses this to set a firewall's status.""" LOG.debug("Setting firewall %s to status: %s" % (firewall_id, status)) # Sanitize status first if status in (n_const.ACTIVE, n_const.DOWN, n_const.INACTIVE): to_update = status else: to_update = n_const.ERROR # ignore changing status if firewall expects to be deleted # That case means that while some pending operation has been # performed on the backend, neutron server received delete request # and changed firewall status to PENDING_DELETE updated = self.plugin.update_firewall_status( context, firewall_id, to_update, not_in=(n_const.PENDING_DELETE,)) if updated: LOG.debug("firewall %s status set: %s" % (firewall_id, to_update)) return updated and to_update != n_const.ERROR def firewall_deleted(self, context, firewall_id, **kwargs): """Agent uses this to indicate firewall is deleted.""" LOG.debug("firewall_deleted() called") with context.session.begin(subtransactions=True): fw_db = self.plugin._get_firewall(context, firewall_id) # allow to delete firewalls in ERROR state if fw_db.status in (n_const.PENDING_DELETE, n_const.ERROR): self.plugin.delete_db_firewall_object(context, firewall_id) return True else: LOG.warning(_LW('Firewall %(fw)s unexpectedly deleted by ' 'agent, status was %(status)s'), {'fw': firewall_id, 'status': fw_db.status}) fw_db.update({"status": n_const.ERROR}) return False def get_firewalls_for_tenant(self, context, **kwargs): """Agent uses this to get all firewalls and rules for a tenant.""" LOG.debug("get_firewalls_for_tenant() called") fw_list = [] for fw in self.plugin.get_firewalls(context): fw_with_rules = self.plugin._make_firewall_dict_with_rules( context, fw['id']) if fw['status'] == n_const.PENDING_DELETE: fw_with_rules['add-router-ids'] = [] fw_with_rules['del-router-ids'] = ( self.plugin.get_firewall_routers(context, fw['id'])) else: fw_with_rules['add-router-ids'] = ( self.plugin.get_firewall_routers(context, fw['id'])) fw_with_rules['del-router-ids'] = [] fw_list.append(fw_with_rules) return fw_list def get_firewalls_for_tenant_without_rules(self, context, **kwargs): """Agent uses this to get all firewalls for a tenant.""" LOG.debug("get_firewalls_for_tenant_without_rules() called") fw_list = [fw for fw in self.plugin.get_firewalls(context)] return fw_list def get_tenants_with_firewalls(self, context, **kwargs): """Agent uses this to get all tenants that have firewalls.""" LOG.debug("get_tenants_with_firewalls() called") ctx = neutron_context.get_admin_context() fw_list = self.plugin.get_firewalls(ctx) fw_tenant_list = list(set(fw['tenant_id'] for fw in fw_list)) return fw_tenant_list class FirewallAgentApi(object): """Plugin side of plugin to agent RPC API.""" def __init__(self, topic, host): self.host = host target = oslo_messaging.Target(topic=topic, version='1.0') self.client = n_rpc.get_client(target) def create_firewall(self, context, firewall): cctxt = self.client.prepare(fanout=True) cctxt.cast(context, 'create_firewall', firewall=firewall, host=self.host) def update_firewall(self, context, firewall): cctxt = self.client.prepare(fanout=True) cctxt.cast(context, 'update_firewall', firewall=firewall, host=self.host) def delete_firewall(self, context, firewall): cctxt = self.client.prepare(fanout=True) cctxt.cast(context, 'delete_firewall', firewall=firewall, host=self.host) class FirewallPlugin( firewall_db.Firewall_db_mixin, firewall_router_insertion_db.FirewallRouterInsertionDbMixin): """Implementation of the Neutron Firewall Service Plugin. This class manages the workflow of FWaaS request/response. Most DB related works are implemented in class firewall_db.Firewall_db_mixin. """ supported_extension_aliases = ["fwaas", "fwaasrouterinsertion"] path_prefix = fw_ext.FIREWALL_PREFIX def __init__(self): """Do the initialization for the firewall service plugin here.""" self.start_rpc_listeners() self.agent_rpc = FirewallAgentApi( f_const.L3_AGENT, cfg.CONF.host ) firewall_db.subscribe() def start_rpc_listeners(self): self.endpoints = [FirewallCallbacks(self)] self.conn = n_rpc.create_connection() self.conn.create_consumer( f_const.FIREWALL_PLUGIN, self.endpoints, fanout=False) return self.conn.consume_in_threads() def _rpc_update_firewall(self, context, firewall_id): status_update = {"firewall": {"status": n_const.PENDING_UPDATE}} super(FirewallPlugin, self).update_firewall(context, firewall_id, status_update) fw_with_rules = self._make_firewall_dict_with_rules(context, firewall_id) # this is triggered on an update to fw rule or policy, no # change in associated routers. fw_with_rules['add-router-ids'] = self.get_firewall_routers( context, firewall_id) fw_with_rules['del-router-ids'] = [] self.agent_rpc.update_firewall(context, fw_with_rules) def _rpc_update_firewall_policy(self, context, firewall_policy_id): firewall_policy = self.get_firewall_policy(context, firewall_policy_id) if firewall_policy: for firewall_id in firewall_policy['firewall_list']: self._rpc_update_firewall(context, firewall_id) def _ensure_update_firewall(self, context, firewall_id): fwall = self.get_firewall(context, firewall_id) if fwall['status'] in [n_const.PENDING_CREATE, n_const.PENDING_UPDATE, n_const.PENDING_DELETE]: raise fw_ext.FirewallInPendingState(firewall_id=firewall_id, pending_state=fwall['status']) def _ensure_update_firewall_policy(self, context, firewall_policy_id): firewall_policy = self.get_firewall_policy(context, firewall_policy_id) if firewall_policy and 'firewall_list' in firewall_policy: for firewall_id in firewall_policy['firewall_list']: self._ensure_update_firewall(context, firewall_id) def _ensure_update_firewall_rule(self, context, firewall_rule_id): fw_rule = self.get_firewall_rule(context, firewall_rule_id) if 'firewall_policy_id' in fw_rule and fw_rule['firewall_policy_id']: self._ensure_update_firewall_policy(context, fw_rule['firewall_policy_id']) def _get_routers_for_create_firewall(self, tenant_id, context, firewall): # pop router_id as this goes in the router association db # and not firewall db router_ids = firewall['firewall'].pop('router_ids', None) if router_ids == attr.ATTR_NOT_SPECIFIED: # old semantics router-ids keyword not specified pick up # all routers on tenant. l3_plugin = manager.NeutronManager.get_service_plugins().get( n_const.L3_ROUTER_NAT) ctx = neutron_context.get_admin_context() routers = l3_plugin.get_routers(ctx) router_ids = [ router['id'] for router in routers if router['tenant_id'] == tenant_id] # validation can still fail this if there is another fw # which is associated with one of these routers. self.validate_firewall_routers_not_in_use(context, router_ids) return router_ids else: if not router_ids: # This indicates that user specifies no routers. return [] else: # some router(s) provided. self.validate_firewall_routers_not_in_use(context, router_ids) return router_ids def create_firewall(self, context, firewall): LOG.debug("create_firewall() called") fw_new_rtrs = self._get_routers_for_create_firewall( firewall['firewall']['tenant_id'], context, firewall) if not fw_new_rtrs: # no messaging to agent needed, and fw needs to go # to INACTIVE(no associated rtrs) state. status = n_const.INACTIVE fw = super(FirewallPlugin, self).create_firewall( context, firewall, status) fw['router_ids'] = [] return fw else: fw = super(FirewallPlugin, self).create_firewall( context, firewall) fw['router_ids'] = fw_new_rtrs fw_with_rules = ( self._make_firewall_dict_with_rules(context, fw['id'])) fw_with_rtrs = {'fw_id': fw['id'], 'router_ids': fw_new_rtrs} self.set_routers_for_firewall(context, fw_with_rtrs) fw_with_rules['add-router-ids'] = fw_new_rtrs fw_with_rules['del-router-ids'] = [] self.agent_rpc.create_firewall(context, fw_with_rules) return fw def update_firewall(self, context, id, firewall): LOG.debug("update_firewall() called on firewall %s", id) self._ensure_update_firewall(context, id) # pop router_id as this goes in the router association db # and not firewall db router_ids = firewall['firewall'].pop('router_ids', None) fw_current_rtrs = self.get_firewall_routers(context, id) if router_ids is not None: if router_ids == []: # This indicates that user is indicating no routers. fw_new_rtrs = [] else: self.validate_firewall_routers_not_in_use( context, router_ids, id) fw_new_rtrs = router_ids self.update_firewall_routers(context, {'fw_id': id, 'router_ids': fw_new_rtrs}) else: # router-ids keyword not specified for update pick up # existing routers. fw_new_rtrs = self.get_firewall_routers(context, id) if not fw_new_rtrs and not fw_current_rtrs: # no messaging to agent needed, and we need to continue # in INACTIVE state firewall['firewall']['status'] = n_const.INACTIVE fw = super(FirewallPlugin, self).update_firewall( context, id, firewall) fw['router_ids'] = [] return fw else: firewall['firewall']['status'] = n_const.PENDING_UPDATE fw = super(FirewallPlugin, self).update_firewall( context, id, firewall) fw['router_ids'] = fw_new_rtrs fw_with_rules = ( self._make_firewall_dict_with_rules(context, fw['id'])) # determine rtrs to add fw to and del from fw_with_rules['add-router-ids'] = fw_new_rtrs fw_with_rules['del-router-ids'] = list( set(fw_current_rtrs).difference(set(fw_new_rtrs))) # last-router drives agent to ack with status to set state to INACTIVE fw_with_rules['last-router'] = not fw_new_rtrs LOG.debug("update_firewall %s: Add Routers: %s, Del Routers: %s", fw['id'], fw_with_rules['add-router-ids'], fw_with_rules['del-router-ids']) self.agent_rpc.update_firewall(context, fw_with_rules) return fw def delete_db_firewall_object(self, context, id): super(FirewallPlugin, self).delete_firewall(context, id) def delete_firewall(self, context, id): LOG.debug("delete_firewall() called on firewall %s", id) fw_with_rules = ( self._make_firewall_dict_with_rules(context, id)) fw_with_rules['del-router-ids'] = self.get_firewall_routers( context, id) fw_with_rules['add-router-ids'] = [] if not fw_with_rules['del-router-ids']: # no routers to delete on the agent side self.delete_db_firewall_object(context, id) else: status = {"firewall": {"status": n_const.PENDING_DELETE}} super(FirewallPlugin, self).update_firewall(context, id, status) # Reflect state change in fw_with_rules fw_with_rules['status'] = status['firewall']['status'] self.agent_rpc.delete_firewall(context, fw_with_rules) def update_firewall_policy(self, context, id, firewall_policy): LOG.debug("update_firewall_policy() called") self._ensure_update_firewall_policy(context, id) fwp = super(FirewallPlugin, self).update_firewall_policy(context, id, firewall_policy) self._rpc_update_firewall_policy(context, id) return fwp def update_firewall_rule(self, context, id, firewall_rule): LOG.debug("update_firewall_rule() called") self._ensure_update_firewall_rule(context, id) fwr = super(FirewallPlugin, self).update_firewall_rule(context, id, firewall_rule) firewall_policy_id = fwr['firewall_policy_id'] if firewall_policy_id: self._rpc_update_firewall_policy(context, firewall_policy_id) return fwr def _notify_firewall_updates(self, context, resource, update_info): notifier = n_rpc.get_notifier('network') notifier.info(context, resource, update_info) def insert_rule(self, context, id, rule_info): LOG.debug("insert_rule() called") self._ensure_update_firewall_policy(context, id) fwp = super(FirewallPlugin, self).insert_rule(context, id, rule_info) self._rpc_update_firewall_policy(context, id) resource = 'firewall_policy.update.insert_rule' self._notify_firewall_updates(context, resource, rule_info) return fwp def remove_rule(self, context, id, rule_info): LOG.debug("remove_rule() called") self._ensure_update_firewall_policy(context, id) fwp = super(FirewallPlugin, self).remove_rule(context, id, rule_info) self._rpc_update_firewall_policy(context, id) resource = 'firewall_policy.update.remove_rule' self._notify_firewall_updates(context, resource, rule_info) return fwp def get_firewalls(self, context, filters=None, fields=None): LOG.debug("fwaas get_firewalls() called") fw_list = super(FirewallPlugin, self).get_firewalls( context, filters, fields) for fw in fw_list: fw_current_rtrs = self.get_firewall_routers(context, fw['id']) fw['router_ids'] = fw_current_rtrs return fw_list def get_firewall(self, context, id, fields=None): LOG.debug("fwaas get_firewall() called") res = super(FirewallPlugin, self).get_firewall( context, id, fields) fw_current_rtrs = self.get_firewall_routers(context, id) res['router_ids'] = fw_current_rtrs return res neutron-fwaas-8.0.0/neutron_fwaas/services/__init__.py0000664000567000056710000000000012701407720024246 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/_i18n.py0000664000567000056710000000252112701407720021614 0ustar jenkinsjenkins00000000000000# 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 oslo_i18n DOMAIN = "neutron_fwaas" _translators = oslo_i18n.TranslatorFactory(domain=DOMAIN) # The primary translation function using the well-known name "_" _ = _translators.primary # The contextual translation function using the name "_C" _C = _translators.contextual_form # The plural translation function using the name "_P" _P = _translators.plural_form # Translators for log levels. # # The abbreviated names are meant to reflect the usual use of a short # name like '_'. The "L" is for "log" and the other letter comes from # the level. _LI = _translators.log_info _LW = _translators.log_warning _LE = _translators.log_error _LC = _translators.log_critical def get_available_languages(): return oslo_i18n.get_available_languages(DOMAIN) neutron-fwaas-8.0.0/neutron_fwaas/extensions/0000775000567000056710000000000012701410073022516 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/extensions/cisco/0000775000567000056710000000000012701410073023616 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/extensions/cisco/__init__.py0000664000567000056710000000000012701407720025722 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/extensions/cisco/csr_firewall_insertion.py0000664000567000056710000000476412701407721030757 0ustar jenkinsjenkins00000000000000# Copyright 2015 Cisco Systems, 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. from neutron.api import extensions from neutron.api.v2 import attributes as attr from neutron.common import exceptions as excp from neutron_fwaas._i18n import _ class InvalidInterfaceForCSRFW(excp.NotFound): message = _("Interface id %(port_id)s provided " "not valid for Cisco CSR Firewall") class InvalidRouterAssociationForCSRFW(excp.InvalidInput): message = _("Port id %(port_id)s provided " "for Cisco CSR Firewall associated with different Router") class InvalidRouterHostingInfoForCSRFW(excp.NotFound): message = _("Interface id %(port_id)s provided " "does not have Hosting Info for Cisco CSR Firewall") csr_firewall_direction = ['inside', 'outside', 'both'] EXTENDED_ATTRIBUTES_2_0 = { 'firewalls': { 'port_id': {'allow_post': True, 'allow_put': True, 'validate': {'type:uuid': None}, 'is_visible': True, 'default': attr.ATTR_NOT_SPECIFIED}, 'direction': {'allow_post': True, 'allow_put': True, 'validate': {'type:values': csr_firewall_direction}, 'is_visible': True, 'default': attr.ATTR_NOT_SPECIFIED}, } } class Csr_firewall_insertion(extensions.ExtensionDescriptor): @classmethod def get_name(cls): return "CSR Firewall insertion" @classmethod def get_alias(cls): return "csrfirewallinsertion" @classmethod def get_description(cls): return "Firewall insertion for Cisco CSR" @classmethod def get_namespace(cls): return ("http://docs.openstack.org/ext/neutron/" "csrfirewallinsertion/api/v1.0") @classmethod def get_updated(cls): return "2014-08-13T10:00:00-00:00" def get_extended_resources(self, version): if version == "2.0": return EXTENDED_ATTRIBUTES_2_0 else: return {} neutron-fwaas-8.0.0/neutron_fwaas/extensions/__init__.py0000664000567000056710000000000012701407720024622 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/extensions/firewallrouterinsertion.py0000664000567000056710000000607212701407721030104 0ustar jenkinsjenkins00000000000000# Copyright 2015 Cisco Systems 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. from neutron.api import extensions from neutron.api.v2 import attributes as attr from neutron.common import exceptions as nexception from neutron_fwaas._i18n import _ class FirewallRouterInUse(nexception.InUse): message = _("Router(s) %(router_ids)s provided already associated with " "other Firewall(s). ") EXTENDED_ATTRIBUTES_2_0 = { 'firewalls': { 'router_ids': {'allow_post': True, 'allow_put': True, 'validate': {'type:uuid_list': None}, 'is_visible': True, 'default': attr.ATTR_NOT_SPECIFIED}, } } class Firewallrouterinsertion(extensions.ExtensionDescriptor): """Extension class supporting Firewall and Router(s) association. The extension enables providing an option to specify router-ids of routers where the firewall is to be installed. This is supported in a manner so that the older version of the API continues to be supported. On a CREATE, if the router_ids option is not specified then the firewall is installed on all routers on the tenant. If the router-ids option is provided with a list of routers then the firewall is installed on the specified routers. If the router-ids option is provided with an empty list then the firewall is created but put in an INACTIVE state to reflect that no routers are associated. This firewall can be updated with a list of routers which will then drive the state to ACTIVE after the agent installs and acks back. UPDATE also supports the option in a similar manner. If the router_ids option is not provided, then there is no change to the existing association with the routers. When the router_is option is provided with a list of routers or an empty list - this drives the new set of routers that the firewall is associated with. """ @classmethod def get_name(cls): return "Firewall Router insertion" @classmethod def get_alias(cls): return "fwaasrouterinsertion" @classmethod def get_description(cls): return "Firewall Router insertion on specified set of routers" @classmethod def get_namespace(cls): return ("http://docs.openstack.org/ext/neutron/fwaasrouterinsertion" "/api/v1.0") @classmethod def get_updated(cls): return "2015-01-27T10:00:00-00:00" def get_extended_resources(self, version): if version == "2.0": return EXTENDED_ATTRIBUTES_2_0 else: return {} neutron-fwaas-8.0.0/neutron_fwaas/extensions/firewall.py0000664000567000056710000004361412701407721024713 0ustar jenkinsjenkins00000000000000# Copyright 2013 Big Switch 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. import abc from neutron.api import extensions from neutron.api.v2 import attributes as attr from neutron.api.v2 import resource_helper from neutron.common import exceptions as nexception from neutron.plugins.common import constants as p_const from neutron.services import service_base from neutron_lib import constants from oslo_config import cfg from oslo_log import log as logging import six from neutron_fwaas._i18n import _ LOG = logging.getLogger(__name__) # Firewall rule action FWAAS_ALLOW = "allow" FWAAS_DENY = "deny" FWAAS_REJECT = "reject" # Firewall resource path prefix FIREWALL_PREFIX = "/fw" # Firewall Exceptions class FirewallNotFound(nexception.NotFound): message = _("Firewall %(firewall_id)s could not be found.") class FirewallInUse(nexception.InUse): message = _("Firewall %(firewall_id)s is still active.") class FirewallInPendingState(nexception.Conflict): message = _("Operation cannot be performed since associated Firewall " "%(firewall_id)s is in %(pending_state)s.") class FirewallPolicyNotFound(nexception.NotFound): message = _("Firewall Policy %(firewall_policy_id)s could not be found.") class FirewallPolicyInUse(nexception.InUse): message = _("Firewall Policy %(firewall_policy_id)s is being used.") class FirewallPolicyConflict(nexception.Conflict): """FWaaS exception for firewall policy Occurs when admin policy tries to use another tenant's unshared policy. """ message = _("Operation cannot be performed since Firewall Policy " "%(firewall_policy_id)s is not shared and does not belong to " "your tenant.") class FirewallRuleSharingConflict(nexception.Conflict): """FWaaS exception for firewall rules When a shared policy is created or updated with unshared rules, this exception will be raised. """ message = _("Operation cannot be performed since Firewall Policy " "%(firewall_policy_id)s is shared but Firewall Rule " "%(firewall_rule_id)s is not shared") class FirewallPolicySharingConflict(nexception.Conflict): """FWaaS exception for firewall policy When a policy is shared without sharing its associated rules, this exception will be raised. """ message = _("Operation cannot be performed. Before sharing Firewall " "Policy %(firewall_policy_id)s, share associated Firewall " "Rule %(firewall_rule_id)s") class FirewallRuleNotFound(nexception.NotFound): message = _("Firewall Rule %(firewall_rule_id)s could not be found.") class FirewallRuleInUse(nexception.InUse): message = _("Firewall Rule %(firewall_rule_id)s is being used.") class FirewallRuleNotAssociatedWithPolicy(nexception.InvalidInput): message = _("Firewall Rule %(firewall_rule_id)s is not associated " " with Firewall Policy %(firewall_policy_id)s.") class FirewallRuleInvalidProtocol(nexception.InvalidInput): message = _("Firewall Rule protocol %(protocol)s is not supported. " "Only protocol values %(values)s and their integer " "representation (0 to 255) are supported.") class FirewallRuleInvalidAction(nexception.InvalidInput): message = _("Firewall rule action %(action)s is not supported. " "Only action values %(values)s are supported.") class FirewallRuleInvalidICMPParameter(nexception.InvalidInput): message = _("%(param)s are not allowed when protocol " "is set to ICMP.") class FirewallRuleWithPortWithoutProtocolInvalid(nexception.InvalidInput): message = _("Source/destination port requires a protocol") class FirewallRuleInvalidPortValue(nexception.InvalidInput): message = _("Invalid value for port %(port)s.") class FirewallRuleInfoMissing(nexception.InvalidInput): message = _("Missing rule info argument for insert/remove " "rule operation.") class FirewallIpAddressConflict(nexception.InvalidInput): message = _("Invalid input - IP addresses do not agree with IP Version") # TODO(dougwig) - once this exception is out of neutron, restore this #class FirewallInternalDriverError(nexception.NeutronException): # """Fwaas exception for all driver errors. # # On any failure or exception in the driver, driver should log it and # raise this exception to the agent # """ # message = _("%(driver)s: Internal driver error.") FirewallInternalDriverError = nexception.FirewallInternalDriverError class FirewallRuleConflict(nexception.Conflict): """Firewall rule conflict exception. Occurs when admin policy tries to use another tenant's unshared rule. """ message = _("Operation cannot be performed since Firewall Rule " "%(firewall_rule_id)s is not shared and belongs to " "another tenant %(tenant_id)s") fw_valid_protocol_values = [None, constants.PROTO_NAME_TCP, constants.PROTO_NAME_UDP, constants.PROTO_NAME_ICMP] fw_valid_action_values = [FWAAS_ALLOW, FWAAS_DENY, FWAAS_REJECT] def convert_protocol(value): if value is None: return if value.isdigit(): val = int(value) if 0 <= val <= 255: return val else: raise FirewallRuleInvalidProtocol( protocol=value, values=fw_valid_protocol_values) elif value.lower() in fw_valid_protocol_values: return value.lower() else: raise FirewallRuleInvalidProtocol( protocol=value, values=fw_valid_protocol_values) def convert_action_to_case_insensitive(value): if value is None: return else: return value.lower() def convert_port_to_string(value): if value is None: return else: return str(value) def _validate_port_range(data, key_specs=None): if data is None: return data = str(data) ports = data.split(':') for p in ports: try: val = int(p) except (ValueError, TypeError): msg = _("Port '%s' is not a valid number") % p LOG.debug(msg) return msg if val <= 0 or val > 65535: msg = _("Invalid port '%s'") % p LOG.debug(msg) return msg def _validate_ip_or_subnet_or_none(data, valid_values=None): if data is None: return None msg_ip = attr._validate_ip_address(data, valid_values) if not msg_ip: return msg_subnet = attr._validate_subnet(data, valid_values) if not msg_subnet: return return _("%(msg_ip)s and %(msg_subnet)s") % {'msg_ip': msg_ip, 'msg_subnet': msg_subnet} attr.validators['type:port_range'] = _validate_port_range attr.validators['type:ip_or_subnet_or_none'] = _validate_ip_or_subnet_or_none RESOURCE_ATTRIBUTE_MAP = { 'firewall_rules': { 'id': {'allow_post': False, 'allow_put': False, 'validate': {'type:uuid': None}, 'is_visible': True, 'primary_key': True}, 'tenant_id': {'allow_post': True, 'allow_put': False, 'required_by_policy': True, 'is_visible': True}, 'name': {'allow_post': True, 'allow_put': True, 'validate': {'type:string': attr.NAME_MAX_LEN}, 'is_visible': True, 'default': ''}, 'description': {'allow_post': True, 'allow_put': True, 'validate': {'type:string': attr.DESCRIPTION_MAX_LEN}, 'is_visible': True, 'default': ''}, 'firewall_policy_id': {'allow_post': False, 'allow_put': False, 'validate': {'type:uuid_or_none': None}, 'is_visible': True}, 'shared': {'allow_post': True, 'allow_put': True, 'default': False, 'convert_to': attr.convert_to_boolean, 'is_visible': True, 'required_by_policy': True, 'enforce_policy': True}, 'protocol': {'allow_post': True, 'allow_put': True, 'is_visible': True, 'default': None, 'convert_to': convert_protocol, 'validate': {'type:values': fw_valid_protocol_values}}, 'ip_version': {'allow_post': True, 'allow_put': True, 'default': 4, 'convert_to': attr.convert_to_int, 'validate': {'type:values': [4, 6]}, 'is_visible': True}, 'source_ip_address': {'allow_post': True, 'allow_put': True, 'validate': {'type:ip_or_subnet_or_none': None}, 'is_visible': True, 'default': None}, 'destination_ip_address': {'allow_post': True, 'allow_put': True, 'validate': {'type:ip_or_subnet_or_none': None}, 'is_visible': True, 'default': None}, 'source_port': {'allow_post': True, 'allow_put': True, 'validate': {'type:port_range': None}, 'convert_to': convert_port_to_string, 'default': None, 'is_visible': True}, 'destination_port': {'allow_post': True, 'allow_put': True, 'validate': {'type:port_range': None}, 'convert_to': convert_port_to_string, 'default': None, 'is_visible': True}, 'position': {'allow_post': False, 'allow_put': False, 'default': None, 'is_visible': True}, 'action': {'allow_post': True, 'allow_put': True, 'convert_to': convert_action_to_case_insensitive, 'validate': {'type:values': fw_valid_action_values}, 'is_visible': True, 'default': 'deny'}, 'enabled': {'allow_post': True, 'allow_put': True, 'default': True, 'convert_to': attr.convert_to_boolean, 'is_visible': True}, }, 'firewall_policies': { 'id': {'allow_post': False, 'allow_put': False, 'validate': {'type:uuid': None}, 'is_visible': True, 'primary_key': True}, 'tenant_id': {'allow_post': True, 'allow_put': False, 'required_by_policy': True, 'is_visible': True}, 'name': {'allow_post': True, 'allow_put': True, 'validate': {'type:string': attr.NAME_MAX_LEN}, 'is_visible': True, 'default': ''}, 'description': {'allow_post': True, 'allow_put': True, 'validate': {'type:string': attr.DESCRIPTION_MAX_LEN}, 'is_visible': True, 'default': ''}, 'shared': {'allow_post': True, 'allow_put': True, 'default': False, 'convert_to': attr.convert_to_boolean, 'is_visible': True, 'required_by_policy': True, 'enforce_policy': True}, 'firewall_rules': {'allow_post': True, 'allow_put': True, 'validate': {'type:uuid_list': None}, 'convert_to': attr.convert_none_to_empty_list, 'default': None, 'is_visible': True}, 'audited': {'allow_post': True, 'allow_put': True, 'default': False, 'convert_to': attr.convert_to_boolean, 'is_visible': True}, }, 'firewalls': { 'id': {'allow_post': False, 'allow_put': False, 'validate': {'type:uuid': None}, 'is_visible': True, 'primary_key': True}, 'tenant_id': {'allow_post': True, 'allow_put': False, 'required_by_policy': True, 'is_visible': True}, 'name': {'allow_post': True, 'allow_put': True, 'validate': {'type:string': attr.NAME_MAX_LEN}, 'is_visible': True, 'default': ''}, 'description': {'allow_post': True, 'allow_put': True, 'validate': {'type:string': attr.DESCRIPTION_MAX_LEN}, 'is_visible': True, 'default': ''}, 'admin_state_up': {'allow_post': True, 'allow_put': True, 'default': True, 'convert_to': attr.convert_to_boolean, 'is_visible': True}, 'status': {'allow_post': False, 'allow_put': False, 'is_visible': True}, 'shared': {'allow_post': True, 'allow_put': True, 'default': False, 'convert_to': attr.convert_to_boolean, 'is_visible': False, 'required_by_policy': True, 'enforce_policy': True}, 'firewall_policy_id': {'allow_post': True, 'allow_put': True, 'validate': {'type:uuid_or_none': None}, 'is_visible': True}, }, } # A tenant may have a unique firewall and policy for each router # when router insertion is used. # Set default quotas to align with default l3 quota_router of 10 # though keep as separately controllable. firewall_quota_opts = [ cfg.IntOpt('quota_firewall', default=10, help=_('Number of firewalls allowed per tenant. ' 'A negative value means unlimited.')), cfg.IntOpt('quota_firewall_policy', default=10, help=_('Number of firewall policies allowed per tenant. ' 'A negative value means unlimited.')), cfg.IntOpt('quota_firewall_rule', default=100, help=_('Number of firewall rules allowed per tenant. ' 'A negative value means unlimited.')), ] cfg.CONF.register_opts(firewall_quota_opts, 'QUOTAS') class Firewall(extensions.ExtensionDescriptor): @classmethod def get_name(cls): return "Firewall service" @classmethod def get_alias(cls): return "fwaas" @classmethod def get_description(cls): return "Extension for Firewall service" @classmethod def get_namespace(cls): return "http://wiki.openstack.org/Neutron/FWaaS/API_1.0" @classmethod def get_updated(cls): return "2013-02-25T10:00:00-00:00" @classmethod def get_resources(cls): special_mappings = {'firewall_policies': 'firewall_policy'} plural_mappings = resource_helper.build_plural_mappings( special_mappings, RESOURCE_ATTRIBUTE_MAP) attr.PLURALS.update(plural_mappings) action_map = {'firewall_policy': {'insert_rule': 'PUT', 'remove_rule': 'PUT'}} return resource_helper.build_resource_info(plural_mappings, RESOURCE_ATTRIBUTE_MAP, p_const.FIREWALL, action_map=action_map, register_quota=True) @classmethod def get_plugin_interface(cls): return FirewallPluginBase def update_attributes_map(self, attributes): super(Firewall, self).update_attributes_map( attributes, extension_attrs_map=RESOURCE_ATTRIBUTE_MAP) def get_extended_resources(self, version): if version == "2.0": return RESOURCE_ATTRIBUTE_MAP else: return {} @six.add_metaclass(abc.ABCMeta) class FirewallPluginBase(service_base.ServicePluginBase): def get_plugin_name(self): return p_const.FIREWALL def get_plugin_type(self): return p_const.FIREWALL def get_plugin_description(self): return 'Firewall service plugin' @abc.abstractmethod def get_firewalls(self, context, filters=None, fields=None): pass @abc.abstractmethod def get_firewall(self, context, id, fields=None): pass @abc.abstractmethod def create_firewall(self, context, firewall): pass @abc.abstractmethod def update_firewall(self, context, id, firewall): pass @abc.abstractmethod def delete_firewall(self, context, id): pass @abc.abstractmethod def get_firewall_rules(self, context, filters=None, fields=None): pass @abc.abstractmethod def get_firewall_rule(self, context, id, fields=None): pass @abc.abstractmethod def create_firewall_rule(self, context, firewall_rule): pass @abc.abstractmethod def update_firewall_rule(self, context, id, firewall_rule): pass @abc.abstractmethod def delete_firewall_rule(self, context, id): pass @abc.abstractmethod def get_firewall_policy(self, context, id, fields=None): pass @abc.abstractmethod def get_firewall_policies(self, context, filters=None, fields=None): pass @abc.abstractmethod def create_firewall_policy(self, context, firewall_policy): pass @abc.abstractmethod def update_firewall_policy(self, context, id, firewall_policy): pass @abc.abstractmethod def delete_firewall_policy(self, context, id): pass @abc.abstractmethod def insert_rule(self, context, id, rule_info): pass @abc.abstractmethod def remove_rule(self, context, id, rule_info): pass neutron-fwaas-8.0.0/neutron_fwaas/common/0000775000567000056710000000000012701410073021607 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/common/__init__.py0000664000567000056710000000000012701407720023713 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/common/fwaas_constants.py0000664000567000056710000000131712701407720025365 0ustar jenkinsjenkins00000000000000# Copyright 2015 Cisco Systems, 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. # Constants for "topics" FIREWALL_PLUGIN = 'q-firewall-plugin' L3_AGENT = 'l3_agent' neutron-fwaas-8.0.0/neutron_fwaas/version.py0000664000567000056710000000126412701407720022366 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation # # 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 pbr.version version_info = pbr.version.VersionInfo('neutron-fwaas') neutron-fwaas-8.0.0/neutron_fwaas/db/0000775000567000056710000000000012701410073020704 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/firewall/0000775000567000056710000000000012701410073022511 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/firewall/__init__.py0000664000567000056710000000000012701407720024615 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/firewall/firewall_router_insertion_db.py0000664000567000056710000000751112701407720031040 0ustar jenkinsjenkins00000000000000# Copyright 2015 Cisco Systems 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. from neutron.db import model_base from oslo_log import helpers as log_helpers from oslo_log import log as logging import sqlalchemy as sa from neutron_fwaas.extensions import firewallrouterinsertion as fwrtrins LOG = logging.getLogger(__name__) class FirewallRouterAssociation(model_base.BASEV2): """Tracks FW Router Association""" __tablename__ = 'firewall_router_associations' fw_id = sa.Column(sa.String(36), sa.ForeignKey('firewalls.id', ondelete="CASCADE"), primary_key=True) router_id = sa.Column(sa.String(36), sa.ForeignKey('routers.id', ondelete="CASCADE"), primary_key=True) class FirewallRouterInsertionDbMixin(object): """Access methods for the firewall_router_associations table.""" @log_helpers.log_method_call def set_routers_for_firewall(self, context, fw): """Sets the routers associated with the fw.""" with context.session.begin(subtransactions=True): for r_id in fw['router_ids']: fw_rtr_db = FirewallRouterAssociation(fw_id=fw['fw_id'], router_id=r_id) context.session.add(fw_rtr_db) @log_helpers.log_method_call def get_firewall_routers(self, context, fwid): """Gets all routers associated with a firewall.""" with context.session.begin(subtransactions=True): fw_rtr_qry = context.session.query( FirewallRouterAssociation.router_id) fw_rtr_rows = fw_rtr_qry.filter_by(fw_id=fwid) fw_rtrs = [entry.router_id for entry in fw_rtr_rows] LOG.debug("get_firewall_routers(): fw_rtrs: %s", fw_rtrs) return fw_rtrs @log_helpers.log_method_call def validate_firewall_routers_not_in_use( self, context, router_ids, fwid=None): """Validate if router-ids not associated with any firewall. If any of the router-ids in the list is already associated with a firewall, raise an exception else just return. """ fw_rtr_qry = context.session.query(FirewallRouterAssociation.router_id) fw_rtrs = fw_rtr_qry.filter( FirewallRouterAssociation.router_id.in_(router_ids), FirewallRouterAssociation.fw_id != fwid).all() if fw_rtrs: router_ids = [entry.router_id for entry in fw_rtrs] raise fwrtrins.FirewallRouterInUse(router_ids=router_ids) @log_helpers.log_method_call def update_firewall_routers(self, context, fw): """Update the firewall with new routers. This involves removing existing router associations and replacing it with the new router associations provided in the update method. """ with context.session.begin(subtransactions=True): fw_rtr_qry = context.session.query(FirewallRouterAssociation) fw_rtr_qry.filter_by(fw_id=fw['fw_id']).delete() if fw['router_ids']: self.set_routers_for_firewall(context, fw) # TODO(sridar): Investigate potential corner case if rpc failure # happens on PENDING_UPDATE and agent did not restart. Evaluate # complexity vs benefit of holding on to old entries until ack # from agent. return fw neutron-fwaas-8.0.0/neutron_fwaas/db/firewall/firewall_db.py0000664000567000056710000007230012701407720025344 0ustar jenkinsjenkins00000000000000# Copyright 2013 Big Switch 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. from neutron.callbacks import events from neutron.callbacks import registry from neutron.callbacks import resources from neutron.db import common_db_mixin as base_db from neutron.db import model_base from neutron.db import models_v2 from neutron.extensions import l3 from neutron import manager from neutron.plugins.common import constants as p_const from neutron_lib import constants from oslo_config import cfg from oslo_log import log as logging from oslo_utils import uuidutils import sqlalchemy as sa from sqlalchemy.ext.orderinglist import ordering_list from sqlalchemy import orm from sqlalchemy.orm import exc import netaddr from neutron_fwaas.extensions import firewall as fw_ext LOG = logging.getLogger(__name__) class FirewallRule(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant): """Represents a Firewall rule.""" __tablename__ = 'firewall_rules' __table_args__ = ({'mysql_collate': 'utf8_bin'}) name = sa.Column(sa.String(255)) description = sa.Column(sa.String(1024)) firewall_policy_id = sa.Column(sa.String(36), sa.ForeignKey('firewall_policies.id'), nullable=True) shared = sa.Column(sa.Boolean) protocol = sa.Column(sa.String(40)) ip_version = sa.Column(sa.Integer, nullable=False) source_ip_address = sa.Column(sa.String(46)) destination_ip_address = sa.Column(sa.String(46)) source_port_range_min = sa.Column(sa.Integer) source_port_range_max = sa.Column(sa.Integer) destination_port_range_min = sa.Column(sa.Integer) destination_port_range_max = sa.Column(sa.Integer) action = sa.Column(sa.Enum('allow', 'deny', 'reject', name='firewallrules_action')) enabled = sa.Column(sa.Boolean) position = sa.Column(sa.Integer) class Firewall(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant): """Represents a Firewall resource.""" __tablename__ = 'firewalls' __table_args__ = ({'mysql_collate': 'utf8_bin'}) name = sa.Column(sa.String(255)) description = sa.Column(sa.String(1024)) shared = sa.Column(sa.Boolean) admin_state_up = sa.Column(sa.Boolean) status = sa.Column(sa.String(16)) firewall_policy_id = sa.Column(sa.String(36), sa.ForeignKey('firewall_policies.id'), nullable=True) class FirewallPolicy(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant): """Represents a Firewall Policy resource.""" __tablename__ = 'firewall_policies' __table_args__ = ({'mysql_collate': 'utf8_bin'}) name = sa.Column(sa.String(255)) description = sa.Column(sa.String(1024)) shared = sa.Column(sa.Boolean) firewall_rules = orm.relationship( FirewallRule, backref=orm.backref('firewall_policies', cascade='all, delete'), order_by='FirewallRule.position', collection_class=ordering_list('position', count_from=1)) audited = sa.Column(sa.Boolean) firewalls = orm.relationship(Firewall, backref='firewall_policies') class Firewall_db_mixin(fw_ext.FirewallPluginBase, base_db.CommonDbMixin): """Mixin class for Firewall DB implementation.""" @property def _core_plugin(self): return manager.NeutronManager.get_plugin() def _get_firewall(self, context, id): try: return self._get_by_id(context, Firewall, id) except exc.NoResultFound: raise fw_ext.FirewallNotFound(firewall_id=id) def _get_firewall_policy(self, context, id): try: return self._get_by_id(context, FirewallPolicy, id) except exc.NoResultFound: raise fw_ext.FirewallPolicyNotFound(firewall_policy_id=id) def _get_firewall_rule(self, context, id): try: return self._get_by_id(context, FirewallRule, id) except exc.NoResultFound: raise fw_ext.FirewallRuleNotFound(firewall_rule_id=id) def _make_firewall_dict(self, fw, fields=None): res = {'id': fw['id'], 'tenant_id': fw['tenant_id'], 'name': fw['name'], 'description': fw['description'], 'shared': fw['shared'], 'admin_state_up': fw['admin_state_up'], 'status': fw['status'], 'firewall_policy_id': fw['firewall_policy_id']} return self._fields(res, fields) def _make_firewall_policy_dict(self, firewall_policy, fields=None): fw_rules = [rule['id'] for rule in firewall_policy['firewall_rules']] firewalls = [fw['id'] for fw in firewall_policy['firewalls']] res = {'id': firewall_policy['id'], 'tenant_id': firewall_policy['tenant_id'], 'name': firewall_policy['name'], 'description': firewall_policy['description'], 'shared': firewall_policy['shared'], 'audited': firewall_policy['audited'], 'firewall_rules': fw_rules, 'firewall_list': firewalls} return self._fields(res, fields) def _make_firewall_rule_dict(self, firewall_rule, fields=None): position = None # We return the position only if the firewall_rule is bound to a # firewall_policy. if firewall_rule['firewall_policy_id']: position = firewall_rule['position'] src_port_range = self._get_port_range_from_min_max_ports( firewall_rule['source_port_range_min'], firewall_rule['source_port_range_max']) dst_port_range = self._get_port_range_from_min_max_ports( firewall_rule['destination_port_range_min'], firewall_rule['destination_port_range_max']) res = {'id': firewall_rule['id'], 'tenant_id': firewall_rule['tenant_id'], 'name': firewall_rule['name'], 'description': firewall_rule['description'], 'firewall_policy_id': firewall_rule['firewall_policy_id'], 'shared': firewall_rule['shared'], 'protocol': firewall_rule['protocol'], 'ip_version': firewall_rule['ip_version'], 'source_ip_address': firewall_rule['source_ip_address'], 'destination_ip_address': firewall_rule['destination_ip_address'], 'source_port': src_port_range, 'destination_port': dst_port_range, 'action': firewall_rule['action'], 'position': position, 'enabled': firewall_rule['enabled']} return self._fields(res, fields) def _make_firewall_dict_with_rules(self, context, firewall_id): firewall = self.get_firewall(context, firewall_id) fw_policy_id = firewall['firewall_policy_id'] if fw_policy_id: fw_policy = self.get_firewall_policy(context, fw_policy_id) fw_rules_list = [self.get_firewall_rule( context, rule_id) for rule_id in fw_policy['firewall_rules']] firewall['firewall_rule_list'] = fw_rules_list else: firewall['firewall_rule_list'] = [] # FIXME(Sumit): If the size of the firewall object we are creating # here exceeds the largest message size supported by rabbit/qpid # then we will have a problem. return firewall def _check_firewall_rule_conflict(self, fwr_db, fwp_db): if not fwr_db['shared']: if fwr_db['tenant_id'] != fwp_db['tenant_id']: raise fw_ext.FirewallRuleConflict( firewall_rule_id=fwr_db['id'], tenant_id=fwr_db['tenant_id']) def _set_rules_for_policy(self, context, firewall_policy_db, fwp): rule_id_list = fwp['firewall_rules'] fwp_db = firewall_policy_db with context.session.begin(subtransactions=True): if not rule_id_list: fwp_db.firewall_rules = [] fwp_db.audited = False return # We will first check if the new list of rules is valid filters = {'id': [r_id for r_id in rule_id_list]} rules_in_db = self._get_collection_query(context, FirewallRule, filters=filters) rules_dict = dict((fwr_db['id'], fwr_db) for fwr_db in rules_in_db) for fwrule_id in rule_id_list: if fwrule_id not in rules_dict: # If we find an invalid rule in the list we # do not perform the update since this breaks # the integrity of this list. raise fw_ext.FirewallRuleNotFound( firewall_rule_id=fwrule_id) elif rules_dict[fwrule_id]['firewall_policy_id']: if (rules_dict[fwrule_id]['firewall_policy_id'] != fwp_db['id']): raise fw_ext.FirewallRuleInUse( firewall_rule_id=fwrule_id) if 'shared' in fwp: if fwp['shared'] and not rules_dict[fwrule_id]['shared']: raise fw_ext.FirewallRuleSharingConflict( firewall_rule_id=fwrule_id, firewall_policy_id=fwp_db['id']) elif fwp_db['shared'] and not rules_dict[fwrule_id]['shared']: raise fw_ext.FirewallRuleSharingConflict( firewall_rule_id=fwrule_id, firewall_policy_id=fwp_db['id']) for fwr_db in rules_in_db: self._check_firewall_rule_conflict(fwr_db, fwp_db) # New list of rules is valid so we will first reset the existing # list and then add each rule in order. # Note that the list could be empty in which case we interpret # it as clearing existing rules. fwp_db.firewall_rules = [] for fwrule_id in rule_id_list: fwp_db.firewall_rules.append(rules_dict[fwrule_id]) fwp_db.firewall_rules.reorder() fwp_db.audited = False def _check_unshared_rules_for_policy(self, fwp_db, fwp): if fwp['shared']: rules_in_db = fwp_db['firewall_rules'] for fwr_db in rules_in_db: if not fwr_db['shared']: raise fw_ext.FirewallPolicySharingConflict( firewall_rule_id=fwr_db['id'], firewall_policy_id=fwp_db['id']) def _process_rule_for_policy(self, context, firewall_policy_id, firewall_rule_db, position): with context.session.begin(subtransactions=True): fwp_query = context.session.query( FirewallPolicy).with_lockmode('update') fwp_db = fwp_query.filter_by(id=firewall_policy_id).one() if position: # Note that although position numbering starts at 1, # internal ordering of the list starts at 0, so we compensate. fwp_db.firewall_rules.insert(position - 1, firewall_rule_db) else: fwp_db.firewall_rules.remove(firewall_rule_db) fwp_db.firewall_rules.reorder() fwp_db.audited = False return self._make_firewall_policy_dict(fwp_db) def _get_min_max_ports_from_range(self, port_range): if not port_range: return [None, None] min_port, sep, max_port = port_range.partition(":") if not max_port: max_port = min_port self._validate_fwr_port_range(min_port, max_port) return [int(min_port), int(max_port)] def _get_port_range_from_min_max_ports(self, min_port, max_port): if not min_port: return None if min_port == max_port: return str(min_port) self._validate_fwr_port_range(min_port, max_port) return '%s:%s' % (min_port, max_port) def _validate_fw_parameters(self, context, fw, fw_tenant_id): if 'firewall_policy_id' not in fw: return fwp_id = fw['firewall_policy_id'] fwp = self._get_firewall_policy(context, fwp_id) if fw_tenant_id != fwp['tenant_id'] and not fwp['shared']: raise fw_ext.FirewallPolicyConflict(firewall_policy_id=fwp_id) def _validate_fwr_src_dst_ip_version(self, fwr): src_version = dst_version = None if fwr['source_ip_address']: src_version = netaddr.IPNetwork(fwr['source_ip_address']).version if fwr['destination_ip_address']: dst_version = netaddr.IPNetwork( fwr['destination_ip_address']).version rule_ip_version = fwr['ip_version'] if ((src_version and src_version != rule_ip_version) or (dst_version and dst_version != rule_ip_version)): raise fw_ext.FirewallIpAddressConflict() def _validate_fwr_port_range(self, min_port, max_port): if int(min_port) > int(max_port): port_range = '%s:%s' % (min_port, max_port) raise fw_ext.FirewallRuleInvalidPortValue(port=port_range) def _validate_fwr_protocol_parameters(self, fwr): protocol = fwr['protocol'] if protocol not in (constants.PROTO_NAME_TCP, constants.PROTO_NAME_UDP): if fwr['source_port'] or fwr['destination_port']: raise fw_ext.FirewallRuleInvalidICMPParameter( param="Source, destination port") def create_firewall(self, context, firewall, status=None): LOG.debug("create_firewall() called") fw = firewall['firewall'] tenant_id = fw['tenant_id'] # distributed routers may required a more complex state machine; # the introduction of a new 'CREATED' state allows this, whilst # keeping a backward compatible behavior of the logical resource. if not status: status = (p_const.CREATED if cfg.CONF.router_distributed else p_const.PENDING_CREATE) with context.session.begin(subtransactions=True): self._validate_fw_parameters(context, fw, tenant_id) firewall_db = Firewall( id=uuidutils.generate_uuid(), tenant_id=tenant_id, name=fw['name'], description=fw['description'], firewall_policy_id=fw['firewall_policy_id'], admin_state_up=fw['admin_state_up'], status=status) context.session.add(firewall_db) return self._make_firewall_dict(firewall_db) def update_firewall(self, context, id, firewall): LOG.debug("update_firewall() called") fw = firewall['firewall'] with context.session.begin(subtransactions=True): fw_db = self.get_firewall(context, id) self._validate_fw_parameters(context, fw, fw_db['tenant_id']) count = context.session.query(Firewall).filter_by(id=id).update(fw) if not count: raise fw_ext.FirewallNotFound(firewall_id=id) return self.get_firewall(context, id) def update_firewall_status(self, context, id, status, not_in=None): """Conditionally update firewall status. Status transition is performed only if firewall is not in the specified states as defined by 'not_in' list. """ # filter in_ wants iterable objects, None isn't. not_in = not_in or [] with context.session.begin(subtransactions=True): return (context.session.query(Firewall). filter(Firewall.id == id). filter(~Firewall.status.in_(not_in)). update({'status': status}, synchronize_session=False)) def delete_firewall(self, context, id): LOG.debug("delete_firewall() called") with context.session.begin(subtransactions=True): # Note: Plugin should ensure that it's okay to delete if the # firewall is active count = context.session.query(Firewall).filter_by(id=id).delete() if not count: raise fw_ext.FirewallNotFound(firewall_id=id) def get_firewall(self, context, id, fields=None): LOG.debug("get_firewall() called") fw = self._get_firewall(context, id) return self._make_firewall_dict(fw, fields) def get_firewalls(self, context, filters=None, fields=None): LOG.debug("get_firewalls() called") return self._get_collection(context, Firewall, self._make_firewall_dict, filters=filters, fields=fields) def get_firewalls_count(self, context, filters=None): LOG.debug("get_firewalls_count() called") return self._get_collection_count(context, Firewall, filters=filters) def create_firewall_policy(self, context, firewall_policy): LOG.debug("create_firewall_policy() called") fwp = firewall_policy['firewall_policy'] with context.session.begin(subtransactions=True): fwp_db = FirewallPolicy(id=uuidutils.generate_uuid(), tenant_id=fwp['tenant_id'], name=fwp['name'], description=fwp['description'], shared=fwp['shared']) context.session.add(fwp_db) self._set_rules_for_policy(context, fwp_db, fwp) fwp_db.audited = fwp['audited'] return self._make_firewall_policy_dict(fwp_db) def update_firewall_policy(self, context, id, firewall_policy): LOG.debug("update_firewall_policy() called") fwp = firewall_policy['firewall_policy'] with context.session.begin(subtransactions=True): fwp_db = self._get_firewall_policy(context, id) # check tenant ids are same for fw and fwp or not if not fwp.get('shared', True) and fwp_db.firewalls: for fw in fwp_db['firewalls']: if fwp_db['tenant_id'] != fw['tenant_id']: raise fw_ext.FirewallPolicyInUse( firewall_policy_id=id) # check any existing rules are not shared if 'shared' in fwp and 'firewall_rules' not in fwp: self._check_unshared_rules_for_policy(fwp_db, fwp) elif 'firewall_rules' in fwp: self._set_rules_for_policy(context, fwp_db, fwp) del fwp['firewall_rules'] if 'audited' not in fwp: fwp['audited'] = False fwp_db.update(fwp) return self._make_firewall_policy_dict(fwp_db) def delete_firewall_policy(self, context, id): LOG.debug("delete_firewall_policy() called") with context.session.begin(subtransactions=True): fwp = self._get_firewall_policy(context, id) # Ensure that the firewall_policy is not # being used qry = context.session.query(Firewall) if qry.filter_by(firewall_policy_id=id).first(): raise fw_ext.FirewallPolicyInUse(firewall_policy_id=id) else: context.session.delete(fwp) def get_firewall_policy(self, context, id, fields=None): LOG.debug("get_firewall_policy() called") fwp = self._get_firewall_policy(context, id) return self._make_firewall_policy_dict(fwp, fields) def get_firewall_policies(self, context, filters=None, fields=None): LOG.debug("get_firewall_policies() called") return self._get_collection(context, FirewallPolicy, self._make_firewall_policy_dict, filters=filters, fields=fields) def get_firewalls_policies_count(self, context, filters=None): LOG.debug("get_firewall_policies_count() called") return self._get_collection_count(context, FirewallPolicy, filters=filters) def create_firewall_rule(self, context, firewall_rule): LOG.debug("create_firewall_rule() called") fwr = firewall_rule['firewall_rule'] self._validate_fwr_protocol_parameters(fwr) self._validate_fwr_src_dst_ip_version(fwr) if not fwr['protocol'] and (fwr['source_port'] or fwr['destination_port']): raise fw_ext.FirewallRuleWithPortWithoutProtocolInvalid() src_port_min, src_port_max = self._get_min_max_ports_from_range( fwr['source_port']) dst_port_min, dst_port_max = self._get_min_max_ports_from_range( fwr['destination_port']) with context.session.begin(subtransactions=True): fwr_db = FirewallRule( id=uuidutils.generate_uuid(), tenant_id=fwr['tenant_id'], name=fwr['name'], description=fwr['description'], shared=fwr['shared'], protocol=fwr['protocol'], ip_version=fwr['ip_version'], source_ip_address=fwr['source_ip_address'], destination_ip_address=fwr['destination_ip_address'], source_port_range_min=src_port_min, source_port_range_max=src_port_max, destination_port_range_min=dst_port_min, destination_port_range_max=dst_port_max, action=fwr['action'], enabled=fwr['enabled']) context.session.add(fwr_db) return self._make_firewall_rule_dict(fwr_db) def update_firewall_rule(self, context, id, firewall_rule): LOG.debug("update_firewall_rule() called") fwr = firewall_rule['firewall_rule'] fwr_db = self._get_firewall_rule(context, id) if fwr_db.firewall_policy_id: fwp_db = self._get_firewall_policy(context, fwr_db.firewall_policy_id) if 'shared' in fwr and not fwr['shared']: if fwr_db['tenant_id'] != fwp_db['tenant_id']: raise fw_ext.FirewallRuleInUse(firewall_rule_id=id) if 'source_port' in fwr: src_port_min, src_port_max = self._get_min_max_ports_from_range( fwr['source_port']) fwr['source_port_range_min'] = src_port_min fwr['source_port_range_max'] = src_port_max del fwr['source_port'] if 'destination_port' in fwr: dst_port_min, dst_port_max = self._get_min_max_ports_from_range( fwr['destination_port']) fwr['destination_port_range_min'] = dst_port_min fwr['destination_port_range_max'] = dst_port_max del fwr['destination_port'] with context.session.begin(subtransactions=True): protocol = fwr.get('protocol', fwr_db['protocol']) if not protocol: sport = fwr.get('source_port_range_min', fwr_db['source_port_range_min']) dport = fwr.get('destination_port_range_min', fwr_db['destination_port_range_min']) if sport or dport: raise fw_ext.FirewallRuleWithPortWithoutProtocolInvalid() fwr_db.update(fwr) if fwr_db.firewall_policy_id: fwp_db.audited = False return self._make_firewall_rule_dict(fwr_db) def delete_firewall_rule(self, context, id): LOG.debug("delete_firewall_rule() called") with context.session.begin(subtransactions=True): fwr = self._get_firewall_rule(context, id) if fwr.firewall_policy_id: raise fw_ext.FirewallRuleInUse(firewall_rule_id=id) context.session.delete(fwr) def get_firewall_rule(self, context, id, fields=None): LOG.debug("get_firewall_rule() called") fwr = self._get_firewall_rule(context, id) return self._make_firewall_rule_dict(fwr, fields) def get_firewall_rules(self, context, filters=None, fields=None): LOG.debug("get_firewall_rules() called") return self._get_collection(context, FirewallRule, self._make_firewall_rule_dict, filters=filters, fields=fields) def get_firewalls_rules_count(self, context, filters=None): LOG.debug("get_firewall_rules_count() called") return self._get_collection_count(context, FirewallRule, filters=filters) def _validate_insert_remove_rule_request(self, id, rule_info): if not rule_info or 'firewall_rule_id' not in rule_info: raise fw_ext.FirewallRuleInfoMissing() def insert_rule(self, context, id, rule_info): LOG.debug("insert_rule() called") self._validate_insert_remove_rule_request(id, rule_info) firewall_rule_id = rule_info['firewall_rule_id'] insert_before = True ref_firewall_rule_id = None if not firewall_rule_id: raise fw_ext.FirewallRuleNotFound(firewall_rule_id=None) if 'insert_before' in rule_info: ref_firewall_rule_id = rule_info['insert_before'] if not ref_firewall_rule_id and 'insert_after' in rule_info: # If insert_before is set, we will ignore insert_after. ref_firewall_rule_id = rule_info['insert_after'] insert_before = False with context.session.begin(subtransactions=True): fwr_db = self._get_firewall_rule(context, firewall_rule_id) fwp_db = self._get_firewall_policy(context, id) if fwr_db.firewall_policy_id: raise fw_ext.FirewallRuleInUse(firewall_rule_id=fwr_db['id']) self._check_firewall_rule_conflict(fwr_db, fwp_db) if ref_firewall_rule_id: # If reference_firewall_rule_id is set, the new rule # is inserted depending on the value of insert_before. # If insert_before is set, the new rule is inserted before # reference_firewall_rule_id, and if it is not set the new # rule is inserted after reference_firewall_rule_id. ref_fwr_db = self._get_firewall_rule( context, ref_firewall_rule_id) if ref_fwr_db.firewall_policy_id != id: raise fw_ext.FirewallRuleNotAssociatedWithPolicy( firewall_rule_id=ref_fwr_db['id'], firewall_policy_id=id) if insert_before: position = ref_fwr_db.position else: position = ref_fwr_db.position + 1 else: # If reference_firewall_rule_id is not set, it is assumed # that the new rule needs to be inserted at the top. # insert_before field is ignored. # So default insertion is always at the top. # Also note that position numbering starts at 1. position = 1 return self._process_rule_for_policy(context, id, fwr_db, position) def remove_rule(self, context, id, rule_info): LOG.debug("remove_rule() called") self._validate_insert_remove_rule_request(id, rule_info) firewall_rule_id = rule_info['firewall_rule_id'] if not firewall_rule_id: raise fw_ext.FirewallRuleNotFound(firewall_rule_id=None) with context.session.begin(subtransactions=True): fwr_db = self._get_firewall_rule(context, firewall_rule_id) if fwr_db.firewall_policy_id != id: raise fw_ext.FirewallRuleNotAssociatedWithPolicy( firewall_rule_id=fwr_db['id'], firewall_policy_id=id) return self._process_rule_for_policy(context, id, fwr_db, None) def migration_callback(resource, event, trigger, **kwargs): context = kwargs['context'] router = kwargs['router'] fw_plugin = manager.NeutronManager.get_service_plugins().get( p_const.FIREWALL) if fw_plugin: tenant_firewalls = fw_plugin.get_firewalls( context, filters={'tenant_id': [router['tenant_id']]}) if tenant_firewalls: raise l3.RouterInUse(router_id=router['id']) def subscribe(): registry.subscribe( migration_callback, resources.ROUTER, events.BEFORE_UPDATE) # NOTE(armax): multiple FW service plugins (potentially out of tree) may # inherit from firewall_db and may need the callbacks to be processed. Having # an implicit subscription (through the module import) preserves the existing # behavior, and at the same time it avoids fixing it manually in each and # every fw plugin out there. That said, The subscription is also made # explicitly in the reference fw plugin. The subscription operation is # idempotent so there is no harm in registering the same callback multiple # times. subscribe() neutron-fwaas-8.0.0/neutron_fwaas/db/cisco/0000775000567000056710000000000012701410073022004 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/cisco/cisco_fwaas_db.py0000664000567000056710000000465612701407720025324 0ustar jenkinsjenkins00000000000000# Copyright 2015 Cisco Systems, Inc. # # 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. from neutron.db import model_base from oslo_log import helpers as log_helpers import sqlalchemy as sa class CiscoFirewallAssociation(model_base.BASEV2): """Represents FW association with CSR interface and attributes""" __tablename__ = 'cisco_firewall_associations' fw_id = sa.Column(sa.String(36), sa.ForeignKey('firewalls.id', ondelete="CASCADE"), primary_key=True) port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id', ondelete="CASCADE")) direction = sa.Column(sa.String(16)) acl_id = sa.Column(sa.String(36)) router_id = sa.Column(sa.String(36)) class CiscoFirewall_db_mixin(object): @log_helpers.log_method_call def add_firewall_csr_association(self, context, fw): with context.session.begin(subtransactions=True): firewall_db = CiscoFirewallAssociation(fw_id=fw['id'], port_id=fw['port_id'], direction=fw['direction'], acl_id=fw['acl_id'], router_id=fw['router_id']) context.session.add(firewall_db) @log_helpers.log_method_call def lookup_firewall_csr_association(self, context, fwid): with context.session.begin(subtransactions=True): csr_fw_qry = context.session.query(CiscoFirewallAssociation) csr_fw = csr_fw_qry.filter_by(fw_id=fwid).first() return csr_fw @log_helpers.log_method_call def update_firewall_csr_association(self, context, fwid, firewall): with context.session.begin(subtransactions=True): csr_fw_qry = context.session.query(CiscoFirewallAssociation) csr_fw = csr_fw_qry.filter_by(fw_id=fwid).first() csr_fw.update(firewall) return firewall neutron-fwaas-8.0.0/neutron_fwaas/db/cisco/__init__.py0000664000567000056710000000000012701407720024110 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/__init__.py0000664000567000056710000000000012701407720023010 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/0000775000567000056710000000000012701410073022675 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/__init__.py0000664000567000056710000000000012701407720025001 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/0000775000567000056710000000000012701410073026525 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/README0000664000567000056710000000004612701407720027412 0ustar jenkinsjenkins00000000000000Generic single-database configuration.neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/env.py0000664000567000056710000000465512701407720027706 0ustar jenkinsjenkins00000000000000# Copyright 2014 OpenStack Foundation # # 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. from logging import config as logging_config from alembic import context from neutron.db import model_base from oslo_config import cfg from oslo_db.sqlalchemy import session import sqlalchemy as sa from sqlalchemy import event MYSQL_ENGINE = None FWAAS_VERSION_TABLE = 'alembic_version_fwaas' config = context.config neutron_config = config.neutron_config logging_config.fileConfig(config.config_file_name) target_metadata = model_base.BASEV2.metadata def set_mysql_engine(): try: mysql_engine = neutron_config.command.mysql_engine except cfg.NoSuchOptError: mysql_engine = None global MYSQL_ENGINE MYSQL_ENGINE = (mysql_engine or model_base.BASEV2.__table_args__['mysql_engine']) def run_migrations_offline(): set_mysql_engine() kwargs = dict() if neutron_config.database.connection: kwargs['url'] = neutron_config.database.connection else: kwargs['dialect_name'] = neutron_config.database.engine kwargs['version_table'] = FWAAS_VERSION_TABLE context.configure(**kwargs) with context.begin_transaction(): context.run_migrations() @event.listens_for(sa.Table, 'after_parent_attach') def set_storage_engine(target, parent): if MYSQL_ENGINE: target.kwargs['mysql_engine'] = MYSQL_ENGINE def run_migrations_online(): set_mysql_engine() engine = session.create_engine(neutron_config.database.connection) connection = engine.connect() context.configure( connection=connection, target_metadata=target_metadata, version_table=FWAAS_VERSION_TABLE ) try: with context.begin_transaction(): context.run_migrations() finally: connection.close() engine.dispose() if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online() neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/0000775000567000056710000000000012701410073030375 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/kilo_release.py0000664000567000056710000000151212701407720033411 0ustar jenkinsjenkins00000000000000# 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. # """kilo Revision ID: kilo Revises: 796c68dffbb Create Date: 2015-04-16 00:00:00.000000 """ # revision identifiers, used by Alembic. revision = 'kilo' down_revision = '796c68dffbb' def upgrade(): """A no-op migration for marking the Kilo release.""" pass neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/mitaka/0000775000567000056710000000000012701410073031643 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/mitaka/contract/0000775000567000056710000000000012701410073033460 5ustar jenkinsjenkins00000000000000././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/mitaka/contract/458aa42b14b_fw_table_alter.pyneutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/mitaka/contract/458aa42b10000664000567000056710000000256212701407720034630 0ustar jenkinsjenkins00000000000000#Copyright 2015 OpenStack Foundation # # 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. # """fw_table_alter script to make column case sensitive Revision ID: 458aa42b14b Revises: 67c8e8d61d5 Create Date: 2015-09-16 11:47:43.061649 """ from alembic import op from neutron.db import migration # revision identifiers, used by Alembic. revision = '458aa42b14b' down_revision = '67c8e8d61d5' # milestone identifier, used by neutron-db-manage neutron_milestone = [migration.MITAKA] FW_TAB_NAME = ['firewall_rules', 'firewall_policies', 'firewalls'] SQL_STATEMENT_UPDATE_CMD = ( "alter table %s " "modify name varchar(255) " "CHARACTER SET utf8 COLLATE utf8_bin" ) def upgrade(): context = op.get_context() if context.bind.dialect.name == 'mysql': for table in FW_TAB_NAME: op.execute(SQL_STATEMENT_UPDATE_CMD % table) ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/796c68dffbb_cisco_csr_fwaas.pyneutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/796c68dffbb_cisco_csr_fwa0000664000567000056710000000301212701407720035037 0ustar jenkinsjenkins00000000000000# Copyright 2015 OpenStack Foundation # # 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. # """cisco_csr_fwaas Revision ID: 796c68dffbb Revises: 540142f314f4 Create Date: 2015-02-02 13:11:55.184112 """ # revision identifiers, used by Alembic. revision = '796c68dffbb' down_revision = '540142f314f4' from alembic import op import sqlalchemy as sa def upgrade(active_plugins=None, options=None): op.create_table('cisco_firewall_associations', sa.Column('fw_id', sa.String(length=36), nullable=False), sa.Column('port_id', sa.String(length=36), nullable=True), sa.Column('direction', sa.String(length=16), nullable=True), sa.Column('acl_id', sa.String(length=36), nullable=True), sa.Column('router_id', sa.String(length=36), nullable=True), sa.ForeignKeyConstraint(['fw_id'], ['firewalls.id'], ondelete='CASCADE'), sa.ForeignKeyConstraint(['port_id'], ['ports.id'], ondelete='CASCADE'), sa.PrimaryKeyConstraint('fw_id') ) neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/CONTRACT_HEAD0000664000567000056710000000001412701407720032316 0ustar jenkinsjenkins00000000000000458aa42b14b neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/start_neutron_fwaas.py0000664000567000056710000000153312701407720035046 0ustar jenkinsjenkins00000000000000# Copyright 2014 OpenStack Foundation # # 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. # """start neutron-fwaas chain Revision ID: start_neutron_fwaas Revises: None Create Date: 2014-12-09 18:42:08.262632 """ # revision identifiers, used by Alembic. revision = 'start_neutron_fwaas' down_revision = None def upgrade(): pass neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/EXPAND_HEAD0000664000567000056710000000001512701407720032061 0ustar jenkinsjenkins000000000000004b47ea298795 neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/0000775000567000056710000000000012701410073032047 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/contract/0000775000567000056710000000000012701410073033664 5ustar jenkinsjenkins00000000000000././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/contract/67c8e8d61d5_initial.pyneutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/contract/67c8e8d60000664000567000056710000000202312701407720034767 0ustar jenkinsjenkins00000000000000# Copyright 2015 Red Hat Inc. # # 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. # """Initial Liberty no-op script. Revision ID: 67c8e8d61d5 Revises: kilo Create Date: 2015-07-28 22:18:13.330846 """ from neutron.db import migration from neutron.db.migration import cli # revision identifiers, used by Alembic. revision = '67c8e8d61d5' down_revision = 'kilo' branch_labels = (cli.CONTRACT_BRANCH,) # milestone identifier, used by neutron-db-manage neutron_milestone = [migration.LIBERTY] def upgrade(): pass neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/0000775000567000056710000000000012701410073033326 5ustar jenkinsjenkins00000000000000././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/c40fbb377ad_initial.pyneutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/c40fbb377a0000664000567000056710000000162512701407720034724 0ustar jenkinsjenkins00000000000000# Copyright 2015 Red Hat Inc. # # 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. # """Initial Liberty no-op script. Revision ID: c40fbb377ad Revises: kilo Create Date: 2015-07-28 22:18:13.321233 """ from neutron.db.migration import cli # revision identifiers, used by Alembic. revision = 'c40fbb377ad' down_revision = 'kilo' branch_labels = (cli.EXPAND_BRANCH,) def upgrade(): pass ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/4b47ea298795_add_reject_rule.pyneutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/4b47ea29870000664000567000056710000000225312701407720034600 0ustar jenkinsjenkins00000000000000# Copyright 2015 NEC Corporation. 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. """add reject rule Revision ID: 4b47ea298795 Revises: c40fbb377ad Create Date: 2015-04-15 04:19:57.324584 """ from alembic import op import sqlalchemy as sa from neutron.db import migration # revision identifiers, used by Alembic. revision = '4b47ea298795' down_revision = 'c40fbb377ad' # milestone identifier, used by neutron-db-manage neutron_milestone = [migration.LIBERTY, migration.MITAKA] new_action = sa.Enum('allow', 'deny', 'reject', name='firewallrules_action') def upgrade(): op.alter_column('firewall_rules', 'action', type_=new_action) ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/540142f314f4_fwaas_router_insertion.pyneutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/540142f314f4_fwaas_router0000664000567000056710000000304212701407720034474 0ustar jenkinsjenkins00000000000000# Copyright 2014 OpenStack Foundation # # 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. # """FWaaS router insertion Revision ID: 540142f314f4 Revises: 4202e3047e47 Create Date: 2015-02-06 17:02:24.279337 """ # revision identifiers, used by Alembic. revision = '540142f314f4' down_revision = '4202e3047e47' from alembic import op import sqlalchemy as sa SQL_STATEMENT = ( "insert into firewall_router_associations " "select " "f.id as fw_id, r.id as router_id " "from firewalls f, routers r " "where " "f.tenant_id=r.tenant_id" ) def upgrade(): op.create_table('firewall_router_associations', sa.Column('fw_id', sa.String(length=36), nullable=False), sa.Column('router_id', sa.String(length=36), nullable=False), sa.ForeignKeyConstraint(['fw_id'], ['firewalls.id'], ondelete='CASCADE'), sa.ForeignKeyConstraint(['router_id'], ['routers.id'], ondelete='CASCADE'), sa.PrimaryKeyConstraint('fw_id', 'router_id'), ) op.execute(SQL_STATEMENT) ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/4202e3047e47_add_index_tenant_id.pyneutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/versions/4202e3047e47_add_index_te0000664000567000056710000000210312701407720034402 0ustar jenkinsjenkins00000000000000# Copyright 2015 OpenStack Foundation # # 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. # """add_index_tenant_id Revision ID: 4202e3047e47 Revises: start_neutron_fwaas Create Date: 2015-02-10 17:17:47.846764 """ # revision identifiers, used by Alembic. revision = '4202e3047e47' down_revision = 'start_neutron_fwaas' from alembic import op TABLES = ['firewall_rules', 'firewalls', 'firewall_policies'] def upgrade(): for table in TABLES: op.create_index(op.f('ix_%s_tenant_id' % table), table, ['tenant_id'], unique=False) neutron-fwaas-8.0.0/neutron_fwaas/db/migration/alembic_migrations/script.py.mako0000664000567000056710000000203512701407720031336 0ustar jenkinsjenkins00000000000000# Copyright ${create_date.year} # # 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. # """${message} Revision ID: ${up_revision} Revises: ${down_revision} Create Date: ${create_date} """ # revision identifiers, used by Alembic. revision = ${repr(up_revision)} down_revision = ${repr(down_revision)} % if branch_labels: branch_labels = ${repr(branch_labels)} %endif from alembic import op import sqlalchemy as sa ${imports if imports else ""} def upgrade(): ${upgrades if upgrades else "pass"} neutron-fwaas-8.0.0/LICENSE0000664000567000056710000002363712701407720016471 0ustar jenkinsjenkins00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. neutron-fwaas-8.0.0/ChangeLog0000664000567000056710000011452212701410072017222 0ustar jenkinsjenkins00000000000000CHANGES ======= 8.0.0 ----- * Constraint requirements using mitaka upper-constraints.txt file 8.0.0.0rc2 ---------- * Update .gitreview for stable/mitaka 8.0.0.0rc1 ---------- * Use routers client instead of networks client * Use tempest.lib base module for network * Updated from global requirements * Make all tox targets constrained * Tag the alembic migration revisions for Mitaka 8.0.0.0b3 --------- * FWaaS: make use of neutron_lib constants * Use tempest.lib instead of tempest-lib * Track alembic heads * Remove unused pngmath Sphinx extension * Fixed typo in subunit-trace.py * Updated from global requirements * Select the right DB to store user and data in each backend * Modify tox.ini to run dsvm-functional tests * Updated from global requirements * delete meaningless braces in log * Updated from global requirements * Cleanup i18n module usages * tempest: Confirm the opposite direction * tempest: Fix a few test cases * FWaaS quota registration * Add testresources to neutron-fwaas test requirements * Fix neutron-fwaas cover tests * Send Notifications for Firewall policy updates * Set testenv env for api and scenario testing * tempest: Skips router insertion tests if public_router_id is configured * tempest: Update for NetworkClient * Add an explicit BRANCH_NAME to tox_install.sh * Update translation setup * tempest: Add a comment * Updated from global requirements * tempest: Remove an extra comma, which breaks the following assertion * Add unittest of convert_action_to_case_insensitive * Updated from global requirements 8.0.0.0b2 --------- * Clean up removed hacking rule from [flake8] ignore lists * tempest: Add test cases for router insertion * Replace deprecated library function os.popen() with subprocess * Add unit test for convert_protocol * Updated from global requirements * Change LOG.warn to LOG.warning * LOG.warn -> LOG.warning * Trival: Remove unused logging import * tempest: Update after the recent tempest change * Updated from global requirements * Avoid duplicating tenant check when creating resources * Fix a typo from UPPER_CONTRAINTS_FILE to UPPER_CONSTRAINTS_FILE * Setup for translation * Deprecated tox -downloadcache option removed * Remove Neutron FWaaS static example configuration files * Updated from global requirements * Added constraints tox targets * Automatically generate neutron FWaaS configuration files * Adapt to the recent tempest * Delete python bytecode before every test run * Updated from global requirements * Remove dependency on neutron for topics * Add reno for release notes management * Fix db error when running python34 Unit tests * Remove version from setup.cfg 8.0.0.0b1 --------- * Fix TempestPlugin to fix gate failure * Freescale FWaaS Plugin code final decomposition * Updated from global requirements * Add some more tempest scenarios * Updated from global requirements * Set ZUUL_BRANCH using BRANCH if not available * Move api tests from Neutron repository * Revert "Register FWaaS resources to quota engine" * Remove deprecated use_namespaces option * Prepare neutron "use_namespaces" option removal * Update list of modules supporting py34 tests * FWaaS fix comment typos * Updated from global requirements * Updated from global requirements * Add tempest scenario tests * Updated from global requirements * Removed new=True argument from create_connection * Include alembic versions directory to the package * Register FWaaS resources to quota engine * Updated from global requirements * Validate src_ip_adress, dest_ip_address and ip_version * Updated from global requirements * Use assert(Not)In instead of assertTrue/False * use assertIs(Not)None instead of assert(Not)Equal * use assertFalse instead of assertEqual(False, ***) * Fix argument order for assertEqual to (expected, observed) * Case-Sensitivity for name column in fw table 7.0.0 ----- * Tag the alembic migration revisions for Liberty * Tag the alembic migration revisions for Liberty * Consume FWaaS plugin queue in RPC workers * Kill HEADS file * Stop doing any magic cloning of neutron during CI * Use stable/liberty branch for neutron dep 7.0.0.0rc1 ---------- * Update defaultbranch in .gitreview to stable/liberty * Open Mitaka development * Change ignore-errors to ignore_errors * Updated from global requirements * Fix check_migration error * Added +x permission to gate hook scripts * py34 support for fwaas 7.0.0.0b3 --------- * Updated from global requirements * Updated from global requirements * Removing unused dependency: discover * Kill contention between update and delete * FWaaS: Fix 500 INTERNAL error on too long name or description * Adopt the migration chaining and branch names from neutron * Switch to using os-testr's copy of subunit2html * Cisco CSR FWaaS driver should use 'l4-options' in CSR RESTAPI call * Updated from global requirements * Add REJECT rule on Neutron FWaaS * Make tests/unit/extensions discoverable * Updated from global requirements * Reduce contention between update and delete * Add oslotest dependency to test-requirements * Updated from global requirements * Validate tenant_id between firewall and firewall-policy * Do not make delete_db_firewall conditional * Updated from global requirements * switch to multi branch migration tree for liberty * py34: Enable initial python34 testing for FWaaS * Killed existing downgrade rules in migration scripts 7.0.0.0b2 --------- * script.py.mako: update to latest standards * py34: Fix usage of gettext.install * Register alembic_migrations at install time * Updated from global requirements * Remove quantum untracked files from .gitignore * Fix wrong argument name in _rpc_update_firewall * Use oslo_log.helpers.log_method_call * Updated from global requirements * Fix UT failures during firewall mock plugin setup * COMMON_PREFIXES cleanup - patch 3/5 * Updated from global requirements * Switch to oslo.service 7.0.0.0b1 --------- * Updated from global requirements * Switch to oslo_utils.uuidutils * Fixes firewall going to error state on an update * Trim some unused test packages * Update version for Liberty * Updated from global requirements * Add handle for protocol value "any" in CSR1kv driver 7.0.0a0 ------- * Updated from global requirements * Revert "Insert tenant_id validation for fw and fw-policy" * Updated from global requirements * Python 3: use six.iteritems instead of dict.items * Enable random hash seeds * Do not assume jsonutils.dumps ordering * Updated from global requirements * Add validation of port_range for firewall-rule * Remove contextlib.nested from tests * vendor code should refer to Brocade * Updated from global requirements * Make iptables firewall work with L3 plugin without DVR support * Updated from global requirements * Insert tenant_id validation for fw and fw-policy 2015.1.0 -------- * Insert validation in creating/updating firewall * update .gitreview for stable/kilo * Updated Protocol named constants * Add Kilo release milestone * Add Kilo release milestone * Pin neutron to stable/kilo * Restore Brocade Vyatta firewall functionality * FWaaS: Remove check for bash usage * Restore Brocade Vyatta firewall functionality * Switch from neutron.common.log.log to oslo_log.helpers.log_method_call * logic error in updating audited of firewall policy 2015.1.0rc1 ----------- * FWaaS: Reorganize unit test tree * Open Liberty development * Updated Protocol named constants * FWaaS: Refactor callback mechanism * Use BaseSudoTestCase instead of BaseLinuxTestCase * Remove reference to testlib_plugin * Updated from global requirements 2015.1.0b3 ---------- * Adding mandatory parameters for Router Info in vArmour fwaas agent * tests: stop overwriting neutron BaseTestCase configuration files * Refactoring related to 'FWaaS insertion Model on Routers' * Adds FWaaS driver for Cisco CSR1kv * Adds FWaaS service plugin for Cisco CSR1kv * FWaaS Insertion Model on Routers * Decouple L3 and Firewall during DVR router migration * Implementation of Mcafee NGFW Driver * Provide hooks for FWaaS repo functional gate * Updated from global requirements * Fix for breaking UTs when creating RouterInfo * Add the missing parameter agent_mode to the FWaaSDriverBase class methods * Add the prefix networking_brocade to import paths * Pick up missing neutron to neuton_fwaas change * Removed lockutils-wrapper from tox targets * Migrate to oslo.log * Change L3 agent AdvancedService class to be non-singleton * Updated from global requirements * Enable removing references to self.services_sync in l3 agent * Stop storing and passing root_helper * Fix pylint error due to novaclient v1_1/v2 rename * Add index on tenant_id * FWaaS: Enable coverage testing * Remove unused _destroy_router_namespaces() * Implementation of Brocade Vyatta Firewall driver * Pass root_helper to ip_lib by keyword argument to prep for removal * Fixed tests to use neutron_fwaas extensions and neutrons * oslo: migrate to namespace-less import paths 2015.1.0b2 ---------- * Code cleanup for Freescale FWaaS Plugin * Updated from global requirements * Move extensions to service repo * Fix neutron-fwaas unit test failures due to multiple issues * Move '_make_firewall_dict_with_rules' to firewall_db.py * Freescale FWaaS Plugin * Updated from global requirements * Updated from global requirements * Updated from global requirements * Migrate to oslo.concurrency * Adjust fwaas unit tests to work with quotas enabled * Updated from global requirements * Update hacking to 0.10 * Fix the neutron-fwaas unit test failures * Updated from global requirements * FWaaS: L3 Agent restructure - observer hierarchy * Cleaned up requirements.txt * Bump from global requirements * Fix gitignore of egg files properly * Do not list neutron in requirements.txt * Re-enable UT for neutron-fwaas for services split * Backward compatibility for fwaas * Update documentation files for FWaaS 2015.1.0b1 ---------- * Kill oslo-incubator files * Move classes out of l3_agent.py * Delete accidentally committed egg files * Fix python path to neutron_fwaas module * Init of separate alembic chain * Fix python path in ini file * After the services split, get neutron-fwaas Jenkins jobs passing * Fix git review target for repo * Split fwaas services code into neutron-fwaas * Workflow documentation is now in infra-manual * tox.ini: Prevent casual addition of bash dependency * Updated from global requirements * Get rid of py26 references: OrderedDict, httplib, xml testing * Updated the README.rst * pretty_tox.sh: Portablity improvement * test_dhcp_agent: Fix no-op tests * Enable undefined-loop-variable pylint check * Fix incorrect exception order in _execute_request * Migrate to oslo.i18n * Migrate to oslo.middleware * Migrate to oslo.utils * Remove Python 2.6 classifier * Remove ryu plugin * Updated from global requirements * Fix AttributeError in RPC code for DVR * Show progress output while running unit tests * Enforce log hints in neutron.services.firewall * enable H401 hacking check * enable H237 check * Updated from global requirements * Drop RpcProxy usage from FWaaS code * Drop several uses of RpcCallback * Enable default SNAT from networks connected to a router indirectly * Updated from global requirements * Update i18n translation for neutron.db log msg's * Update i18n translation for neutron.agents log msg's * enable F812 check for flake8 * enable F811 check for flake8 * Support pudb as a different post mortem debugger * switch to oslo.serialization * Add rootwrap filters for ofagent * Remove useless return * Remove openvswitch core plugin entry point * Updated from global requirements * Purge use of "PRED and A or B" poor-mans-ternary * Remove duplicate ensure_remove_chain method in iptables_manager * Remove use_namespaces from RouterInfo Property * Updated from global requirements * Remove XML support * enable F402 check for flake8 * enable E713 in pep8 tests * Hyper-V: Remove useless use of "else" clause on for loop * Enable no-name-in-module pylint check * Updated from global requirements * Remove duplicate import of constants module * Switch run-time import to using importutils.import_module * Enable assignment-from-no-return pylint check * tox.ini: Avoid using bash where unnecessary * Empty files should not contain copyright or license * Remove single occurrence of lost-exception warning * Updated fileutils and its dependencies * remove E251 exemption from pep8 check * mock.assert_called_once() is not a valid method * Add pylint tox environment and disable all existing warnings * Updated from global requirements * Ignore top-level hidden dirs/files by default * Avoid constructing a RouterInfo object to get namespace name * Drop sslutils and versionutils modules * Removed kombu from requirements * Updated from global requirements * Updated from global requirements * Remove sslutils from openstack.common * remove linuxbridge plugin * Open Kilo development * Implement ModelsMigrationsSync test from oslo.db * Disallow unsharing used firewall policy * Fix entrypoint of OneConvergencePlugin plugin * Stop admin using other tenants unshared rules * Set dsvm-functional job to use system packages * Separate Configuration from Freescale SDN ML2 mechanism Driver * Remove @author(s) from copyright statements * Add HA support to the l3 agent * Updated from global requirements * Adds ipset support for Security Groups * Remove useless check in _rpc_update_firewall * Don't allow user to set firewall rule with port and no protocol * Changes to support FWaaS in a DVR based environment * Add requests_mock to test-requirements.txt * Removed kombu from requirements * Supply missing cisco_cfg_agent.ini file * Remove unused arg to config.setup_logging() * Updated from global requirements * shared policy shouldn't have unshared rules * Work toward Python 3.4 support and testing * Revert "Cisco DFA ML2 Mechanism Driver" * Remove SELECT FOR UPDATE use in delete_firewall * Big Switch: Separate L3 functions into L3 service * Remove reference to cisco_cfg_agent.ini from setup.cfg again * Adds router service plugin for CSR1kv * Support for extensions in ML2 * Cisco DFA ML2 Mechanism Driver * Adding mechanism driver in ML2 plugin for Nuage Networks * Fix state_path in tests * Remove ovs dependency in embrane plugin * Use lockutils module for tox functional env * Remove SELECT FOR UPDATE use in update_firewall * Prefer "val !=/== ref" over "val (not) in [ref]" in conditions * Remove status initialization from plugin's create_firewall * Set firewall state to CREATED when dealing with DVR * Updated from global requirements * Add specific docs build option to tox * Fix bigswitch setup.cfg lines * Remove auto-generation of db schema from models at startup * Skip FWaaS config mismatch check if RPC method is unsupported * Updated from global requirements * Use jsonutils instead of stdlib json * Remove INACTIVE status from FWaaS * Preserve link local IP allocations for DVR fip ns across restart * Opencontrail plug-in implementation for core resources * Return 403 instead of 404 on attr policy failures * Proper validation for inserting firewall rule * Remove redundant topic from rpc calls * Add a tox test environment for random hashseed testing * Updated from global requirements * Move from Python logging to Openstack logging * Remove reference to cisco_cfg_agent.ini from setup.cfg * Exit Firewall Agent if config is invalid * Removed configobj from test requirements * Updated from global requirements * Functional tests work fine with random PYTHONHASHSEED * Set python hash seed to 0 in tox.ini * Configuration agent for Cisco devices * Updated from global requirements * ML2 mechanism driver for SR-IOV capable NIC based switching, Part 2 * Audited attribute for policy update not changing * This patch changes the name of directory from mech_arista to arista * ML2 mechanism driver for SR-IOV capable NIC based switching, Part 1 * Allow to import _LC, _LE, _LI and _LW functions directly * Make readme reference git.openstack.org not github * Bump hacking to version 0.9.2 * Use auth_token from keystonemiddleware * Change all occurences of no_delete to do_delete * Extract CommonDBMixin to a separate file * Remove reference to setuptools_git * Add a gate-specific tox env for functional tests * Add CONTRIBUTING.rst * Updated from global requirements * Updated from global requirements * Updated from global requirements * Fix example for running individual tests * Switch to using of oslo.db * remove unsupported middleware * Add config for performance gate job * Synced log module and its dependencies from olso-incubator * don't ignore rules that are already enforced * Moved rpc_compat.py code back into rpc.py * Updated from global requirements * Updated from global requirements * ofagent: move main module from ryu repository * Remove the useless vim modelines * Removed 'rpc' and 'notifier' incubator modules * Removed create_rpc_dispatcher methods * Use openstack.common.lockutils module for locks in tox functional tests * Renamed consume_in_thread -> consume_in_threads * Port to oslo.messaging * Updated from global requirements * Ignore emacs checkpoint files * Check port value when creating firewall rule with icmp protocol * Configure agents using neutron.common.config.init (formerly .parse) * Added missing core_plugins symbolic names * Introduced rpc_compat.create_connection() * Introduce RpcCallback class * remove pep8 E122 exemption and correct style * remove E112 hacking exemption and fix errors * Updated from global requirements * Fix race condition with firewall deletion * Monkey patch threading module as early as possible * Added RpcProxy class * Freescale SDN Mechanism Driver for ML2 Plugin * Remove run-time version checking for openvswitch features * Log firewall status on delete in case of status inconsistency * Added missing plugin .ini files to setup.cfg * FWaaS plugin doesn't need to handle firewall rule del ops * Updated from global requirements * Disallow regular user to update firewall's shared attribute * Synced jsonutils from oslo-incubator * Cisco APIC ML2 mechanism driver, part 2 * NSX: get rid of the last Nicira/NVP bits * Do not defer IPTables apply in firewall path * Fix non-existent 'assert' calls to mocks * Add missing translation support * Add mailmap entry * Updated from global requirements * Remove explicit dependency on amqplib * Remove duplicate module-rgx line in .pylintrc * Fix H302 violations * Fix H302 violations in unit tests * Updated from global requirements * Updated from global requirements * Exclude .ropeproject from flake8 checks * Remove mock.patch.stop from tests that inherit from BaseTestCase * Enable flake8 E711 and E712 checking * Updated from global requirements * Sync service and systemd modules from oslo-incubator * Move bash whitelisting to pep8 testenv * Fix Jenkins translation jobs * Set ns_name in RouterInfo as attribute * ignore build directory for pep8 * Return 409 for second firewall creation * Enable hacking H301 check * Updated from global requirements * Remove last parts of Quantum compatibility shim * UT: do not hide an original error in test resource ctxtmgr * Open Juno development * Start using oslosphinx theme for docs * Updated from global requirements * add HEAD sentinel file that contains migration revision * Ensure to count firewalls in target tenant * Mock agent RPC for FWaaS tests to delete DB objs * Fix KeyError except on router_info in FW Agent * Bugfix and refactoring for ovs_lib flow methods * Removes calls to mock.patch.stopall in unit tests * Updated from global requirements * Updated from global requirements * Updated from global requirements * One Convergence Neutron Plugin l3 ext support * One Convergence Neutron Plugin Implementation * BigSwitch: Add SSL Certificate Validation * Updated from global requirements * Add OpenDaylight ML2 MechanismDriver * Implementaion of Mechanism driver for Brocade VDX cluster of switches * Implement Mellanox ML2 MechanismDriver * Implement OpenFlow Agent mechanism driver * Finish off rebranding of the Nicira NVP plugin * BigSwitch: Add agent to support neutron sec groups * Adds the new IBM SDN-VE plugin * Updated from global requirements * Remove unused variable * Change firewall to DOWN when admin state down * Update License Headers to replace Nicira with VMware * Developer documentation * options: consolidate options definitions * Rename Neutron core/service plugins for VMware NSX * Updated from global requirements * Sync minimum requirements * Copy cache package from oslo-incubator * ipt_mgr.ipv6 written in the wrong ipt_mgr.ipv4 * Validate rule uuids provided for update_policy * Remove dependent module py3kcompat * Add migration support from agent to NSX dhcp/metadata services * Remove psutil dependency * LBaaS: move agent based driver files into a separate dir * mailmap: update .mailmap * Return request-id in API response * Prepare for multiple cisco ML2 mech drivers * Support building wheels (PEP-427) * Use oslo.rootwrap library instead of local copy * Enables BigSwitch/Restproxy ML2 VLAN driver * Add an explicit tox job for functional tests * Base ML2 bulk support on the loaded drivers * Enable hacking H233 rule * Update RPC code from oslo * Configure plugins by name * Update lockutils and fixture in openstack.common * Rename nicira configuration elements to match new naming structure * Remove unused imports * Rename check_nvp_config utility tool * Corrects broken format strings in check_i18n.py * Remove FWaaS Noop driver as default and move to unit tests dir * Updates tox.ini to use new features * Updated from global requirements * Sync global requirements to pin sphinx to sphinx>=1.1.2,<1.2 * Remove start index 0 in range() * Add fwaas_driver.ini to setup.cfg * Add vpnaas and debug filters to setup.cfg * Updates .gitignore * Update Zhenguo Niu's mailmap * Fwaas can't run in operating system without namespace feature * Replace stubout with fixtures * Ensure get_pid_to_kill works with rootwrap script * Call _destroy_metadata_proxy from _destroy_router_namespaces * Apply six for metaclass * Updated from global requirements * Cleanup HACKING.rst * Fix import log_handler error with publish_errors set * Updated from global requirements * Utilizes assertIsNone and assertIsNotNone * Updated from global requirements * Fix incorrect indentations found by Pep 1.4.6+ * avoid changing the rule's own action * Cleanup and make HACKING.rst DRYer * Add support for managing async processes * Remove obsolete redhat-eventlet.patch * Open Icehouse development * Updated from global requirements * Fix to enable delete of firewall in PENDING_CREATE state * Require oslo.config 1.2.0 final * Fix FWaaS plugin to allow one firewall per tenant * Use built-in print() instead of print statement * FWaaS - fix reordering of rules in policy * Support for NVP advanced FwaaS service * FWaaS - fix policy association of firewall rule * Add l2 population base classes * Fix message i18n error * Install metering_agent.ini and vpn_agent.ini * fix conversion type missing * vArmour gateway agent and FWaaS driver * Enclose command args in with_venv.sh * ML2 Mechanism Driver for Cisco Nexus * Reference driver implementation (IPsec) for VPNaaS * Implement ML2 port binding * Adding more unit tests for the FWaaS agent * Arista ML2 Mechanism driver * ML2 Mechanism Driver for Tail-f Network Control System (NCS) * Default to not capturing log output in tests * Add Neutron l3 metering agent * Update mailmap * Fix wrong example in HACKING.rst * Bumps hacking to 0.7.0 * remove binaries under bin * Fixes Windows setup dependency bug * Restore Babel to requirements.txt * fix up inadevertant octal to make hacking pass * Firewall as a Service (FWaaS) Iptables Driver * Remove DHCP lease logic * Firewall as a Service (FWaaS) Agent * Remove last vestiges of nose * Updated from global requirements * Ignore pbr*.egg directory * Fix H102, H103 Apache 2.0 license hacking check error * Remove openstack.common.exception usage * Adds Babel dependency missing from 555d27c * Fix the alphabetical order in requirement files * Followup fixes to FWaaS API patch * Remove comments from requirements.txt (workaround pbr bug) * Remove last of assertEquals * Firewall as a Service (FWaaS) APIs and DB Model * remove netifaces dependency of ryu-agent * Add gre tunneling support for the ML2 plugin * Add VXLAN tunneling support for the ML2 plugin * xenapi - rename quantum to neutron * Fix issue with pip installing oslo.config-1.2.0 * Initial Modular L2 Mechanism Driver implementation * Add cover/ to .gitignore * fix some missing change from quantum to neutron * git remove old non-working packaging files * Rename Quantum to Neutron * Rename quantum to neutron in .gitreview * Sync install_venv_common from oslo * Update to use OSLO db * Require greenlet 0.3.2 (or later) * Remove single-version-externally-managed in setup.cfg * Fix single-version-externally-mananged typo in setup.cfg * Allow use of lowercase section names in conf files * Require pbr 0.5.16 or newer * Update to the latest stevedore * Rename agent_loadbalancer directory to loadbalancer * Remove unit tests that are no longer run * Update with latest OSLO code * Remove explicit distribute depend * Fix and enable H90x tests * Remove generic Exception when using assertRaises * Add *.swo/swp to .gitignore * python3: Introduce py33 to tox.ini * Rename README to README.rst * Rename requires files to standard names * Initial Modular L2 plugin implementation * Revert dependency on oslo.config 1.2.0 * Perform a sync with oslo-incubator * Require oslo.config 1.2.0a2 * update mailmap * Revert "Fix ./run_tests.sh --pep8" * Move to pbr * Docstrings formatted according to pep257 * relax amqplib and kombu version requirements * Fix ./run_tests.sh --pep8 * blueprint mellanox-quantum-plugin * Update flake8 pinned versions * Let the cover venv run individual tests * Copy the RHEL6 eventlet workaround from Oslo * Remove locals() from strings substitutions * Enable automatic validation of many HACKING rules * Shorten the path of the nicira nvp plugin * Allow pdb debugging in manually-invoked tests * Reformat openstack-common.conf * Switch to flake8 from pep8 * Parallelize quantum unit testing: * blueprint cisco-single-config * Add lbaas_agent files to setup.py * Add VIRTUAL_ENV key to enviroment passed to patch_tox_env * Pin SQLAlchemy to 0.7.x * Sync latest Oslo components for updated copyright * drop rfc.sh * Replace "OpenStack LLC" with "OpenStack Foundation" * First havana commit * remove references to netstack in setup.py * Switch to final 1.1.0 oslo.config release * Update to Quantum Client 2.2.0 * Update tox.ini to support RHEL 6.x * Switch to oslo.config * Add common test base class to hold common things * Pin pep8 to 1.3.3 * Add initial testr support * LBaaS Agent Reference Implementation * Bump python-quantumclient version to 2.1.2 * Add scheduling feature basing on agent management extension * Remove compat cfg wrapper * Unpin PasteDeploy dependency version * Use testtools instead of unittest or unittest2 * Add midonet to setup.py * Sync latest install_venv_common.py with olso * Add check-nvp-config utility * Add unit test for ryu-agent * Use oslo-config-2013.1b3 * Adds Brocade Plugin implementation * Synchronize code from oslo * PLUMgrid quantum plugin * Update .coveragerc * Allow tools/install_venv_common.py to be run from within the source directory * Updated to latest oslo-version code * Use install_venv_common.py from oslo * Cisco plugin cleanup * Use babel to generate translation file * Update WebOb version to >=1.2 * Update latest OSLO * Adding multi switch support to the Cisco Nexus plugin * Adds support for deploying Quantum on Windows * Latest OSLO updates * Port to argparse based cfg * Add migration support to Quantum * Undo change to require WebOb 1.2.3, instead, require only >=1.0.8 * .gitignore cleanup * Upgrade WebOb to 1.2.3 * Logging module cleanup * Add OVS cleanup utility * Add tox artifacts to .gitignore * Add restproxy.ini to config_path in setup.py * Add script for checking i18n message * l3 agent rpc * Add metadata_agent.ini to config_path in setup.py * Remove __init__.py from bin/ and tools/ * add metadata proxy support for Quantum Networks * Use auth_token middleware in keystoneclient * Add QUANTUM_ prefix for env used by quantum-debug * Make tox.ini run pep8 checks on bin * Explicitly include versioninfo in tarball * Import lockutils and fileutils from openstack-common * Updated openstack-common setup and version code * Ensure that the anyjson version is correct * Add eventlet_backdoor and threadgroup from openstack-common * Add loopingcall from openstack-common * Added service from openstack-common * Drop lxml dependency * Add uuidutils module * Import order clean-up * pin sqlalchemy to 0.7 * Correct Intended Audience * Add OpenStack trove classifier for PyPI * Improve unit test times * l3_nat_agent was renamed to l3_agent and this was missed * Support for several HA RabbitMQ servers * add missing files from setup.py * Create .mailmap file * Lower webob dep from v1.2.0 to v1.0.8 * Implements agent for Quantum Networking testing * Create utility to clean-up netns * Update rootwrap; track changes in nova/cinder * Execute unit tests for Cisco plugin with Quantum tests * Add lease expiration script support for dnsmasq * Add nosehtmloutput as a test dependency * quantum l3 + floating IP support * Updates pip requirements * NEC OpenFlow plugin support * remove old gflags config code * RPC support for OVS Plugin and Agent * Initial implemention of MetaPlugin * RPC support for Linux Bridge Plugin and Agent * Exempt openstack-common from pep8 check * fix bug lp:1025526,update iniparser.py to accept empty value * Introduce files from openstack common * fix bug lp:1019230,update rpc from openstack-common * implement dhcp agent for quantum * Use setuptools git plugin for file inclusion * Remove paste configuration details to a seperate file. blueprint use-common-cfg * Implements the blueprint use-common-cfg for the quantum service. More specifically uses global CONF for the quantum.conf file * Add authZ through incorporation of policy checks * Bug #1013967 - Quantum is breaking on tests with pep 1.3 * Use openstack.common.exception * API v2: mprove validation of post/put, rename few attributes * Add API v2 support * Fix up test running to match jenkins expectation * Add build_sphinx options * Quantum should use openstack.common.jsonutils * Remove hardcoded version for pep8 from tools/test-requires * Quantum should use openstack.common.importutils * PEP8 fixes * Bug #1002605 * Parse linuxbridge plugins using openstack.common.cfg * Add HACKING.rst to tarball generation bug 1001220 * Include AUTHORS in release package * Change Resource.__call__() to not leak internal errors * Removed simplejson from pip-requires * Remove dependency on python-quantumclient * Add sphinx to the test build deps * Add HACKING.rst coding style doc * bug 963152: add a few missing files to sdist tarball * Fix path to python-quantumclient * Split out pip requires and aligned tox file * Fix missing files in sdist package [bug 954906] * Downgraded required version of WebOb to 1.0.8 * more files missing in sdist tarball * make sure pip-requires is included in setup.py sdist * remove pep8 and strict lxml version from setup.py * plugin: introduce ryu plugin * bug 934459: pip no longer supports -E * blueprint quantum-ovs-tunnel-agent * Initial commit: nvp plugin * Cleanup the source distribution * blueprint quantum-linux-bridge-plugin * Remove quantum CLI console script * Bug 925372: remove deprecated webob attributes (and also specify stable webob version in pip-requires) essex-3 ------- * Make tox config work * Pin versions to standard versions * Split out quantum.client and quantum.common * Quantum was missing depend on lxml * moving batch config out of quantum-server repo * Getting ready for the client split * Removed erroneous print from setup.py * Base version.py on glance * Fix lp bug 897882 * Install a good version of pip in the venv * Rename .quantum-venv to .venv * Remove plugin pip-requires essex-2 ------- * Bug #890028 * Fix for bug 900316 * Second round of packaging changes * Changes to make pip-based tests work with jenkins * Fix for bug 888811 * Fix for Bug #888820 - pip-requires file support for plugins essex-1 ------- * blueprint quantum-packaging * Add .gitreview config file for gerrit * Add code-coverage support to run_tests.sh (lp860160) 2011.3 ------ * Add rfc.sh to help with gerrit workflow * merge tyler's unit tests for cisco plugin changes lp845140 * merge salv's no-cheetah CLI branch lp 842190 * merge sumit's branch for lp837752 * Merging latest from lp:quantum * Merging lo:~salvatore-orlando/quantum/quantum-api-auth * Updating CLI for not using Cheetah anymore. Now using a mechanism based on Python built-in templates * Merging Sumit's changes including fixes for multinic support, and CLI module for working with extensions * Merging from Cisco branch * Merging from lp:quantum * merge cisco consolidated plugin changes * Merging lp:~salvatore-orlando/quantum/bug834449 * merge trunk * Merging from lp:quantum * merge salvatore's new cli code * Addressing comments from Dan * Merging from quantum * merge cisco extensions branch * Merging from Sumit's branch, changes to VIF-driver and Scheduler; extension action names have been changed in response to Salvatore's review comments in the extensions branch review * Syncing with Cisco extensions branch * Merging from Sumit's branch, import ordering related changes * Merging the Cisco branch * Finishing cli work Fixing bug with XML deserialization * Merging lp:~salvatore-orlando/quantum/quantum-api-alignment * merge latest quantum branch and resolve conflicts * Merging lp:~asomya/quantum/lp833163 Fix for Bug #833163: Pep8 violations in recent packaging changes that were merged into trunk (Critical) * PEP8 fixes for setup.py * Merging lp:~cisco-openstack/quantum/802dot1qbh-vifdriver-scheduler * Merging lp:~cisco-openstack/quantum/l2network-plugin-persistence * Merging lp:quantum * merging with lp:quantum * Making Keystone version configurable * Merging branch: lp:~danwent/quantum/test-refactor * Syncing with lp:quantum * Merging fixes and changes batch-config script. Thanks lp:danwent ! * Merging lp:~asomya/quantum/lp824145 Fix for Bug#824145 : Adding a setup script for quantum * merge trunk pep8 fixes adapting CLI to API v1.0 Fixing wsgi to avoid failure with extensions * merge trunk * Pulling in changes from lp:quantum * Merging Cisco's contribution to Quantum. Thanks to various folks at Cisco Systems, Quantum will have plugins to integrate with Cisco UCS blade servers using 802.1Qbh, Cisco Nexus family of switches and the ability for Quantum plugin to have multiple switches/devices within a single Quantum plugin * Merging from Sumit's branch pylint fixes and incorporating review comments * Mergin from cisco brach * Merging from lp:quantum * Introducting cheetah Updating list_nets in CLI Writing unit tests for list_nets Stubbing out with FakeConnection now * Merging quantum extenions framework into trunk. Thanks rajaram vinkesh, deepak & santhosh for the great work! * lp Bug#824145 : Adding a setup script for quantum * skeleton for cli unit tests * merge trunk * Merged quantum trunk * - Adding setup script * force batch_config.py to use json, as XML has issues (see bug: 798262) * update batch_config.py to use new client lib, hooray for deleting code * Merging changes addressing Bug # 802772. Thanks lp:danwent ! * Merging bugfix for Bug 822890 - Added License file for Quantum code distribution * L2 Network Plugin Framework merge * Adding Apache Version 2.0 license file. This is the official license agreement under which Quantum code is available to the Open Source community * merge * merge heckj's pip-requires fixes * updates to pip-requires for CI * Merged quantum trunk * Merging changes from lp:quantum * Completing API spec alignment Unit tests aligned with changes in the API spec * Merging the brand new Quantum-client-library feature * Merging lp:quantum updates * persistence of l2network & ucs plugins using mysql - db_conn.ini - configuration details of making a connection to the database - db_test_plugin.py - contains abstraction methods for storing database values in a dict and unit test cases for DB testing - l2network_db.py - db methods for l2network models - l2network_models.py - class definitions for the l2 network tables - ucs_db.py - db methods for ucs models - ucs_models.py - class definition for the ucs tables dynamic loading of the 2nd layer plugin db's based on passed arguments Create, Delete, Get, Getall, Update database methods at - Quantum, L2Network and Ucs Unit test cases for create, delete, getall and update operations for L2Network and Ucs plugins pep8 checks done branch based off revision 34 plugin-framework * Merged from trunk * merged the latest changes from plugin-framework branch - revision 39 conforming to the new cisco plugin directory structure and moving all db related modules into cisco/db folder updated db_test_plugin.py - added import of cisco constants module - added LOG.getLogger for logging component name - updated import module paths for l2network_models/db and ucs_models/db to use the new directory structure - updated (rearranged) imports section to obey openstack alphabetical placement convention updated db_conn.ini - updated database name from cisco_naas to quantum_l2network unit test cases ran successfully and pep8 checks done again * merge branch for to fix bug817826 * Merging the latest changes from lp:quantum * fix bug 817826 and similar error in batch_config.py * merge Salvatore's api branch with fixes for tests. Tweaking branch to remove unwanted bin/quantum.py as part of merge * Santhosh/Rajaram|latest merge from quantum and made extensions use options to load plugin * Apply fix for bug #797419 merging lp:~salvatore-orlando/quantum/bug797419 * Merging branch lp:~netstack/quantum/quantum-unit-tests * Merged from quantum trunk * Adapated plugin infrastructure to allow API to pass options to plugins Now using in-memory sqlite db for tests on FakePlugin teardown() now 'resets' the in-memory db Adding unit tests for APIs * Adding Routes>=1.12.3 to tools/pip-requires * Merging dan wendlandt's bugfixes for Bug #800466 and improvements that enable Quantum to seamlessly run on KVM! * more pep8 goodness * refactor batch_config, allow multiple attaches with the empty string * merge and pep8 cleanup * Merging latest changes from parent repo - lp:network-service , Parent repo had approved merge proposal for merging lp:~santhom/network-service/quantum_testing_framework , which has now been merged into lp:network-service * Merging pep8 and functional test related changes lp:~santhom/network-service/quantum_testing_framework branch * add example to usage string for batch_config.py * Bug fixes and clean-up, including supporting libvirt * Santhosh/Vinkesh | Added the testing framework. Moved the smoketest to tests/functional * Pushing initial started code based on Glance project and infrstructure work done by the melange team * Merging in latest changes from lp:quantum neutron-fwaas-8.0.0/PKG-INFO0000664000567000056710000000264412701410073016547 0ustar jenkinsjenkins00000000000000Metadata-Version: 1.1 Name: neutron-fwaas Version: 8.0.0 Summary: OpenStack Networking FWaaS Home-page: http://www.openstack.org/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: Welcome! ======== This package contains the code for the Neutron Firewall as a Service (FWaaS) service. This includes third-party drivers. This package requires Neutron to run. External Resources: =================== The homepage for Neutron is: http://launchpad.net/neutron. Use this site for asking for help, and filing bugs. We use a single Launchpad page for all Neutron projects. Code is available on git.openstack.org at: . Please refer to Neutron documentation for more information: `Neutron README.rst `_ Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 neutron-fwaas-8.0.0/MANIFEST.in0000664000567000056710000000042212701407720017205 0ustar jenkinsjenkins00000000000000include AUTHORS include README.rst include ChangeLog include LICENSE include neutron_fwaas/db/migration/alembic_migrations/script.py.mako recursive-include neutron_fwaas/db/migration/alembic_migrations/versions * exclude .gitignore exclude .gitreview global-exclude *.pyc neutron-fwaas-8.0.0/tox.ini0000664000567000056710000000753612701407721017000 0ustar jenkinsjenkins00000000000000[tox] envlist = py34,py27,pep8,pylint minversion = 1.6 skipsdist = True [testenv] setenv = VIRTUAL_ENV={envdir} usedevelop = True install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/mitaka} {opts} {packages} deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt whitelist_externals = sh commands = find . -type f -name "*.py[c|o]" -delete find . -type d -name "__pycache__" -delete sh tools/pretty_tox.sh '{posargs}' # there is also secret magic in pretty_tox.sh which lets you run in a fail only # mode. To do this define the TRACE_FAILONLY environmental variable. [testenv:functional] setenv = OS_TEST_PATH=./neutron_fwaas/tests/functional commands = python setup.py testr --slowest --testr-args='{posargs}' [testenv:api] sitepackages=True setenv = OS_TEST_PATH=./neutron_fwaas/tests/tempest_plugin/tests/api/ OS_TESTR_CONCURRENCY=1 TEMPEST_CONFIG_DIR={env:TEMPEST_CONFIG_DIR:/opt/stack/tempest/etc} commands = python setup.py testr --slowest --testr-args='{posargs}' [testenv:scenario] sitepackages=True setenv = OS_TEST_PATH=./neutron_fwaas/tests/tempest_plugin/tests/scenario/ OS_TESTR_CONCURRENCY=1 TEMPEST_CONFIG_DIR={env:TEMPEST_CONFIG_DIR:/opt/stack/tempest/etc} commands = python setup.py testr --slowest --testr-args='{posargs}' [testenv:dsvm-functional] setenv = OS_TEST_PATH=./neutron_fwaas/tests/functional OS_SUDO_TESTING=1 OS_ROOTWRAP_CMD=sudo {envdir}/bin/neutron-rootwrap {envdir}/etc/neutron/rootwrap.conf OS_ROOTWRAP_DAEMON_CMD=sudo {envdir}/bin/neutron-rootwrap-daemon {envdir}/etc/neutron/rootwrap.conf OS_FAIL_ON_MISSING_DEPS=1 whitelist_externals = sh cp sudo commands = python setup.py testr --slowest --testr-args='{posargs}' [testenv:releasenotes] # TODO(ihrachys): remove once infra supports constraints for this target install_command = {toxinidir}/tools/tox_install.sh unconstrained {opts} {packages} commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [testenv:pep8] commands = flake8 {toxinidir}/tools/check_unit_test_structure.sh neutron-db-manage --subproject neutron-fwaas --database-connection sqlite:// check_migration {[testenv:genconfig]commands} whitelist_externals = sh [testenv:i18n] commands = python ./tools/check_i18n.py ./neutron_fwaas ./tools/i18n_cfg.py [testenv:cover] # TODO(ihrachys): remove once infra supports constraints for this target install_command = {toxinidir}/tools/tox_install.sh unconstrained {opts} {packages} commands = python setup.py test --coverage --coverage-package-name=neutron_fwaas --testr-args='{posargs}' [testenv:venv] # TODO(ihrachys): remove once infra supports constraints for this target install_command = {toxinidir}/tools/tox_install.sh unconstrained {opts} {packages} commands = {posargs} [testenv:docs] commands = python setup.py build_sphinx [flake8] # E125 continuation line does not distinguish itself from next logical line # E126 continuation line over-indented for hanging indent # E128 continuation line under-indented for visual indent # E129 visually indented line with same indent as next logical line # E265 block comment should start with ‘# ‘ # H405 multi line docstring summary not separated with an empty line # TODO(marun) H404 multi line docstring should start with a summary ignore = E125,E126,E128,E129,E265,H404,H405 show-source = true exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,tools,.ropeproject,rally-scenarios [testenv:pylint] deps = {[testenv]deps} pylint commands = pylint --rcfile=.pylintrc --output-format=colorized {posargs:neutron_fwaas} [hacking] import_exceptions = neutron_fwaas._i18n local-check-factory = neutron.hacking.checks.factory [testenv:genconfig] commands = {toxinidir}/tools/generate_config_file_samples.sh neutron-fwaas-8.0.0/neutron_fwaas.egg-info/0000775000567000056710000000000012701410073022011 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/neutron_fwaas.egg-info/requires.txt0000664000567000056710000000043512701410072024412 0ustar jenkinsjenkins00000000000000pbr>=1.6 eventlet!=0.18.3,>=0.18.2 httplib2>=0.7.5 netaddr!=0.7.16,>=0.7.12 SQLAlchemy<1.1.0,>=1.0.10 alembic>=0.8.0 six>=1.9.0 neutron-lib>=0.0.1 oslo.config>=3.7.0 oslo.db>=4.1.0 oslo.log>=1.14.0 oslo.messaging>=4.0.0 oslo.serialization>=1.10.0 oslo.service>=1.0.0 oslo.utils>=3.5.0 neutron-fwaas-8.0.0/neutron_fwaas.egg-info/dependency_links.txt0000664000567000056710000000000112701410072026056 0ustar jenkinsjenkins00000000000000 neutron-fwaas-8.0.0/neutron_fwaas.egg-info/not-zip-safe0000664000567000056710000000000112701410066024241 0ustar jenkinsjenkins00000000000000 neutron-fwaas-8.0.0/neutron_fwaas.egg-info/SOURCES.txt0000664000567000056710000002045112701410073023677 0ustar jenkinsjenkins00000000000000.coveragerc .mailmap .pylintrc .testr.conf AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE MANIFEST.in README.rst TESTING.rst babel.cfg requirements.txt setup.cfg setup.py test-requirements.txt tox.ini doc/source/conf.py doc/source/index.rst etc/README.txt etc/oslo-config-generator/fwaas_driver.ini neutron_fwaas/__init__.py neutron_fwaas/_i18n.py neutron_fwaas/opts.py neutron_fwaas/version.py neutron_fwaas.egg-info/PKG-INFO neutron_fwaas.egg-info/SOURCES.txt neutron_fwaas.egg-info/dependency_links.txt neutron_fwaas.egg-info/entry_points.txt neutron_fwaas.egg-info/not-zip-safe neutron_fwaas.egg-info/pbr.json neutron_fwaas.egg-info/requires.txt neutron_fwaas.egg-info/top_level.txt neutron_fwaas/common/__init__.py neutron_fwaas/common/fwaas_constants.py neutron_fwaas/db/__init__.py neutron_fwaas/db/cisco/__init__.py neutron_fwaas/db/cisco/cisco_fwaas_db.py neutron_fwaas/db/firewall/__init__.py neutron_fwaas/db/firewall/firewall_db.py neutron_fwaas/db/firewall/firewall_router_insertion_db.py neutron_fwaas/db/migration/__init__.py neutron_fwaas/db/migration/alembic_migrations/README neutron_fwaas/db/migration/alembic_migrations/env.py neutron_fwaas/db/migration/alembic_migrations/script.py.mako neutron_fwaas/db/migration/alembic_migrations/versions/4202e3047e47_add_index_tenant_id.py neutron_fwaas/db/migration/alembic_migrations/versions/540142f314f4_fwaas_router_insertion.py neutron_fwaas/db/migration/alembic_migrations/versions/796c68dffbb_cisco_csr_fwaas.py neutron_fwaas/db/migration/alembic_migrations/versions/CONTRACT_HEAD neutron_fwaas/db/migration/alembic_migrations/versions/EXPAND_HEAD neutron_fwaas/db/migration/alembic_migrations/versions/kilo_release.py neutron_fwaas/db/migration/alembic_migrations/versions/start_neutron_fwaas.py neutron_fwaas/db/migration/alembic_migrations/versions/liberty/contract/67c8e8d61d5_initial.py neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/4b47ea298795_add_reject_rule.py neutron_fwaas/db/migration/alembic_migrations/versions/liberty/expand/c40fbb377ad_initial.py neutron_fwaas/db/migration/alembic_migrations/versions/mitaka/contract/458aa42b14b_fw_table_alter.py neutron_fwaas/extensions/__init__.py neutron_fwaas/extensions/firewall.py neutron_fwaas/extensions/firewallrouterinsertion.py neutron_fwaas/extensions/cisco/__init__.py neutron_fwaas/extensions/cisco/csr_firewall_insertion.py neutron_fwaas/services/__init__.py neutron_fwaas/services/firewall/__init__.py neutron_fwaas/services/firewall/fwaas_plugin.py neutron_fwaas/services/firewall/agents/__init__.py neutron_fwaas/services/firewall/agents/firewall_agent_api.py neutron_fwaas/services/firewall/agents/firewall_service.py neutron_fwaas/services/firewall/agents/l3reference/__init__.py neutron_fwaas/services/firewall/agents/l3reference/firewall_l3_agent.py neutron_fwaas/services/firewall/agents/varmour/__init__.py neutron_fwaas/services/firewall/agents/varmour/varmour_api.py neutron_fwaas/services/firewall/agents/varmour/varmour_router.py neutron_fwaas/services/firewall/agents/varmour/varmour_utils.py neutron_fwaas/services/firewall/agents/vyatta/__init__.py neutron_fwaas/services/firewall/agents/vyatta/firewall_service.py neutron_fwaas/services/firewall/agents/vyatta/fwaas_agent.py neutron_fwaas/services/firewall/agents/vyatta/vyatta_utils.py neutron_fwaas/services/firewall/drivers/__init__.py neutron_fwaas/services/firewall/drivers/fwaas_base.py neutron_fwaas/services/firewall/drivers/cisco/__init__.py neutron_fwaas/services/firewall/drivers/cisco/csr_acl_driver.py neutron_fwaas/services/firewall/drivers/cisco/csr_firewall_svc_helper.py neutron_fwaas/services/firewall/drivers/linux/__init__.py neutron_fwaas/services/firewall/drivers/linux/iptables_fwaas.py neutron_fwaas/services/firewall/drivers/mcafee/README.rst neutron_fwaas/services/firewall/drivers/mcafee/__init__.py neutron_fwaas/services/firewall/drivers/mcafee/constants.py neutron_fwaas/services/firewall/drivers/mcafee/ngfw_fwaas.py neutron_fwaas/services/firewall/drivers/mcafee/smc_api.py neutron_fwaas/services/firewall/drivers/varmour/__init__.py neutron_fwaas/services/firewall/drivers/varmour/varmour_fwaas.py neutron_fwaas/services/firewall/drivers/vyatta/README.rst neutron_fwaas/services/firewall/drivers/vyatta/__init__.py neutron_fwaas/services/firewall/drivers/vyatta/vyatta_fwaas.py neutron_fwaas/services/firewall/plugins/__init__.py neutron_fwaas/services/firewall/plugins/cisco/__init__.py neutron_fwaas/services/firewall/plugins/cisco/cisco_fwaas_plugin.py neutron_fwaas/tests/__init__.py neutron_fwaas/tests/base.py neutron_fwaas/tests/contrib/README neutron_fwaas/tests/contrib/filters.template neutron_fwaas/tests/contrib/gate_hook.sh neutron_fwaas/tests/contrib/post_test_hook.sh neutron_fwaas/tests/functional/__init__.py neutron_fwaas/tests/functional/test_fwaas_driver.py neutron_fwaas/tests/tempest_plugin/__init__.py neutron_fwaas/tests/tempest_plugin/plugin.py neutron_fwaas/tests/tempest_plugin/services/__init__.py neutron_fwaas/tests/tempest_plugin/services/client.py neutron_fwaas/tests/tempest_plugin/tests/__init__.py neutron_fwaas/tests/tempest_plugin/tests/fwaas_client.py neutron_fwaas/tests/tempest_plugin/tests/api/__init__.py neutron_fwaas/tests/tempest_plugin/tests/api/base.py neutron_fwaas/tests/tempest_plugin/tests/api/test_fwaas_extensions.py neutron_fwaas/tests/tempest_plugin/tests/scenario/__init__.py neutron_fwaas/tests/tempest_plugin/tests/scenario/base.py neutron_fwaas/tests/tempest_plugin/tests/scenario/test_fwaas.py neutron_fwaas/tests/unit/__init__.py neutron_fwaas/tests/unit/db/__init__.py neutron_fwaas/tests/unit/db/firewall/__init__.py neutron_fwaas/tests/unit/db/firewall/test_firewall_db.py neutron_fwaas/tests/unit/extensions/__init__.py neutron_fwaas/tests/unit/extensions/test_firewall.py neutron_fwaas/tests/unit/services/__init__.py neutron_fwaas/tests/unit/services/firewall/__init__.py neutron_fwaas/tests/unit/services/firewall/test_fwaas_plugin.py neutron_fwaas/tests/unit/services/firewall/agents/__init__.py neutron_fwaas/tests/unit/services/firewall/agents/test_firewall_agent_api.py neutron_fwaas/tests/unit/services/firewall/agents/test_firewall_service.py neutron_fwaas/tests/unit/services/firewall/agents/l3reference/__init__.py neutron_fwaas/tests/unit/services/firewall/agents/l3reference/test_firewall_l3_agent.py neutron_fwaas/tests/unit/services/firewall/agents/varmour/__init__.py neutron_fwaas/tests/unit/services/firewall/agents/varmour/test_varmour_router.py neutron_fwaas/tests/unit/services/firewall/agents/vyatta/__init__.py neutron_fwaas/tests/unit/services/firewall/agents/vyatta/test_firewall_service.py neutron_fwaas/tests/unit/services/firewall/agents/vyatta/test_vyatta_utils.py neutron_fwaas/tests/unit/services/firewall/drivers/__init__.py neutron_fwaas/tests/unit/services/firewall/drivers/cisco/__init__.py neutron_fwaas/tests/unit/services/firewall/drivers/cisco/test_csr_acl_driver.py neutron_fwaas/tests/unit/services/firewall/drivers/cisco/test_csr_firewall_svc_helper.py neutron_fwaas/tests/unit/services/firewall/drivers/linux/__init__.py neutron_fwaas/tests/unit/services/firewall/drivers/linux/test_iptables_fwaas.py neutron_fwaas/tests/unit/services/firewall/drivers/mcafee/__init__.py neutron_fwaas/tests/unit/services/firewall/drivers/mcafee/test_ngfw_fwaas.py neutron_fwaas/tests/unit/services/firewall/drivers/varmour/__init__.py neutron_fwaas/tests/unit/services/firewall/drivers/varmour/test_varmour_fwaas.py neutron_fwaas/tests/unit/services/firewall/drivers/vyatta/__init__.py neutron_fwaas/tests/unit/services/firewall/drivers/vyatta/test_vyatta_fwaas.py neutron_fwaas/tests/unit/services/firewall/plugins/__init__.py neutron_fwaas/tests/unit/services/firewall/plugins/cisco/__init__.py neutron_fwaas/tests/unit/services/firewall/plugins/cisco/test_cisco_fwaas_plugin.py releasenotes/notes/.placeholder releasenotes/notes/config-file-generation-265c5256668a26bf.yaml releasenotes/notes/enable-quotas-a3d0a21743bb1985.yaml releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/liberty.rst releasenotes/source/unreleased.rst releasenotes/source/_static/.placeholder releasenotes/source/_templates/.placeholder tools/check_i18n.py tools/check_i18n_test_case.txt tools/check_unit_test_structure.sh tools/clean.sh tools/generate_config_file_samples.sh tools/i18n_cfg.py tools/install_venv.py tools/install_venv_common.py tools/pretty_tox.sh tools/subunit-trace.py tools/tox_install.sh tools/with_venv.shneutron-fwaas-8.0.0/neutron_fwaas.egg-info/PKG-INFO0000664000567000056710000000264412701410072023113 0ustar jenkinsjenkins00000000000000Metadata-Version: 1.1 Name: neutron-fwaas Version: 8.0.0 Summary: OpenStack Networking FWaaS Home-page: http://www.openstack.org/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: Welcome! ======== This package contains the code for the Neutron Firewall as a Service (FWaaS) service. This includes third-party drivers. This package requires Neutron to run. External Resources: =================== The homepage for Neutron is: http://launchpad.net/neutron. Use this site for asking for help, and filing bugs. We use a single Launchpad page for all Neutron projects. Code is available on git.openstack.org at: . Please refer to Neutron documentation for more information: `Neutron README.rst `_ Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 neutron-fwaas-8.0.0/neutron_fwaas.egg-info/top_level.txt0000664000567000056710000000001612701410072024537 0ustar jenkinsjenkins00000000000000neutron_fwaas neutron-fwaas-8.0.0/neutron_fwaas.egg-info/pbr.json0000664000567000056710000000005612701410072023467 0ustar jenkinsjenkins00000000000000{"git_version": "ab56228", "is_release": true}neutron-fwaas-8.0.0/neutron_fwaas.egg-info/entry_points.txt0000664000567000056710000000113412701410072025305 0ustar jenkinsjenkins00000000000000[firewall_drivers] neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas:IptablesFwaasDriver neutron.services.firewall.drivers.varmour.varmour_fwaas.vArmourFwaasDriver = neutron_fwaas.services.firewall.drivers.varmour.varmour_fwaas:vArmourFwaasDriver [neutron.db.alembic_migrations] neutron-fwaas = neutron_fwaas.db.migration:alembic_migrations [oslo.config.opts] firewall.agent = neutron_fwaas.opts:list_agent_opts [tempest.test_plugins] neutron-fwaas = neutron_fwaas.tests.tempest_plugin.plugin:NeutronFWaaSPlugin neutron-fwaas-8.0.0/.testr.conf0000664000567000056710000000037212701407720017541 0ustar jenkinsjenkins00000000000000[DEFAULT] test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_LOG_CAPTURE=1 ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./neutron_fwaas/tests/unit} $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--list neutron-fwaas-8.0.0/AUTHORS0000664000567000056710000002053012701410072016513 0ustar jenkinsjenkins00000000000000Aaron Rosen Adam Harwell Akash Gangil Akihiro MOTOKI Akihiro Motoki Aleks Chirko Alessandro Pilotti Alessio Ababilov Alessio Ababilov Amir Sadoughi Andre Pech Andreas Jaeger Andreas Jaeger Angus Lees Ann Kamyshnikova Anusha Ramineni Arvind Somy Arvind Somya Assaf Muller Bertrand Lallau Bertrand Lallau Bhuvan Arumugam Bob Kukura Bob Melander Brad Hall Brandon Logan Brandon Logan Brant Knudson Brian Haley Brian Waldon Carl Baldwin Cedric Brandily Chang Bo Guo ChangBo Guo(gcb) Christian Berendt Chuck Short Clark Boylan Clint Byrum Cyril Roelandt Dan Prince Dan Wendlandt Davanum Srinivas Dave Lapsley Deepak N Dirk Mueller Doug Hellmann Doug Hellmann Doug Wiegley Edgar Magana Elena Ezhova Emilien Macchi Eugene Nikanorov Gary Kotton Gary Kotton German Eichberger Gordon Chung Guilherme Salgado Hareesh Puthalath Harkirat Singh He Jie Xu Hemanth Ravi Henry Gessau Henry Gessau HenryVIII Hirofumi Ichihara Hiroyuki Ito Ignacio Scopetta Ihar Hrachyshka Ionuț Arțăriși Irena Berezovsky Isaku Yamahata Isaku Yamahata Itsuro Oda JJ Asghar Jacek Swiderski Jakub Libosvar James Arendt James E. Blair James E. Blair Jason Kölker Jay Pipes Jeremy Stanley Jiajun Liu Joe Gordon Joe Heck John Dunning Jordan Tardif Juliano Martinez Julien Danjou Justin Lund KIYOHIRO ADACHI Keshava Bharadwaj Kevin Benton Kevin L. Mitchell Koteswara Rao Kelam Koteswara Rao Kelam Kris Lindgren Kun Huang Kyle Mestery Kyle Mestery Li Ma LiuNanke Luke Gorrie Major Hayden Mark McClain Mark McClain Mark McLoughlin Martin Hickey Maru Newby Maru Newby Mate Lakat Mathieu Rohon Matt Riedemann Matthew Treinish Miguel Angel Ajo Mohammad Banikazemi Monty Taylor Morgan Fainberg Motohiro OTSUKA Nachi Ueno Nachi Ueno Nader Lahouti Nick Numan Siddique Oleg Bondarev Ondřej Nový Paddu Krishnan Paul Michali Paul Michali Praneet Bachheti Preeti Mirji Rajaram Mallya Rajesh Mohan Rajesh Mohan Ralf Haferkamp Reedip Banerjee Rich Curran Roman Podoliaka Romil Gupta Rui Zang Russell Bryant Ryota MIBU Salvatore Orlando Salvatore Orlando Samer Deeb Santhosh Santhosh Kumar Sascha Peilicke Sascha Peilicke Sascha Peilicke Sean Dague Sean Dague Sean M. Collins Sean M. Collins Sergey Lukjanov Sergey Skripnick Shiv Haris Shivakumar M Somik Behera Somik Behera Sridar Kandaswamy Sukhdev Sumit Naiksatam Sumit Naiksatam Sushil Kumar Sylvain Afchain Terry Wilson Thierry Carrez Thomas Bechtold Tim Miller Tony Breeds Toshiaki Higuchi Trinath Somanchi TrinathSomanchi Tyler Smith Vishwanath Jayaraman Weidong Shao Wu Wenxiang Xuhan Peng YAMAMOTO Takashi YAMAMOTO Takashi Yaguang Tang Yalei Wang Yanping Qu Yi Zhao Ying Liu Yong Sheng Gong Yong Sheng Gong Yoshihiro Kaneko Yushiro FURUKAWA Zang MingJie Zhenguo Niu ZhiQiang Fan ZhiQiang Fan Zhongyue Luo alexpilotti armando-migliaccio armando-migliaccio badveli_vishnuus berlin drzix fujioka yuuichi fumihiko kakuma garyduan gongysh gongysh goocher gordon chung justin Lund lawrancejing liu-sheng liuqing llg8212 madhusudhan-kandadai mark mcclain mathieu-rohon rohitagarwalla ronak rossella shihanzhang snaiksat sridhargaddam sukhdev takanorimiyagishi trinaths vinkesh banka zhangguoqing zhhuabj neutron-fwaas-8.0.0/requirements.txt0000664000567000056710000000155112701407720020737 0ustar jenkinsjenkins00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. pbr>=1.6 # Apache-2.0 eventlet!=0.18.3,>=0.18.2 # MIT httplib2>=0.7.5 # MIT netaddr!=0.7.16,>=0.7.12 # BSD SQLAlchemy<1.1.0,>=1.0.10 # MIT alembic>=0.8.0 # MIT six>=1.9.0 # MIT neutron-lib>=0.0.1 # Apache-2.0 oslo.config>=3.7.0 # Apache-2.0 oslo.db>=4.1.0 # Apache-2.0 oslo.log>=1.14.0 # Apache-2.0 oslo.messaging>=4.0.0 # Apache-2.0 oslo.serialization>=1.10.0 # Apache-2.0 oslo.service>=1.0.0 # Apache-2.0 oslo.utils>=3.5.0 # Apache-2.0 # This project does depend on neutron as a library, but the # openstack tooling does not play nicely with projects that # are not publicly available in pypi. # -e git+https://git.openstack.org/openstack/neutron#egg=neutron neutron-fwaas-8.0.0/HACKING.rst0000664000567000056710000000036012701407720017246 0ustar jenkinsjenkins00000000000000Neutron FWaaS Style Commandments ================================ Please see the Neutron HACKING.rst file for style commandments for neutron-fwaas: `Neutron HACKING.rst `_ neutron-fwaas-8.0.0/TESTING.rst0000664000567000056710000000050412701407720017317 0ustar jenkinsjenkins00000000000000Testing Neutron FWaaS ===================== Please see the TESTING.rst file for the Neutron project itself. This will have the latest up to date instructions for how to test Neutron, and will be applicable to neutron-fwaas as well: `Neutron TESTING.rst `_ neutron-fwaas-8.0.0/CONTRIBUTING.rst0000664000567000056710000000027212701407720020113 0ustar jenkinsjenkins00000000000000Please see the Neutron CONTRIBUTING.rst file for how to contribute to neutron-fwaas: `Neutron CONTRIBUTING.rst `_ neutron-fwaas-8.0.0/releasenotes/0000775000567000056710000000000012701410073020135 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/releasenotes/notes/0000775000567000056710000000000012701410073021265 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/releasenotes/notes/config-file-generation-265c5256668a26bf.yaml0000664000567000056710000000043512701407720030557 0ustar jenkinsjenkins00000000000000--- prelude: > Generation of sample Neutron FWaaS configuration files. features: - Neutron FWaaS no longer includes static example configuration files. Instead, use tools/generate_config_file_samples.sh to generate them. The files are generated with a .sample extension. neutron-fwaas-8.0.0/releasenotes/notes/.placeholder0000664000567000056710000000000012701407720023543 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/releasenotes/notes/enable-quotas-a3d0a21743bb1985.yaml0000664000567000056710000000135212701407720027041 0ustar jenkinsjenkins00000000000000--- prelude: > Enable quotas for FWaaS. features: - The FWaaS extension will register quotas. The default values for quota_firewall and quota_firewall_policy are set to 10. The default value for quota_firewall_rule is set to 100. Quotas can be adjusted in the conf files, including -1 values to allow unlimited. issues: - Tenants may receive a 409 Conflict error with a message body containing a quota exceeded message during resource creation if their quota is exceeded. other: - Operators that increase the default limit for quota_routers from 10 may want to bump FWaaS quotas as well, since with router insertion a tenant can potentially have a unique policy and firewall for each router. neutron-fwaas-8.0.0/releasenotes/source/0000775000567000056710000000000012701410073021435 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/releasenotes/source/index.rst0000664000567000056710000000022112701407721023277 0ustar jenkinsjenkins00000000000000============================= Neutron FWaaS Release Notes ============================= .. toctree:: :maxdepth: 1 liberty unreleased neutron-fwaas-8.0.0/releasenotes/source/_templates/0000775000567000056710000000000012701410073023572 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/releasenotes/source/_templates/.placeholder0000664000567000056710000000000012701407720026050 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/releasenotes/source/unreleased.rst0000664000567000056710000000016012701407720024320 0ustar jenkinsjenkins00000000000000============================== Current Series Release Notes ============================== .. release-notes:: neutron-fwaas-8.0.0/releasenotes/source/liberty.rst0000664000567000056710000000022212701407720023642 0ustar jenkinsjenkins00000000000000============================== Liberty Series Release Notes ============================== .. release-notes:: :branch: origin/stable/liberty neutron-fwaas-8.0.0/releasenotes/source/conf.py0000664000567000056710000002177312701407720022753 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # 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. # Neutron FWaaS Release Notes documentation build configuration file, created # by # sphinx-quickstart on Tue Nov 3 17:40:50 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'oslosphinx', 'reno.sphinxext', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Neutron FWaaS Release Notes' copyright = u'2015, Neutron FWaaS Developers' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. from neutron_fwaas.version import version_info as neutron_fwaas_version # The full version, including alpha/beta/rc tags. release = neutron_fwaas_version.version_string_with_vcs() # The short X.Y version. version = neutron_fwaas_version.canonical_version_string() # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'NeutronFWaaSReleaseNotesdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # 'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'NeutronFWaaSReleaseNotes.tex', u'Neutron FWaaS Release Notes Documentation', u'Neutron FWaaS Developers', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'neutronfwaasreleasenotes', u'Neutron FWaaS Release Notes ' 'Documentation', [u'Neutron FWaaS Developers'], 1) ] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'NeutronFWaaSReleaseNotes', u'Neutron FWaaS Release Notes ' 'Documentation', u'Neutron FWaaS Developers', 'NeutronFWaaSReleaseNotes', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False neutron-fwaas-8.0.0/releasenotes/source/_static/0000775000567000056710000000000012701410073023063 5ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/releasenotes/source/_static/.placeholder0000664000567000056710000000000012701407720025341 0ustar jenkinsjenkins00000000000000neutron-fwaas-8.0.0/README.rst0000664000567000056710000000117712701407720017146 0ustar jenkinsjenkins00000000000000Welcome! ======== This package contains the code for the Neutron Firewall as a Service (FWaaS) service. This includes third-party drivers. This package requires Neutron to run. External Resources: =================== The homepage for Neutron is: http://launchpad.net/neutron. Use this site for asking for help, and filing bugs. We use a single Launchpad page for all Neutron projects. Code is available on git.openstack.org at: . Please refer to Neutron documentation for more information: `Neutron README.rst `_ neutron-fwaas-8.0.0/.mailmap0000664000567000056710000000111612701407720017071 0ustar jenkinsjenkins00000000000000# Format is: # # lawrancejing Jiajun Liu Zhongyue Luo Kun Huang Zhenguo Niu Isaku Yamahata Isaku Yamahata Morgan Fainberg neutron-fwaas-8.0.0/setup.py0000664000567000056710000000200412701407720017157 0ustar jenkinsjenkins00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # 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. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools # In python < 2.7.4, a lazy loading of package `pbr` will break # setuptools if some other modules registered functions in `atexit`. # solution from: http://bugs.python.org/issue15881#msg170215 try: import multiprocessing # noqa except ImportError: pass setuptools.setup( setup_requires=['pbr>=1.8'], pbr=True) neutron-fwaas-8.0.0/.pylintrc0000664000567000056710000000700012701407720017313 0ustar jenkinsjenkins00000000000000# The format of this file isn't really documented; just use --generate-rcfile [MASTER] # Add to the black list. It should be a base name, not a # path. You may set this option multiple times. # # Note the 'openstack' below is intended to match only # neutron.openstack.common. If we ever have another 'openstack' # dirname, then we'll need to expand the ignore features in pylint :/ ignore=.git,tests,openstack [MESSAGES CONTROL] # NOTE(gus): This is a long list. A number of these are important and # should be re-enabled once the offending code is fixed (or marked # with a local disable) disable= # "F" Fatal errors that prevent further processing import-error, # "I" Informational noise locally-disabled, # "E" Error for important programming issues (likely bugs) access-member-before-definition, bad-super-call, maybe-no-member, no-member, no-method-argument, no-self-argument, not-callable, no-value-for-parameter, super-on-old-class, too-few-format-args, # "W" Warnings for stylistic problems or minor programming issues abstract-method, anomalous-backslash-in-string, anomalous-unicode-escape-in-string, arguments-differ, attribute-defined-outside-init, bad-builtin, bad-indentation, broad-except, dangerous-default-value, deprecated-lambda, duplicate-key, expression-not-assigned, fixme, global-statement, global-variable-not-assigned, logging-not-lazy, no-init, non-parent-init-called, pointless-string-statement, protected-access, redefined-builtin, redefined-outer-name, redefine-in-handler, signature-differs, star-args, super-init-not-called, unnecessary-lambda, unnecessary-pass, unpacking-non-sequence, unreachable, unused-argument, unused-import, unused-variable, # "C" Coding convention violations bad-continuation, invalid-name, missing-docstring, old-style-class, superfluous-parens, # "R" Refactor recommendations abstract-class-little-used, abstract-class-not-used, duplicate-code, interface-not-implemented, no-self-use, too-few-public-methods, too-many-ancestors, too-many-arguments, too-many-branches, too-many-instance-attributes, too-many-lines, too-many-locals, too-many-public-methods, too-many-return-statements, too-many-statements [BASIC] # Variable names can be 1 to 31 characters long, with lowercase and underscores variable-rgx=[a-z_][a-z0-9_]{0,30}$ # Argument names can be 2 to 31 characters long, with lowercase and underscores argument-rgx=[a-z_][a-z0-9_]{1,30}$ # Method names should be at least 3 characters long # and be lowecased with underscores method-rgx=([a-z_][a-z0-9_]{2,}|setUp|tearDown)$ # Module names matching neutron-* are ok (files in bin/) module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(neutron-[a-z0-9_-]+))$ # Don't require docstrings on tests. no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$ [FORMAT] # Maximum number of characters on a single line. max-line-length=79 [VARIABLES] # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. # _ is used by our localization additional-builtins=_ [CLASSES] # List of interface methods to ignore, separated by a comma. ignore-iface-methods= [IMPORTS] # Deprecated modules which should not be used, separated by a comma deprecated-modules= # should use openstack.common.jsonutils json [TYPECHECK] # List of module names for which member attributes should not be checked ignored-modules=six.moves,_MovedItems [REPORTS] # Tells whether to display a full report or only the messages reports=no neutron-fwaas-8.0.0/test-requirements.txt0000664000567000056710000000132712701407720021715 0ustar jenkinsjenkins00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. hacking<0.11,>=0.10.0 coverage>=3.6 # Apache-2.0 fixtures>=1.3.1 # Apache-2.0/BSD mock>=1.2 # BSD python-subunit>=0.0.18 # Apache-2.0/BSD requests-mock>=0.7.0 # Apache-2.0 sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0 oslo.concurrency>=3.5.0 # Apache-2.0 testrepository>=0.0.18 # Apache-2.0/BSD testresources>=0.2.4 # Apache-2.0/BSD testtools>=1.4.0 # MIT testscenarios>=0.4 # Apache-2.0/BSD WebOb>=1.2.3 # MIT WebTest>=2.0 # MIT oslotest>=1.10.0 # Apache-2.0 reno>=0.1.1 # Apache2