From 353ab6f9f8de235f6ec57c9982c4a86c2361534c Mon Sep 17 00:00:00 2001
From: Ionut Balutoiu <ibalutoiu@cloudbasesolutions.com>
Date: Wed, 29 Jun 2016 04:05:30 +0300
Subject: [PATCH] Added Hyper-V networking support

This patch adds hyperv mechanism driver to ml2_conf.ini template
and the required python package to the list of packages to install.

Change-Id: If23f22aea53ba5549160f44442567d57b8077af6
---
 hooks/neutron_api_context.py           |  8 +++++++-
 hooks/neutron_api_utils.py             |  9 +++++++--
 templates/kilo/ml2_conf.ini            |  2 ++
 tests/basic_deployment.py              |  7 ++++---
 unit_tests/test_neutron_api_context.py | 12 ++++++++----
 unit_tests/test_neutron_api_utils.py   |  3 ++-
 6 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/hooks/neutron_api_context.py b/hooks/neutron_api_context.py
index 98c4c636..cca59a9b 100644
--- a/hooks/neutron_api_context.py
+++ b/hooks/neutron_api_context.py
@@ -183,6 +183,7 @@ class NeutronCCContext(context.NeutronContext):
         ctxt['dhcp_agents_per_network'] = config('dhcp-agents-per-network')
         ctxt['overlay_network_type'] = self.neutron_overlay_network_type
         ctxt['external_network'] = config('neutron-external-network')
+        release = os_release('neutron-server')
         if config('neutron-plugin') in ['vsp']:
             _config = config()
             for k, v in _config.iteritems():
@@ -192,7 +193,7 @@ class NeutronCCContext(context.NeutronContext):
                 for unit in related_units(rid):
                     rdata = relation_get(rid=rid, unit=unit)
                     vsd_ip = rdata.get('vsd-ip-address')
-                    if os_release('neutron-server') >= 'kilo':
+                    if release >= 'kilo':
                         cms_id_value = rdata.get('nuage-cms-id')
                         log('relation data:cms_id required for'
                             ' nuage plugin: {}'.format(cms_id_value))
@@ -240,6 +241,11 @@ class NeutronCCContext(context.NeutronContext):
         ctxt['enable_ml2_port_security'] = config('enable-ml2-port-security')
         ctxt['enable_sriov'] = config('enable-sriov')
 
+        if release == 'kilo' or release >= 'mitaka':
+            ctxt['enable_hyperv'] = True
+        else:
+            ctxt['enable_hyperv'] = False
+
         return ctxt
 
 
diff --git a/hooks/neutron_api_utils.py b/hooks/neutron_api_utils.py
index a20194cb..2d46938d 100755
--- a/hooks/neutron_api_utils.py
+++ b/hooks/neutron_api_utils.py
@@ -285,9 +285,14 @@ def determine_packages(source=None):
                                             'neutron')
             packages.extend(pkgs)
 
-    if get_os_codename_install_source(source) >= 'kilo':
+    release = get_os_codename_install_source(source)
+
+    if release >= 'kilo':
         packages.extend(KILO_PACKAGES)
 
+    if release == 'kilo' or release >= 'mitaka':
+        packages.append('python-networking-hyperv')
+
     if config('neutron-plugin') == 'vsp':
         nuage_pkgs = config('nuage-packages').split()
         packages += nuage_pkgs
@@ -299,7 +304,7 @@ def determine_packages(source=None):
         for p in GIT_PACKAGE_BLACKLIST:
             if p in packages:
                 packages.remove(p)
-        if get_os_codename_install_source(source) >= 'kilo':
+        if release >= 'kilo':
             for p in GIT_PACKAGE_BLACKLIST_KILO:
                 packages.remove(p)
 
diff --git a/templates/kilo/ml2_conf.ini b/templates/kilo/ml2_conf.ini
index 5589ffb5..5265b950 100644
--- a/templates/kilo/ml2_conf.ini
+++ b/templates/kilo/ml2_conf.ini
@@ -16,6 +16,8 @@ type_drivers = {{ overlay_network_type }},vlan,flat,local
 tenant_network_types = {{ overlay_network_type }},vlan,flat,local
 {% if enable_sriov %}
 mechanism_drivers = openvswitch,l2population,sriovnicswitch
