From ec68daecc39d964adb9cb976cd56ab297898ff5d Mon Sep 17 00:00:00 2001
From: Amey Bhide <abhide@vmware.com>
Date: Wed, 4 Nov 2015 23:59:04 -0800
Subject: [PATCH] Admin Utility: Update DHCP binding for NSXv edge

$ nsxadmin -r dhcp-binding -o nsx-update --property edge-id=edge-15
NSX Plugin in use: nsxv
Notify callbacks for dhcp-binding, nsx-update
Calling callback
tools.python_nsxadmin.admin.plugins.common.utils.nsx_update_dhcp_edge_binding
==== [NSX] Update Dhcp Edge Binding ====
Updating NSXv Edge: edge-15

Change-Id: I3524a5cb7a4418006f157842b35c9519235be1d7
---
 .../plugins/nsxv/resources/dhcp_binding.py    | 30 ++++++++++-
 vmware_nsx/plugins/nsx_v/plugin.py            | 53 ++-----------------
 .../plugins/nsx_v/vshield/edge_utils.py       | 46 +++++++++++++++-
 3 files changed, 77 insertions(+), 52 deletions(-)

diff --git a/tools/python_nsxadmin/admin/plugins/nsxv/resources/dhcp_binding.py b/tools/python_nsxadmin/admin/plugins/nsxv/resources/dhcp_binding.py
index a651ae191b..0b26f0e065 100644
--- a/tools/python_nsxadmin/admin/plugins/nsxv/resources/dhcp_binding.py
+++ b/tools/python_nsxadmin/admin/plugins/nsxv/resources/dhcp_binding.py
@@ -16,16 +16,19 @@
 import logging
 
 from tools.python_nsxadmin.admin.plugins.common import constants
-
 import tools.python_nsxadmin.admin.plugins.common.utils as admin_utils
 import tools.python_nsxadmin.admin.plugins.nsxv.resources.utils as utils
 
 import tools.python_nsxadmin.admin.shell as shell
 
 from neutron.callbacks import registry
+from neutron.db import db_base_plugin_v2
 
-from vmware_nsx._i18n import _LI
+from vmware_nsx._i18n import _LE, _LI
 from vmware_nsx.db import nsxv_db
+from vmware_nsx.plugins.nsx_v.vshield import edge_utils
+from vmware_nsx.plugins.nsx_v.vshield import vcns_driver
+
 
 LOG = logging.getLogger(__name__)
 nsxv = utils.get_nsxv_client()
@@ -82,6 +85,29 @@ def list_missing_dhcp_bindings(resource, event, trigger, **kwargs):
         LOG.info(neutron_dhcp_static_bindings - nsx_dhcp_static_bindings)
 
 
+@admin_utils.output_header
+def nsx_update_dhcp_edge_binding(resource, event, trigger, **kwargs):
+    """Resync DHCP bindings on NSXv Edge"""
+
+    if not kwargs['property']:
+        LOG.error(_LE("Need to specify edge-id parameter"))
+        return
+    else:
+        properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
+        LOG.info(_LI("Updating NSXv Edge: %s"), properties.get('edge-id'))
+        # Need to create a NeutronDbPlugin object; so that we are able to
+        # do neutron list-ports.
+        plugin = db_base_plugin_v2.NeutronDbPluginV2()
+        nsxv_manager = vcns_driver.VcnsDriver(
+                           edge_utils.NsxVCallbacks(plugin))
+        edge_manager = edge_utils.EdgeManager(nsxv_manager, plugin)
+        edge_manager.update_dhcp_service_config(
+            neutron_db.context, properties.get('edge-id'))
+
+
 registry.subscribe(list_missing_dhcp_bindings,
                    constants.DHCP_BINDING,
                    shell.Operations.LIST.value)
+registry.subscribe(nsx_update_dhcp_edge_binding,
+                   constants.DHCP_BINDING,
+                   shell.Operations.NSX_UPDATE.value)
diff --git a/vmware_nsx/plugins/nsx_v/plugin.py b/vmware_nsx/plugins/nsx_v/plugin.py
index 0116122c56..0b5f691636 100644
--- a/vmware_nsx/plugins/nsx_v/plugin.py
+++ b/vmware_nsx/plugins/nsx_v/plugin.py
@@ -266,11 +266,10 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
         network_id = neutron_port_db['network_id']
         device_owner = neutron_port_db['device_owner']
         if device_owner.startswith("compute"):
-            s_bindings = self._create_static_binding(context,
-                                                     neutron_port_db)
-            self.edge_manager.create_dhcp_bindings(
-                context, neutron_port_db['id'],
-                network_id, s_bindings)
+            s_bindings = self.edge_manager.create_static_binding(
+                context, neutron_port_db)
+            self.edge_manager.create_dhcp_bindings(context, self.nsx_v,
+                                            network_id, s_bindings)
 
     def _delete_dhcp_static_binding(self, context, neutron_port_db):
 
