From 9d0e903139d9066c097196370242cfd586991068 Mon Sep 17 00:00:00 2001 From: Adit Sarfaty Date: Mon, 14 Nov 2016 16:39:15 +0200 Subject: [PATCH] [Admin-util] NSX|V admin util to use a policy in a security group New admin utility that can be used when the user changes the configuration to use policies in security groups (use_nsx_policies=True) This utility deletes the current rules and section of the security group, and adds it to the policy. usage: nsxadmin -r security-groups -o migrate-to-policy --property policy-id=<> --property security-group-id=<> Output example: ==== [MIGRATE] Sg To Policy ==== Successfully established new session; session ID is 28c3f. Deleting the rules of security group: 415ff93e-cbd4-4f49-a06d-44885eba7c88 Deleting the section of security group: 415ff93e-cbd4-4f49-a06d-44885eba7c88 Binding the NSX security group securitygroup-143 to policy policy-9 Done. Change-Id: I7041c33b86a0ebc965e2cfcfe1c9ac9261a0318a --- doc/source/admin_util.rst | 4 + vmware_nsx/db/nsxv_db.py | 6 ++ .../plugins/nsxv/resources/securitygroups.py | 83 +++++++++++++++++++ vmware_nsx/shell/resources.py | 4 +- 4 files changed, 96 insertions(+), 1 deletion(-) diff --git a/doc/source/admin_util.rst b/doc/source/admin_util.rst index 31ead9074e..fed29f7b80 100644 --- a/doc/source/admin_util.rst +++ b/doc/source/admin_util.rst @@ -137,6 +137,10 @@ Security Groups, Firewall and Spoofguard nsxadmin -r spoofguard-policy -o clean --property policy-id=spoofguardpolicy-10 nsxadmin -r spoofguard-policy -o list --property reverse (entries defined on NSXv and not in Neutron) +- Migrate a security group from using rules to using a policy + + nsxadmin -r security-groups -o migrate-to-policy --property policy-id=policy-10 --property security-group-id=733f0741-fa2c-4b32-811c-b78e4dc8ec39 + Metadata ~~~~~~~~ diff --git a/vmware_nsx/db/nsxv_db.py b/vmware_nsx/db/nsxv_db.py index 23c4b41633..8a97edbc88 100644 --- a/vmware_nsx/db/nsxv_db.py +++ b/vmware_nsx/db/nsxv_db.py @@ -448,6 +448,12 @@ def get_nsx_section(session, neutron_id): "stored in Neutron DB", neutron_id) +def delete_neutron_nsx_section_mapping(session, neutron_id): + with session.begin(subtransactions=True): + return (session.query(nsxv_models.NsxvSecurityGroupSectionMapping). + filter_by(neutron_id=neutron_id).delete()) + + def get_nsx_rule_id(session, neutron_id): try: mapping = (session.query(nsxv_models.NsxvRuleMapping). diff --git a/vmware_nsx/shell/admin/plugins/nsxv/resources/securitygroups.py b/vmware_nsx/shell/admin/plugins/nsxv/resources/securitygroups.py index 373a78654a..e34911d75d 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv/resources/securitygroups.py +++ b/vmware_nsx/shell/admin/plugins/nsxv/resources/securitygroups.py @@ -16,18 +16,24 @@ import logging import xml.etree.ElementTree as et +from neutron.callbacks import registry from neutron import context from neutron.db.models import securitygroup as sg_models from neutron.db import models_v2 from neutron.db import securitygroups_db +from neutron.extensions import securitygroup as ext_sg +from vmware_nsx._i18n import _LE, _LI, _LW from vmware_nsx.db import db as nsx_db from vmware_nsx.db import nsx_models +from vmware_nsx.db import nsxv_db from vmware_nsx.db import nsxv_models +from vmware_nsx.extensions import securitygrouppolicy as sg_policy from vmware_nsx.shell.admin.plugins.common import constants from vmware_nsx.shell.admin.plugins.common import formatters from vmware_nsx.shell.admin.plugins.common import utils as admin_utils from vmware_nsx.shell.admin.plugins.nsxv.resources import utils +from vmware_nsx.shell import resources as shell LOG = logging.getLogger(__name__) @@ -242,3 +248,80 @@ def fix_security_groups(resource, event, trigger, **kwargs): nsx_id = nsx_db.get_nsx_security_group_id(context_.session, sg_id) for vnic_id in neutron_sg.get_vnics_in_security_group(sg_id): plugin._add_member_to_security_group(nsx_id, vnic_id) + + +@admin_utils.output_header +def migrate_sg_to_policy(resource, event, trigger, **kwargs): + """Change the mode of a security group from rules to NSX policy""" + if not kwargs.get('property'): + LOG.error(_LE("Need to specify security-group-id and policy-id " + "parameters")) + return + + # input validation + properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) + sg_id = properties.get('security-group-id') + if not sg_id: + LOG.error(_LE("Need to specify security-group-id parameter")) + return + policy_id = properties.get('policy-id') + if not policy_id: + LOG.error(_LE("Need to specify policy-id parameter")) + return + + # validate that the security group exist and contains rules and no policy + context_ = context.get_admin_context() + plugin = utils.NsxVPluginWrapper() + try: + secgroup = plugin.get_security_group(context_, sg_id) + except ext_sg.SecurityGroupNotFound: + LOG.error(_LE("Security group %s was not found"), sg_id) + return + if secgroup.get('policy'): + LOG.error(_LE("Security group %s already uses a policy"), sg_id) + return + + # validate that the policy exists + if not plugin.nsx_v.vcns.validate_inventory(policy_id): + LOG.error(_LE("NSX policy %s was not found"), policy_id) + return + + # Delete the rules from the security group + LOG.info(_LI("Deleting the rules of security group: %s"), sg_id) + for rule in secgroup.get('security_group_rules', []): + try: + plugin.delete_security_group_rule(context_, rule['id']) + except Exception as e: + LOG.warning(_LW("Failed to delete rule %(r)s from security group " + "%(sg)s: %(e)s"), + {'r': rule['id'], 'sg': sg_id, 'e': e}) + # continue anyway + + # Delete the security group FW section + LOG.info(_LI("Deleting the section of security group: %s"), sg_id) + try: + section_uri = plugin._get_section_uri(context_.session, sg_id) + plugin._delete_section(section_uri) + nsxv_db.delete_neutron_nsx_section_mapping(context_.session, sg_id) + except Exception as e: + LOG.warning(_LW("Failed to delete firewall section of security group " + "%(sg)s: %(e)s"), + {'sg': sg_id, 'e': e}) + # continue anyway + + # bind this security group to the policy in the backend and DB + nsx_sg_id = nsx_db.get_nsx_security_group_id(context_.session, sg_id) + LOG.info(_LI("Binding the NSX security group %(nsx)s to policy %(pol)s"), + {'nsx': nsx_sg_id, 'pol': policy_id}) + plugin._update_nsx_security_group_policies( + policy_id, None, nsx_sg_id) + prop = plugin._get_security_group_properties(context_, sg_id) + with context_.session.begin(subtransactions=True): + prop.update({sg_policy.POLICY: policy_id}) + + LOG.info(_LI("Done.")) + + +registry.subscribe(migrate_sg_to_policy, + constants.SECURITY_GROUPS, + shell.Operations.MIGRATE_TO_POLICY.value) diff --git a/vmware_nsx/shell/resources.py b/vmware_nsx/shell/resources.py index a3d40f39d8..4780abe94b 100644 --- a/vmware_nsx/shell/resources.py +++ b/vmware_nsx/shell/resources.py @@ -48,6 +48,7 @@ class Operations(enum.Enum): NSX_RECREATE = 'nsx-recreate' MIGRATE_TO_DYNAMIC_CRITERIA = 'migrate-to-dynamic-criteria' NSX_MIGRATE_V_V3 = 'nsx-migrate-v-v3' + MIGRATE_TO_POLICY = 'migrate-to-policy' STATUS = 'status' ops = [op.value for op in Operations] @@ -121,7 +122,8 @@ nsxv_resources = { Operations.NSX_CLEAN.value]), constants.SECURITY_GROUPS: Resource(constants.SECURITY_GROUPS, [Operations.LIST.value, - Operations.FIX_MISMATCH.value]), + Operations.FIX_MISMATCH.value, + Operations.MIGRATE_TO_POLICY.value]), constants.FIREWALL_SECTIONS: Resource(constants.FIREWALL_SECTIONS, [Operations.LIST.value, Operations.LIST_MISMATCHES.value]),