+{% elif enable_hyperv %}
+mechanism_drivers = openvswitch,hyperv,l2population
 {% else %}
 mechanism_drivers = openvswitch,l2population
 {% endif %}
diff --git a/tests/basic_deployment.py b/tests/basic_deployment.py
index 8d331ba7..65bda61e 100644
--- a/tests/basic_deployment.py
+++ b/tests/basic_deployment.py
@@ -572,13 +572,14 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
             }
         }
 
-        if self._get_openstack_release() >= self.trusty_kilo:
-            # Kilo or later
+        if (self._get_openstack_release() in
+           [self.trusty_liberty, self.wily_liberty]):
+            # Liberty
             expected['ml2'].update({
                 'mechanism_drivers': 'openvswitch,l2population'
             })
         else:
-            # Juno or earlier
+            # Earlier or later than Liberty
             expected['ml2'].update({
                 'mechanism_drivers': 'openvswitch,hyperv,l2population'
             })
diff --git a/unit_tests/test_neutron_api_context.py b/unit_tests/test_neutron_api_context.py
index 00150bfa..62c55ced 100644
--- a/unit_tests/test_neutron_api_context.py
+++ b/unit_tests/test_neutron_api_context.py
@@ -325,7 +325,8 @@ class NeutronCCContextTest(CharmTestCase):
             'quota_vip': 10,
             'vlan_ranges': 'physnet1:1000:2000',
             'vni_ranges': '1001:2000',
-            'enable_ml2_port_security': True
+            'enable_ml2_port_security': True,
+            'enable_hyperv': False
         }
         napi_ctxt = context.NeutronCCContext()
         with patch.object(napi_ctxt, '_ensure_packages'):
@@ -364,7 +365,8 @@ class NeutronCCContextTest(CharmTestCase):
             'vlan_ranges': 'physnet1:1000:2000',
             'vni_ranges': '1001:2000,3001:4000',
             'network_providers': 'physnet2,physnet3',
-            'enable_ml2_port_security': True
+            'enable_ml2_port_security': True,
+            'enable_hyperv': False
         }
         napi_ctxt = context.NeutronCCContext()
         with patch.object(napi_ctxt, '_ensure_packages'):
@@ -406,7 +408,8 @@ class NeutronCCContextTest(CharmTestCase):
             'quota_vip': 10,
             'vlan_ranges': 'physnet1:1000:2000',
             'vni_ranges': '1001:2000',
-            'enable_ml2_port_security': True
+            'enable_ml2_port_security': True,
+            'enable_hyperv': False
         }
         napi_ctxt = context.NeutronCCContext()
         with patch.object(napi_ctxt, '_ensure_packages'):
@@ -442,7 +445,8 @@ class NeutronCCContextTest(CharmTestCase):
             'quota_vip': 10,
             'vlan_ranges': 'physnet1:1000:2000',
             'vni_ranges': '1001:2000',
-            'enable_ml2_port_security': True
+            'enable_ml2_port_security': True,
+            'enable_hyperv': False
         }
         napi_ctxt = context.NeutronCCContext()
         with patch.object(napi_ctxt, '_ensure_packages'):
diff --git a/unit_tests/test_neutron_api_utils.py b/unit_tests/test_neutron_api_utils.py
index 61751a4e..61acd539 100644
--- a/unit_tests/test_neutron_api_utils.py
+++ b/unit_tests/test_neutron_api_utils.py
@@ -126,7 +126,8 @@ class TestNeutronAPIUtils(CharmTestCase):
         self.get_os_codename_install_source.return_value = 'kilo'
         pkg_list = nutils.determine_packages()
         expect = deepcopy(nutils.BASE_PACKAGES)
-        expect.extend(['neutron-server', 'neutron-plugin-ml2'])
+        expect.extend(['neutron-server', 'neutron-plugin-ml2',
+                      'python-networking-hyperv'])
         expect.extend(nutils.KILO_PACKAGES)
         self.assertItemsEqual(pkg_list, expect)