@@ -1339,50 +1338,6 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
         LOG.debug("Update the DHCP address group to %s", address_groups)
         return address_groups
 
-    def _create_static_binding(self, context, port):
-        """Create the DHCP Edge static binding configuration
-
-        <staticBinding>
-            <macAddress></macAddress>
-            <ipAddress></ipAddress>
-            <hostname></hostname> <!--disallow duplicate-->
-            <defaultGateway></defaultGateway> <!--optional.-->
-            <primaryNameServer></primaryNameServer> <!--optional-->
-            <secondaryNameServer></secondaryNameServer> <!--optional-->
-        </staticBinding>
-        """
-        static_bindings = []
-        static_config = {}
-        static_config['macAddress'] = port['mac_address']
-        static_config['hostname'] = port['id']
-        static_config['leaseTime'] = cfg.CONF.nsxv.dhcp_lease_time
-
-        for fixed_ip in port['fixed_ips']:
-            # Query the subnet to get gateway and DNS
-            try:
-                subnet_id = fixed_ip['subnet_id']
-                subnet = self._get_subnet(context, subnet_id)
-            except n_exc.SubnetNotFound:
-                LOG.debug("No related subnet for port %s", port['id'])
-                continue
-            # Only configure if subnet has DHCP support
-            if not subnet['enable_dhcp']:
-                continue
-            static_config['ipAddress'] = fixed_ip['ip_address']
-            # Set gateway for static binding
-            static_config['defaultGateway'] = subnet['gateway_ip']
-            # set primary and secondary dns
-            name_servers = [dns['address']
-                            for dns in subnet['dns_nameservers']]
-            if len(name_servers) == 1:
-                static_config['primaryNameServer'] = name_servers[0]
-            elif len(name_servers) >= 2:
-                static_config['primaryNameServer'] = name_servers[0]
-                static_config['secondaryNameServer'] = name_servers[1]
-
-            static_bindings.append(static_config)
-        return static_bindings
-
     def _extract_external_gw(self, context, router, is_extract=True):
         r = router['router']
         gw_info = attr.ATTR_NOT_SPECIFIED
diff --git a/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py b/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py
index 692c3e9510..dd53f510e2 100644
--- a/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py
+++ b/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py
@@ -666,6 +666,50 @@ class EdgeManager(object):
                 lock_file_prefix='nsxv-dhcp-config-'):
             self.update_dhcp_service_config(context, edge_binding['edge_id'])
 
+    def create_static_binding(self, context, port):
+        """Create the DHCP Edge static binding configuration
+
+        <staticBinding>
+            <macAddress></macAddress>
+            <ipAddress></ipAddress>
+            <hostname></hostname> <!--disallow duplicate-->
+            <defaultGateway></defaultGateway> <!--optional.-->
+            <primaryNameServer></primaryNameServer> <!--optional-->
+            <secondaryNameServer></secondaryNameServer> <!--optional-->
+        </staticBinding>
+        """
+        static_bindings = []
+        static_config = {}
+        static_config['macAddress'] = port['mac_address']
+        static_config['hostname'] = port['id']
+        static_config['leaseTime'] = cfg.CONF.nsxv.dhcp_lease_time
+
+        for fixed_ip in port['fixed_ips']:
+            # Query the subnet to get gateway and DNS
+            try:
+                subnet_id = fixed_ip['subnet_id']
+                subnet = self.nsxv_plugin._get_subnet(context, subnet_id)
+            except n_exc.SubnetNotFound:
+                LOG.debug("No related subnet for port %s", port['id'])
+                continue
+            # Only configure if subnet has DHCP support
+            if not subnet['enable_dhcp']:
+                continue
+            static_config['ipAddress'] = fixed_ip['ip_address']
+            # Set gateway for static binding
+            static_config['defaultGateway'] = subnet['gateway_ip']
+            # set primary and secondary dns
+            name_servers = [dns['address']
+                            for dns in subnet['dns_nameservers']]
+            if len(name_servers) == 1:
+                static_config['primaryNameServer'] = name_servers[0]
+            elif len(name_servers) >= 2:
+                static_config['primaryNameServer'] = name_servers[0]
+                static_config['secondaryNameServer'] = name_servers[1]
+
+            static_bindings.append(static_config)
+        return static_bindings
+
     def update_dhcp_service_config(self, context, edge_id):
         """Reconfigure the DHCP to the edge."""
         # Get all networks attached to the edge
@@ -681,7 +725,7 @@ class EdgeManager(object):
         static_bindings = []
         for port in inst_ports:
             static_bindings.extend(
-                self.nsxv_plugin._create_static_binding(
+                self.create_static_binding(
                     context.elevated(), port))
         dhcp_request = {
             'featureType': "dhcp_4.0",