diff options
| -rw-r--r-- | Authors | 1 | ||||
| -rw-r--r-- | nova/api/ec2/admin.py | 41 | ||||
| -rw-r--r-- | nova/compute/api.py | 2 | ||||
| -rw-r--r-- | nova/compute/manager.py | 4 | ||||
| -rwxr-xr-x | nova/network/linux_net.py | 9 | ||||
| -rw-r--r-- | nova/tests/api/ec2/test_admin.py | 59 | ||||
| -rw-r--r-- | nova/tests/test_xenapi.py | 60 | ||||
| -rw-r--r-- | nova/tests/xenapi/stubs.py | 1 | ||||
| -rw-r--r-- | nova/utils.py | 4 | ||||
| -rw-r--r-- | nova/virt/driver.py | 4 | ||||
| -rw-r--r-- | nova/virt/firewall.py | 47 | ||||
| -rw-r--r-- | nova/virt/libvirt/firewall.py | 45 | ||||
| -rw-r--r-- | nova/virt/xenapi/firewall.py | 56 | ||||
| -rw-r--r-- | nova/virt/xenapi/vmops.py | 3 | ||||
| -rw-r--r-- | nova/virt/xenapi_conn.py | 3 |
15 files changed, 263 insertions, 76 deletions
@@ -41,6 +41,7 @@ Dave Walker <DaveWalker@ubuntu.com> David Pravec <David.Pravec@danix.org> David Subiros <david.perez5@hp.com> Dean Troyer <dtroyer@gmail.com> +Deepak Garg <deepak.garg@citrix.com> Derek Higgins <higginsd@gmail.com> Devendra Modium <dmodium@isi.edu> Devin Carlen <devin.carlen@gmail.com> diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index 80a30659d..4e81debe4 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -349,8 +349,15 @@ class AdminController(object): LOG.audit(_('Blocking traffic to all projects incoming from %s'), cidr, context=context) cidr = urllib.unquote(cidr).decode() - # raise if invalid - netaddr.IPNetwork(cidr) + failed = {'status': 'Failed', 'message': ' 0 rules added'} + if not utils.is_valid_cidr(cidr): + msg = 'Improper input. Please provide a valid cidr: ' \ + 'e.g. 121.12.10.11/24.' + failed['message'] = msg + failed['message'] + return failed + #Normalizing cidr. e.g. '20.20.20.11/24' -> '20.20.20.0/24', so that + #db values stay in sync with filters' values (e.g. in iptables) + cidr = str(netaddr.IPNetwork(cidr).cidr) rule = {'cidr': cidr} tcp_rule = rule.copy() tcp_rule.update({'protocol': 'tcp', 'from_port': 1, 'to_port': 65535}) @@ -370,7 +377,9 @@ class AdminController(object): db.provider_fw_rule_create(context, icmp_rule) rules_added += 1 if not rules_added: - raise exception.ApiError(_('Duplicate rule')) + msg = 'Duplicate Rule.' + failed['message'] = msg + failed['message'] + return failed self.compute_api.trigger_provider_fw_rules_refresh(context) return {'status': 'OK', 'message': 'Added %s rules' % rules_added} @@ -385,11 +394,25 @@ class AdminController(object): def remove_external_address_block(self, context, cidr): LOG.audit(_('Removing ip block from %s'), cidr, context=context) cidr = urllib.unquote(cidr).decode() - # raise if invalid - netaddr.IPNetwork(cidr) + # Catch the exception and LOG for improper or malicious inputs. + # Also return a proper status and message in that case + failed = {'status': 'Failed', 'message': ' 0 rules deleted'} + if not utils.is_valid_cidr(cidr): + msg = 'Improper input. Please provide a valid cidr: ' \ + 'e.g. 121.12.10.11/24.' + failed['message'] = msg + failed['message'] + return failed + #Normalizing cidr. e.g. '20.20.20.11/24' -> '20.20.20.0/24', so that + #db values stay in sync with filters' values (e.g. in iptables) + cidr = str(netaddr.IPNetwork(cidr).cidr) rules = db.provider_fw_rule_get_all_by_cidr(context, cidr) - for rule in rules: - db.provider_fw_rule_destroy(context, rule['id']) - if rules: + + if not rules: + msg = 'No such CIDR currently blocked.' + failed['message'] = msg + failed['message'] + return failed + else: + for rule in rules: + db.provider_fw_rule_destroy(context, rule['id']) self.compute_api.trigger_provider_fw_rules_refresh(context) - return {'status': 'OK', 'message': 'Deleted %s rules' % len(rules)} + return {'status': 'OK', 'message': 'Deleted %s rules' % len(rules)} diff --git a/nova/compute/api.py b/nova/compute/api.py index a4c228e26..0e874358b 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -710,7 +710,7 @@ class API(base.Base): "args": {"security_group_id": group_id}}) def trigger_provider_fw_rules_refresh(self, context): - """Called when a rule is added to or removed from a security_group""" + """Called when a rule is added/removed from a provider firewall""" hosts = [x['host'] for (x, idx) in self.db.service_get_all_compute_sorted(context)] diff --git a/nova/compute/manager.py b/nova/compute/manager.py index f43c7a1a0..59e228e45 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -261,9 +261,9 @@ class ComputeManager(manager.SchedulerDependentManager): return self.driver.refresh_security_group_members(security_group_id) @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) - def refresh_provider_fw_rules(self, context, **_kwargs): + def refresh_provider_fw_rules(self, context, **kwargs): """This call passes straight through to the virtualization driver.""" - return self.driver.refresh_provider_fw_rules() + return self.driver.refresh_provider_fw_rules(**kwargs) def _get_instance_nw_info(self, context, instance): """Get a list of dictionaries of network data of an instance. diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index fa5e514b9..996f89a5f 100755 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -303,16 +303,17 @@ class IptablesManager(object): for cmd, tables in s: for table in tables: - current_table, _ = self.execute('%s-save' % (cmd,), - '-t', '%s' % (table,), - run_as_root=True, - attempts=5) + current_table, _err = self.execute('%s-save' % (cmd,), + '-t', '%s' % (table,), + run_as_root=True, + attempts=5) current_lines = current_table.split('\n') new_filter = self._modify_rules(current_lines, tables[table]) self.execute('%s-restore' % (cmd,), run_as_root=True, process_input='\n'.join(new_filter), attempts=5) + LOG.debug(_("IPTablesManager.apply completed with success")) def _modify_rules(self, current_lines, table, binary=None): unwrapped_chains = table.unwrapped_chains diff --git a/nova/tests/api/ec2/test_admin.py b/nova/tests/api/ec2/test_admin.py index 2b4e463ee..62eb596f3 100644 --- a/nova/tests/api/ec2/test_admin.py +++ b/nova/tests/api/ec2/test_admin.py @@ -365,24 +365,43 @@ class AdminControllerTestCase(test.TestCase): hosts = self._ac.describe_hosts(self._c)['hosts'] self.assertEqual('volume1', hosts[0]['hostname']) - def test_block_external_addresses(self): + def test_block_external_addresses_validate_output_for_valid_input(self): result = self._ac.block_external_addresses(self._c, '192.168.100.1/24') self.assertEqual('OK', result['status']) self.assertEqual('Added 3 rules', result['message']) - def test_block_external_addresses_already_existent_rule(self): - self._ac.block_external_addresses(self._c, '192.168.100.1/24') - self.assertRaises(exception.ApiError, - self._ac.block_external_addresses, - self._c, '192.168.100.1/24') + def test_block_external_addresses_validate_output_for_invalid_input(self): + result = self._ac.block_external_addresses(self._c, '12.10.10.256/24') + self.assertEqual('Failed', result['status']) + value = '0 rules added' in result['message'] + self.assertEqual(value, True) - def test_describe_external_address_blocks(self): - self._ac.block_external_addresses(self._c, '192.168.100.1/24') + def test_block_external_addresses_already_existent_rule(self): + self._ac.block_external_addresses(self._c, '192.168.100.0/24') + result = self._ac.block_external_addresses(self._c, '192.168.100.0/24') + self.assertEqual('Failed', result['status']) + value = '0 rules added' in result['message'] + self.assertEqual(value, True) + + def test_describe_external_address_blocks_normalized_output(self): + self._ac.block_external_addresses(self._c, '192.168.100.11/24') self.assertEqual( - {'externalIpBlockInfo': [{'cidr': u'192.168.100.1/24'}]}, + {'externalIpBlockInfo': [{'cidr': u'192.168.100.0/24'}]}, self._ac.describe_external_address_blocks(self._c)) - def test_remove_external_address_block(self): + def test_describe_external_address_blocks_many_inputs(self): + self._ac.block_external_addresses(self._c, '192.168.100.11/24') + self._ac.block_external_addresses(self._c, '12.12.12.10/24') + self._ac.block_external_addresses(self._c, '18.18.18.0/24') + output1 = {'cidr': u'192.168.100.0/24'} + output2 = {'cidr': u'12.12.12.0/24'} + output3 = {'cidr': u'18.18.18.0/24'} + result = self._ac.describe_external_address_blocks(self._c) + result = sorted(result['externalIpBlockInfo']) + output = sorted([output1, output2, output3]) + self.assertEqual(result, output) + + def test_remove_external_address_block_existent_rule(self): self._ac.block_external_addresses(self._c, '192.168.100.1/24') result = self._ac.remove_external_address_block(self._c, @@ -393,6 +412,26 @@ class AdminControllerTestCase(test.TestCase): result = self._ac.describe_external_address_blocks(self._c) self.assertEqual([], result['externalIpBlockInfo']) + def test_remove_external_address_block_non_existent_rule(self): + result = self._ac.remove_external_address_block(self._c, + '192.168.100.1/24') + self.assertEqual('Failed', result['status']) + value = '0 rules deleted' in result['message'] + self.assertEqual(value, True) + + result = self._ac.describe_external_address_blocks(self._c) + self.assertEqual([], result['externalIpBlockInfo']) + + def test_remove_external_address_block_invalid_input(self): + result = self._ac.remove_external_address_block(self._c, + '192.168.100/24') + self.assertEqual('Failed', result['status']) + value = '0 rules deleted' in result['message'] + self.assertEqual(value, True) + + result = self._ac.describe_external_address_blocks(self._c) + self.assertEqual([], result['externalIpBlockInfo']) + def test_start_vpn(self): def fake_launch_vpn_instance(self, *args): diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index c3730b3ca..482cd450c 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -1334,6 +1334,9 @@ class XenAPIBWUsageTestCase(test.TestCase): self.assertEqual(result, []) +# TODO(salvatore-orlando): this class and +# nova.tests.test_libvirt.IPTablesFirewallDriverTestCase share a lot of code. +# Consider abstracting common code in a base class for firewall driver testing. class XenAPIDom0IptablesFirewallTestCase(test.TestCase): _in_nat_rules = [ @@ -1581,3 +1584,60 @@ class XenAPIDom0IptablesFirewallTestCase(test.TestCase): self.assertTrue(len(filter(regex.match, self._out_rules)) > 0, "Rules were not updated properly." "The rule for UDP acceptance is missing") + + def test_provider_firewall_rules(self): + # setup basic instance data + instance_ref = self._create_instance_ref() + # FRAGILE: as in libvirt tests + # peeks at how the firewall names chains + chain_name = 'inst-%s' % instance_ref['id'] + + network_info = fake_network.fake_get_instance_nw_info(self.stubs, 1, 1) + self.fw.prepare_instance_filter(instance_ref, network_info) + self.assertTrue('provider' in self.fw.iptables.ipv4['filter'].chains) + rules = [rule for rule in self.fw.iptables.ipv4['filter'].rules + if rule.chain == 'provider'] + self.assertEqual(0, len(rules)) + + admin_ctxt = context.get_admin_context() + # add a rule and send the update message, check for 1 rule + provider_fw0 = db.provider_fw_rule_create(admin_ctxt, + {'protocol': 'tcp', + 'cidr': '10.99.99.99/32', + 'from_port': 1, + 'to_port': 65535}) + self.fw.refresh_provider_fw_rules() + rules = [rule for rule in self.fw.iptables.ipv4['filter'].rules + if rule.chain == 'provider'] + self.assertEqual(1, len(rules)) + + # Add another, refresh, and make sure number of rules goes to two + provider_fw1 = db.provider_fw_rule_create(admin_ctxt, + {'protocol': 'udp', + 'cidr': '10.99.99.99/32', + 'from_port': 1, + 'to_port': 65535}) + self.fw.refresh_provider_fw_rules() + rules = [rule for rule in self.fw.iptables.ipv4['filter'].rules + if rule.chain == 'provider'] + self.assertEqual(2, len(rules)) + + # create the instance filter and make sure it has a jump rule + self.fw.prepare_instance_filter(instance_ref, network_info) + self.fw.apply_instance_filter(instance_ref, network_info) + inst_rules = [rule for rule in self.fw.iptables.ipv4['filter'].rules + if rule.chain == chain_name] + jump_rules = [rule for rule in inst_rules if '-j' in rule.rule] + provjump_rules = [] + # IptablesTable doesn't make rules unique internally + for rule in jump_rules: + if 'provider' in rule.rule and rule not in provjump_rules: + provjump_rules.append(rule) + self.assertEqual(1, len(provjump_rules)) + + # remove a rule from the db, cast to compute to refresh rule + db.provider_fw_rule_destroy(admin_ctxt, provider_fw1['id']) + self.fw.refresh_provider_fw_rules() + rules = [rule for rule in self.fw.iptables.ipv4['filter'].rules + if rule.chain == 'provider'] + self.assertEqual(1, len(rules)) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 0c707e14e..2dfece00f 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -32,7 +32,6 @@ def stubout_firewall_driver(stubs, conn): return vmops = conn._vmops - stubs.Set(vmops.firewall_driver, 'setup_basic_filtering', fake_none) stubs.Set(vmops.firewall_driver, 'prepare_instance_filter', fake_none) stubs.Set(vmops.firewall_driver, 'instance_filter_exists', fake_none) diff --git a/nova/utils.py b/nova/utils.py index bd68c6966..818dc2b73 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -1075,12 +1075,12 @@ def monkey_patch(): if isinstance(module_data[key], pyclbr.Class): clz = import_class("%s.%s" % (module, key)) for method, func in inspect.getmembers(clz, inspect.ismethod): - setattr(clz, method,\ + setattr(clz, method, decorator("%s.%s.%s" % (module, key, method), func)) # set the decorator for the function if isinstance(module_data[key], pyclbr.Function): func = import_class("%s.%s" % (module, key)) - setattr(sys.modules[module], key,\ + setattr(sys.modules[module], key, decorator("%s.%s" % (module, key), func)) diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 7a9347542..fa40160f6 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -380,7 +380,7 @@ class ComputeDriver(object): * another host 'H1' runs an instance 'i-1' * instance 'i-1' is a member of security group 'b' - When 'i-1' launches or terminates we will recieve the message + When 'i-1' launches or terminates we will receive the message to update members of group 'b', at which time we will make any changes needed to the rules for instance 'i-0' to allow or deny traffic coming from 'i-1', depending on if it is being @@ -399,7 +399,7 @@ class ComputeDriver(object): # TODO(Vek): Need to pass context in for access to auth_token raise NotImplementedError() - def refresh_provider_fw_rules(self, security_group_id): + def refresh_provider_fw_rules(self): """This triggers a firewall update based on database changes. When this is called, rules have either been added or removed from the diff --git a/nova/virt/firewall.py b/nova/virt/firewall.py index 3426120ac..ed60051d9 100644 --- a/nova/virt/firewall.py +++ b/nova/virt/firewall.py @@ -34,7 +34,7 @@ flags.DEFINE_bool('allow_same_net_traffic', class FirewallDriver(object): """ Firewall Driver base class. - Defines methos that any driver providing security groups + Defines methods that any driver providing security groups and provider fireall functionality should implement. """ def prepare_instance_filter(self, instance, network_info): @@ -129,12 +129,18 @@ class IptablesFirewallDriver(FirewallDriver): self.instances[instance['id']] = instance self.network_infos[instance['id']] = network_info self.add_filters_for_instance(instance) + LOG.debug(_('Filters added to the instance: %r'), instance) + self.refresh_provider_fw_rules() + LOG.debug(_('Provider Firewall Rules refreshed')) self.iptables.apply() def _create_filter(self, ips, chain_name): return ['-d %s -j $%s' % (ip, chain_name) for ip in ips] def _filters_for_instance(self, chain_name, network_info): + """Creates a rule corresponding to each ip that defines a + jump to the corresponding instance - chain for all the traffic + destined to that ip""" ips_v4 = [ip['ip'] for (_n, mapping) in network_info for ip in mapping['ips']] ipv4_rules = self._create_filter(ips_v4, chain_name) @@ -190,6 +196,10 @@ class IptablesFirewallDriver(FirewallDriver): ipv4_rules += ['-m state --state ESTABLISHED,RELATED -j ACCEPT'] ipv6_rules += ['-m state --state ESTABLISHED,RELATED -j ACCEPT'] + # Pass through provider-wide drops + ipv4_rules += ['-j $provider'] + ipv6_rules += ['-j $provider'] + def _do_dhcp_rules(self, ipv4_rules, network_info): dhcp_servers = [info['dhcp_server'] for (_n, info) in network_info] @@ -345,3 +355,38 @@ class IptablesFirewallDriver(FirewallDriver): for instance in self.instances.values(): self.remove_filters_for_instance(instance) self.add_filters_for_instance(instance) + + def refresh_provider_fw_rules(self): + """See class:FirewallDriver: docs.""" + self._do_refresh_provider_fw_rules() + self.iptables.apply() + + @utils.synchronized('iptables', external=True) + def _do_refresh_provider_fw_rules(self): + """Internal, synchronized version of refresh_provider_fw_rules.""" + self._purge_provider_fw_rules() + self._build_provider_fw_rules() + + def _purge_provider_fw_rules(self): + """Remove all rules from the provider chains.""" + self.iptables.ipv4['filter'].empty_chain('provider') + if FLAGS.use_ipv6: + self.iptables.ipv6['filter'].empty_chain('provider') + + def _build_provider_fw_rules(self): + """Create all rules for the provider IP DROPs.""" + self.iptables.ipv4['filter'].add_chain('provider') + if FLAGS.use_ipv6: + self.iptables.ipv6['filter'].add_chain('provider') + ipv4_rules, ipv6_rules = self._provider_rules() + for rule in ipv4_rules: + self.iptables.ipv4['filter'].add_rule('provider', rule) + + if FLAGS.use_ipv6: + for rule in ipv6_rules: + self.iptables.ipv6['filter'].add_rule('provider', rule) + + @staticmethod + def _provider_rules(): + """Generate a list of rules from provider for IP4 & IP6.""" + raise NotImplementedError() diff --git a/nova/virt/libvirt/firewall.py b/nova/virt/libvirt/firewall.py index 9b9e3540e..3e299b932 100644 --- a/nova/virt/libvirt/firewall.py +++ b/nova/virt/libvirt/firewall.py @@ -259,7 +259,7 @@ class NWFilterFirewall(base_firewall.FirewallDriver): LOG.debug(_('The nwfilter(%(instance_filter_name)s) ' 'for %(instance_name)s is not found.') % locals()) - instance_secgroup_filter_name =\ + instance_secgroup_filter_name = \ '%s-secgroup' % (self._instance_filter_name(instance)) try: @@ -486,53 +486,10 @@ class IptablesFirewallDriver(base_firewall.IptablesFirewallDriver): LOG.info(_('Attempted to unfilter instance %s which is not ' 'filtered'), instance['id']) - def _do_basic_rules(self, ipv4_rules, ipv6_rules, network_info): - # Always drop invalid packets - ipv4_rules += ['-m state --state ' 'INVALID -j DROP'] - ipv6_rules += ['-m state --state ' 'INVALID -j DROP'] - - # Allow established connections - ipv4_rules += ['-m state --state ESTABLISHED,RELATED -j ACCEPT'] - ipv6_rules += ['-m state --state ESTABLISHED,RELATED -j ACCEPT'] - - # Pass through provider-wide drops - ipv4_rules += ['-j $provider'] - ipv6_rules += ['-j $provider'] - def instance_filter_exists(self, instance, network_info): """Check nova-instance-instance-xxx exists""" return self.nwfilter.instance_filter_exists(instance, network_info) - def refresh_provider_fw_rules(self): - """See class:FirewallDriver: docs.""" - self._do_refresh_provider_fw_rules() - self.iptables.apply() - - @utils.synchronized('iptables', external=True) - def _do_refresh_provider_fw_rules(self): - """Internal, synchronized version of refresh_provider_fw_rules.""" - self._purge_provider_fw_rules() - self._build_provider_fw_rules() - - def _purge_provider_fw_rules(self): - """Remove all rules from the provider chains.""" - self.iptables.ipv4['filter'].empty_chain('provider') - if FLAGS.use_ipv6: - self.iptables.ipv6['filter'].empty_chain('provider') - - def _build_provider_fw_rules(self): - """Create all rules for the provider IP DROPs.""" - self.iptables.ipv4['filter'].add_chain('provider') - if FLAGS.use_ipv6: - self.iptables.ipv6['filter'].add_chain('provider') - ipv4_rules, ipv6_rules = self._provider_rules() - for rule in ipv4_rules: - self.iptables.ipv4['filter'].add_rule('provider', rule) - - if FLAGS.use_ipv6: - for rule in ipv6_rules: - self.iptables.ipv6['filter'].add_rule('provider', rule) - @staticmethod def _provider_rules(): """Generate a list of rules from provider for IP4 & IP6.""" diff --git a/nova/virt/xenapi/firewall.py b/nova/virt/xenapi/firewall.py index 8f6f17de3..41d67de5c 100644 --- a/nova/virt/xenapi/firewall.py +++ b/nova/virt/xenapi/firewall.py @@ -19,8 +19,12 @@ import json + +from nova import context from nova import flags from nova import log as logging +from nova.db import api as db +from nova.virt import netutils from nova.virt.firewall import IptablesFirewallDriver @@ -65,3 +69,55 @@ class Dom0IptablesFirewallDriver(IptablesFirewallDriver): # No multiport needed for XS! return ['--dport', '%s:%s' % (rule.from_port, rule.to_port)] + + @staticmethod + def _provider_rules(): + """Generate a list of rules from provider for IP4 & IP6. + Note: We could not use the common code from virt.firewall because + XS doesn't accept the '-m multiport' option""" + + ctxt = context.get_admin_context() + ipv4_rules = [] + ipv6_rules = [] + rules = db.provider_fw_rule_get_all(ctxt) + for rule in rules: + LOG.debug(_('Adding provider rule: %s'), rule['cidr']) + version = netutils.get_ip_version(rule['cidr']) + if version == 4: + fw_rules = ipv4_rules + else: + fw_rules = ipv6_rules + + protocol = rule['protocol'] + if version == 6 and protocol == 'icmp': + protocol = 'icmpv6' + + args = ['-p', protocol, '-s', rule['cidr']] + + if protocol in ['udp', 'tcp']: + if rule['from_port'] == rule['to_port']: + args += ['--dport', '%s' % (rule['from_port'],)] + else: + args += ['--dport', '%s:%s' % (rule['from_port'], + rule['to_port'])] + elif protocol == 'icmp': + icmp_type = rule['from_port'] + icmp_code = rule['to_port'] + + if icmp_type == -1: + icmp_type_arg = None + else: + icmp_type_arg = '%s' % icmp_type + if not icmp_code == -1: + icmp_type_arg += '/%s' % icmp_code + + if icmp_type_arg: + if version == 4: + args += ['-m', 'icmp', '--icmp-type', + icmp_type_arg] + elif version == 6: + args += ['-m', 'icmp6', '--icmpv6-type', + icmp_type_arg] + args += ['-j DROP'] + fw_rules += [' '.join(args)] + return ipv4_rules, ipv6_rules diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 1309879b5..f681aceef 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -1744,6 +1744,9 @@ class VMOps(object): """ recreates security group rules for every instance """ self.firewall_driver.refresh_security_group_members(security_group_id) + def refresh_provider_fw_rules(self): + self.firewall_driver.refresh_provider_fw_rules() + def unfilter_instance(self, instance_ref, network_info): """Removes filters for each VIF of the specified instance.""" self.firewall_driver.unfilter_instance(instance_ref, diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 1bd0b52a5..42f035217 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -443,6 +443,9 @@ class XenAPIConnection(driver.ComputeDriver): """ return self._vmops.refresh_security_group_members(security_group_id) + def refresh_provider_fw_rules(self): + return self._vmops.refresh_provider_fw_rules() + def update_host_status(self): """Update the status info of the host, and return those values to the calling program.""" |
