NSX|P: Fix transactions related issues
1. Call NSX transactional api only if partial updates are supported (Or else some attributes of the main resource can be reset) 2. Fix bulk rule creation under transaction to provide all the attributes of the existing rules. Change-Id: Iff9d6b59fffeaca91e09d6eeff158748aaa5578a
This commit is contained in:
parent
f1837f6766
commit
722f93b752
|
@ -2266,6 +2266,14 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
# remove the edge cluster from the tier1 router
|
||||
self.nsxpolicy.tier1.remove_edge_cluster(router_id)
|
||||
|
||||
def _run_under_transaction(self, method):
|
||||
if self.nsxpolicy.feature_supported(
|
||||
nsxlib_consts.FEATURE_PARTIAL_UPDATES):
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
method()
|
||||
else:
|
||||
method()
|
||||
|
||||
def _update_router_gw_info(self, context, router_id, info,
|
||||
called_from=None):
|
||||
# Get the original data of the router GW
|
||||
|
@ -2313,7 +2321,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
if actions['add_service_router']:
|
||||
self.create_service_router(context, router_id, router=router)
|
||||
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
def _do_remove_nat():
|
||||
if actions['remove_snat_rules']:
|
||||
for subnet in router_subnets:
|
||||
self._del_subnet_snat_rule(router_id, subnet)
|
||||
|
@ -2321,6 +2329,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
for subnet in router_subnets:
|
||||
self._del_subnet_no_dnat_rule(router_id, subnet)
|
||||
|
||||
self._run_under_transaction(_do_remove_nat)
|
||||
|
||||
if (actions['remove_router_link_port'] or
|
||||
actions['add_router_link_port']):
|
||||
# GW was changed. update GW and route advertisement
|
||||
|
@ -2338,7 +2348,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
nat=actions['advertise_route_nat_flag'],
|
||||
subnets=actions['advertise_route_connected_flag'])
|
||||
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
def _do_add_nat():
|
||||
if actions['add_snat_rules']:
|
||||
# Add SNAT rules for all the subnets which are in different
|
||||
# scope than the GW
|
||||
|
@ -2348,12 +2358,13 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
self._add_subnet_snat_rule(context, router_id,
|
||||
subnet, gw_address_scope,
|
||||
newaddr)
|
||||
|
||||
if actions['add_no_dnat_rules']:
|
||||
for subnet in router_subnets:
|
||||
self._add_subnet_no_dnat_rule(
|
||||
context, router_id, subnet)
|
||||
|
||||
self._run_under_transaction(_do_add_nat)
|
||||
|
||||
# always advertise ipv6 subnets if gateway is set
|
||||
advertise_ipv6_subnets = True if info else False
|
||||
self._update_router_advertisement_rules(router_id,
|
||||
|
@ -2408,7 +2419,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
r, resource_type='os-neutron-router-id',
|
||||
project_name=context.tenant_name)
|
||||
try:
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
def _do_create_router():
|
||||
self.nsxpolicy.tier1.create_or_overwrite(
|
||||
router_name, router['id'],
|
||||
tier0=None,
|
||||
|
@ -2417,6 +2428,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
# Also create the empty locale-service as it must always exist
|
||||
self.nsxpolicy.tier1.create_locale_service(router['id'])
|
||||
|
||||
self._run_under_transaction(_do_create_router)
|
||||
|
||||
except Exception as ex:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error('Failed to create router %(id)s '
|
||||
|
@ -2480,7 +2493,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
route['nexthop'])
|
||||
|
||||
def _add_static_routes(self, router_id, routes):
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
def _do_add_routes():
|
||||
for route in routes:
|
||||
dest = route['destination']
|
||||
self.nsxpolicy.tier1_static_route.create_or_overwrite(
|
||||
|
@ -2490,6 +2503,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
network=dest,
|
||||
next_hop=route['nexthop'])
|
||||
|
||||
self._run_under_transaction(_do_add_routes)
|
||||
|
||||
def _delete_static_routes(self, router_id, routes):
|
||||
for route in routes:
|
||||
self.nsxpolicy.tier1_static_route.delete(
|
||||
|
@ -2825,8 +2840,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
return policy_constants.NAT_FIREWALL_MATCH_EXTERNAL
|
||||
|
||||
def _add_fip_nat_rules(self, tier1_id, fip_id, ext_ip, int_ip):
|
||||
firewall_match = self._get_nat_firewall_match()
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
def _do_add_fip_nat():
|
||||
firewall_match = self._get_nat_firewall_match()
|
||||
self.nsxpolicy.tier1_nat_rule.create_or_overwrite(
|
||||
'snat for fip %s' % fip_id,
|
||||
tier1_id,
|
||||
|
@ -2846,8 +2861,10 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
sequence_number=NAT_RULE_PRIORITY_FIP,
|
||||
firewall_match=firewall_match)
|
||||
|
||||
self._run_under_transaction(_do_add_fip_nat)
|
||||
|
||||
def _delete_fip_nat_rules(self, tier1_id, fip_id):
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
def _do_delete_fip_nat():
|
||||
self.nsxpolicy.tier1_nat_rule.delete(
|
||||
tier1_id,
|
||||
nat_rule_id=self._get_fip_snat_rule_id(fip_id))
|
||||
|
@ -2855,6 +2872,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
tier1_id,
|
||||
nat_rule_id=self._get_fip_dnat_rule_id(fip_id))
|
||||
|
||||
self._run_under_transaction(_do_delete_fip_nat)
|
||||
|
||||
def _update_lb_vip(self, port, vip_address):
|
||||
# update the load balancer virtual server's VIP with
|
||||
# floating ip, but don't add NAT rules
|
||||
|
@ -3205,7 +3224,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
category = NSX_P_PROVIDER_SECTION_CATEGORY
|
||||
|
||||
try:
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
def _do_create_sg():
|
||||
# Create the group
|
||||
self.nsxpolicy.group.create_or_overwrite_with_conditions(
|
||||
nsx_name, NSX_P_GLOBAL_DOMAIN_ID, group_id=sg_id,
|
||||
|
@ -3219,6 +3238,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
tags=tags, category=category)
|
||||
for entry in entries:
|
||||
self.nsxpolicy.comm_map.create_entry_from_def(entry)
|
||||
|
||||
self._run_under_transaction(_do_create_sg)
|
||||
except Exception as e:
|
||||
msg = (_("Failed to create NSX resources for SG %(sg)s: "
|
||||
"%(e)s") % {'sg': sg_id, 'e': e})
|
||||
|
@ -3289,7 +3310,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
|
||||
def _create_security_group_backend_rule(self, context, map_id,
|
||||
sg_rule, secgroup_logging,
|
||||
is_provider_sg=False):
|
||||
is_provider_sg=False,
|
||||
create_related_resource=True):
|
||||
"""Create backend resources for a DFW rule
|
||||
|
||||
All rule resources (service, groups) will be created
|
||||
|
@ -3318,32 +3340,42 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
# Create a group for the remote IPs
|
||||
remote_ip = sg_rule['remote_ip_prefix']
|
||||
remote_group_id = self._get_sg_rule_remote_ip_group_id(sg_rule)
|
||||
expr = self.nsxpolicy.group.build_ip_address_expression(
|
||||
[remote_ip])
|
||||
self.nsxpolicy.group.create_or_overwrite_with_conditions(
|
||||
remote_group_id, NSX_P_GLOBAL_DOMAIN_ID,
|
||||
group_id=remote_group_id,
|
||||
description='%s for OS rule %s' % (remote_ip, sg_rule['id']),
|
||||
conditions=[expr], tags=tags)
|
||||
if create_related_resource:
|
||||
expr = self.nsxpolicy.group.build_ip_address_expression(
|
||||
[remote_ip])
|
||||
self.nsxpolicy.group.create_or_overwrite_with_conditions(
|
||||
remote_group_id, NSX_P_GLOBAL_DOMAIN_ID,
|
||||
group_id=remote_group_id,
|
||||
description='%s for OS rule %s' % (remote_ip,
|
||||
sg_rule['id']),
|
||||
conditions=[expr], tags=tags)
|
||||
source = remote_group_id
|
||||
if sg_rule.get(sg_prefix.LOCAL_IP_PREFIX):
|
||||
# Create a group for the local ips
|
||||
local_ip = sg_rule[sg_prefix.LOCAL_IP_PREFIX]
|
||||
local_group_id = self._get_sg_rule_local_ip_group_id(sg_rule)
|
||||
expr = self.nsxpolicy.group.build_ip_address_expression(
|
||||
[local_ip])
|
||||
self.nsxpolicy.group.create_or_overwrite_with_conditions(
|
||||
local_group_id, NSX_P_GLOBAL_DOMAIN_ID,
|
||||
group_id=local_group_id,
|
||||
description='%s for OS rule %s' % (local_ip, sg_rule['id']),
|
||||
conditions=[expr], tags=tags)
|
||||
if create_related_resource:
|
||||
expr = self.nsxpolicy.group.build_ip_address_expression(
|
||||
[local_ip])
|
||||
self.nsxpolicy.group.create_or_overwrite_with_conditions(
|
||||
local_group_id, NSX_P_GLOBAL_DOMAIN_ID,
|
||||
group_id=local_group_id,
|
||||
description='%s for OS rule %s' % (local_ip,
|
||||
sg_rule['id']),
|
||||
conditions=[expr], tags=tags)
|
||||
destination = local_group_id
|
||||
|
||||
if direction == nsxlib_consts.OUT:
|
||||
# Swap source and destination
|
||||
source, destination = destination, source
|
||||
|
||||
service = self._get_rule_service_id(context, sg_rule, tags)
|
||||
if create_related_resource:
|
||||
service = self._get_rule_service_id(context, sg_rule, tags)
|
||||
else:
|
||||
if nsxlib_utils.get_l4_protocol_name(sg_rule['protocol']):
|
||||
service = sg_rule['id']
|
||||
else:
|
||||
service = None
|
||||
ip_protocol = self._get_rule_ip_protocol(sg_rule)
|
||||
logging = (cfg.CONF.nsx_p.log_security_groups_allowed_traffic or
|
||||
secgroup_logging)
|
||||
|
@ -3399,13 +3431,12 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
sg_rules = secgroup_db['security_group_rules']
|
||||
secgroup_logging = secgroup.get(sg_logging.LOGGING, False)
|
||||
backend_rules = []
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
# Create all the rules resources in a single transaction
|
||||
for sg_rule in sg_rules:
|
||||
rule_entry = self._create_security_group_backend_rule(
|
||||
context, secgroup_db['id'], sg_rule,
|
||||
secgroup_logging)
|
||||
backend_rules.append(rule_entry)
|
||||
# Create all the rules resources in a single transaction
|
||||
for sg_rule in sg_rules:
|
||||
rule_entry = self._create_security_group_backend_rule(
|
||||
context, secgroup_db['id'], sg_rule,
|
||||
secgroup_logging)
|
||||
backend_rules.append(rule_entry)
|
||||
# Create Group & communication map on the NSX
|
||||
self._create_security_group_backend_resources(
|
||||
context, secgroup, backend_rules)
|
||||
|
@ -3521,20 +3552,21 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
category = (NSX_P_PROVIDER_SECTION_CATEGORY if is_provider_sg
|
||||
else NSX_P_REGULAR_SECTION_CATEGORY)
|
||||
# Create the NSX backend rules in a single transaction
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
|
||||
def _do_update_rules():
|
||||
# Build new rules and relevant objects
|
||||
backend_rules = []
|
||||
for rule_data in rules_db:
|
||||
rule_entry = self._create_security_group_backend_rule(
|
||||
context, sg_id, rule_data, secgroup_logging,
|
||||
is_provider_sg=is_provider_sg)
|
||||
|
||||
backend_rules.append(rule_entry)
|
||||
|
||||
# Add the old rules
|
||||
for rule in sg['security_group_rules']:
|
||||
rule_entry = self.nsxpolicy.comm_map.build_entry(
|
||||
NSX_P_GLOBAL_DOMAIN_ID, sg_id, rule['id'])
|
||||
rule_entry = self._create_security_group_backend_rule(
|
||||
context, sg_id, rule, secgroup_logging,
|
||||
is_provider_sg=is_provider_sg,
|
||||
create_related_resource=False)
|
||||
backend_rules.append(rule_entry)
|
||||
|
||||
# Update the policy with all the rules.
|
||||
|
@ -3542,6 +3574,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
NSX_P_GLOBAL_DOMAIN_ID, sg_id, entries=backend_rules,
|
||||
category=category)
|
||||
|
||||
self._run_under_transaction(_do_update_rules)
|
||||
|
||||
return rules_db
|
||||
|
||||
def _delete_security_group_rule_backend_resources(
|
||||
|
|
|
@ -24,6 +24,7 @@ from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
|
|||
from vmware_nsx.shell.admin.plugins.nsxp.resources import utils as p_utils
|
||||
from vmware_nsx.shell import resources as shell
|
||||
|
||||
from vmware_nsxlib.v3 import nsx_constants
|
||||
from vmware_nsxlib.v3.policy import constants as policy_constants
|
||||
from vmware_nsxlib.v3.policy import transaction as policy_trans
|
||||
|
||||
|
@ -146,11 +147,18 @@ def update_nat_firewall_match(resource, event, trigger, **kwargs):
|
|||
for router in neutron_routers:
|
||||
rules = nsxpolicy.tier1_nat_rule.list(router['id'])
|
||||
for rule in rules:
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
if not nsxpolicy.feature_supported(
|
||||
nsx_constants.FEATURE_PARTIAL_UPDATES):
|
||||
if rule['firewall_match'] == old_firewall_match:
|
||||
nsxpolicy.tier1_nat_rule.update(
|
||||
router['id'], rule['id'],
|
||||
firewall_match=new_firewall_match)
|
||||
else:
|
||||
with policy_trans.NsxPolicyTransaction():
|
||||
if rule['firewall_match'] == old_firewall_match:
|
||||
nsxpolicy.tier1_nat_rule.update(
|
||||
router['id'], rule['id'],
|
||||
firewall_match=new_firewall_match)
|
||||
|
||||
LOG.info("Done.")
|
||||
|
||||
|
|
Loading…
Reference in New Issue