[ovs-dev] [PATCH 1/4] windows: Add internal switch port per OVS bridge

Alin Serdean aserdean at cloudbasesolutions.com
Tue May 10 00:03:13 UTC 2016


This patch updates the following commands in the vswitch:
ovs-vsctl add-br br-test
ovs-vsctl del-br br-test

ovs-vsctl add-br br-test:
    This command will now create an internal port on the MSFT virtual switch
  using the WMI interface from Msvm_VirtualEthernetSwitchManagementService
  leveraging the method AddResourceSettings.
    Before creating the actual port, the switch will be queried to see if there
  is not a port already created (good for restarts when restarting the
  vswitch daemon). If there is a port defined it will return success and log
  a message.
    After checking if the port already exists the command will also verify
  if the forwarding extension (windows datapath) is enabled and on a single
  switch. If it is not activated or if it is activated on multiple switches
  it will return an error and a message will be logged.
    After the port was created on the switch, we will disable the adapter on
  the host and rename to the corresponding OVS bridge name for consistency.
    The user will enable and set the values he wants after creation.

ovs-vsctl del-br br-test
    This command will remove an internal port on the MSFT virtual switch
  using the Msvm_VirtualEthernetSwitchManagementService class and executing
  the method RemoveResourceSettings.

Both commands will be blocking until the WMI job is finished, this allows us
to guarantee that the ports are created and their name are set before issuing
a netlink message to the windows datapath.

This patch also includes helpers for normal WMI retrievals and initializations.
Appveyor and documentation has been modified to include the libraries needed
for COM objects.

This patch was tested individually using IMallocSpy and CRT heap checks
to ensure no new memory leaks are introduced.

Tested on the following OS's:
Windows 2012 and Windows 2012r2

Signed-off-by: Alin Gabriel Serdean <aserdean at cloudbasesolutions.com>
---
 INSTALL.Windows.md |   76 ++--
 appveyor.yml       |    2 +-
 lib/automake.mk    |    4 +-
 lib/dpif-netlink.c |   25 +-
 lib/wmi.c          | 1197 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/wmi.h          |   51 +++
 6 files changed, 1309 insertions(+), 46 deletions(-)
 create mode 100644 lib/wmi.c
 create mode 100644 lib/wmi.h

diff --git a/INSTALL.Windows.md b/INSTALL.Windows.md
index 6b0f5d8..f86bf98 100644
--- a/INSTALL.Windows.md
+++ b/INSTALL.Windows.md
@@ -72,9 +72,9 @@ or from a distribution tar ball.
   directories, etc. For example,
 
     % ./configure CC=./build-aux/cccl LD="`which link`" \
-      LIBS="-lws2_32 -liphlpapi" --prefix="C:/openvswitch/usr" \
-      --localstatedir="C:/openvswitch/var" --sysconfdir="C:/openvswitch/etc" \
-       --with-pthread="C:/pthread"
+      LIBS="-lws2_32 -liphlpapi -lwbemuuid -lole32 -loleaut32" \
+      --prefix="C:/openvswitch/usr" --localstatedir="C:/openvswitch/var" \
+      --sysconfdir="C:/openvswitch/etc" --with-pthread="C:/pthread"
 
     By default, the above enables compiler optimization for fast code.
     For default compiler optimization, pass the "--with-debug" configure
@@ -125,9 +125,10 @@ Note down the directory where OpenSSL is installed (e.g.: C:/OpenSSL-Win32).
 For example,
 
     % ./configure CC=./build-aux/cccl LD="`which link`"  \
-    LIBS="-lws2_32 -liphlpapi" --prefix="C:/openvswitch/usr" \
-    --localstatedir="C:/openvswitch/var" --sysconfdir="C:/openvswitch/etc" \
-    --with-pthread="C:/pthread" --enable-ssl --with-openssl="C:/OpenSSL-Win32"
+    LIBS="-lws2_32 -liphlpapi -lwbemuuid -lole32 -loleaut32" \
+    --prefix="C:/openvswitch/usr" --localstatedir="C:/openvswitch/var" \
+    --sysconfdir="C:/openvswitch/etc" --with-pthread="C:/pthread" \
+    --enable-ssl --with-openssl="C:/OpenSSL-Win32"
 
 * Run make for the ported executables.
 
@@ -142,10 +143,11 @@ level 'make' will invoke building the kernel datapath, if the
 For example,
 
     % ./configure CC=./build-aux/cccl LD="`which link`" \
-    LIBS="-lws2_32 -liphlpapi" --prefix="C:/openvswitch/usr" \
-    --localstatedir="C:/openvswitch/var" --sysconfdir="C:/openvswitch/etc" \
-    --with-pthread="C:/pthread" --enable-ssl \
-    --with-openssl="C:/OpenSSL-Win32" --with-vstudiotarget="<target type>"
+    LIBS="-lws2_32 -liphlpapi -lwbemuuid -lole32 -loleaut32" \
+    --prefix="C:/openvswitch/usr" --localstatedir="C:/openvswitch/var" \
+    --sysconfdir="C:/openvswitch/etc" --with-pthread="C:/pthread" \
+    --enable-ssl --with-openssl="C:/OpenSSL-Win32" \
+    --with-vstudiotarget="<target type>"
 
     Possible values for "<target type>" are:
     "Debug" and "Release"
@@ -180,14 +182,11 @@ during boot.  The following commands can be used:
 Note: you may have to restart the machine for the settings to take effect.
 
 03> In the Virtual Switch Manager configuration you can enable the Open vSwitch
-Extension on an existing switch or create a new switch.  If you are using an
-existing switch, make sure to enable the "Allow Management OS" option for VXLAN
-to work (covered later).
+Extension on an existing switch or create a new switch.
 
 The command to create a new switch named 'OVS-Extended-Switch' using a physical
 NIC named 'Ethernet 1' is:
-    % New-VMSwitch "OVS-Extended-Switch" -AllowManagementOS $true \
-                   -NetAdapterName "Ethernet 1"
+    % New-VMSwitch "OVS-Extended-Switch" -NetAdapterName "Ethernet 1"
 
 Note: you can obtain the list of physical NICs on the host using
 'Get-NetAdapter' command.
@@ -281,20 +280,20 @@ use that name('Ethernet0') as a special name to refer to that adapter.
 Note: Currently, we assume that the Hyper-V switch on which OVS extension is
 enabled has a single physical NIC connected to it.
 
-Internal port is the virtual adapter created on the Hyper-V switch using the
-'AllowManagementOS' setting.  This has already been setup while creating the
-switch using the instructions above.  In OVS for Hyper-V, we use a the name of
-that specific adapter as a special name to refer to that adapter. By default it
-is created under the following rule "vEthernet (<name of the switch>)".
+Internal ports are the virtual adapters created on the Hyper-V switch using the
+ovs-vsctl add-br <bridge> command. By default they are created under the
+following rule "<name of bridge>" and the adapters are disabled. One needs to
+enable them and set the corresponding values to it to make them IP-able.
 
 As a whole example, if we issue the following in a powershell console:
-PS C:\package\binaries> Get-NetAdapter | select Name,MacAddress,InterfaceDescription
+PS C:\package\binaries> Get-NetAdapter | select Name,InterfaceDescription
 
-Name                   MacAddress         InterfaceDescription
-----                   ----------         --------------------
-Ethernet1              00-0C-29-94-05-65  Intel(R) PRO/1000 MT Network Connection
-vEthernet (external)   00-0C-29-94-05-5B  Hyper-V Virtual Ethernet Adapter #2
-Ethernet0              00-0C-29-94-05-5B  Intel(R) PRO/1000 MT Network Connection #2
+Name                   InterfaceDescription
+----                   --------------------
+Ethernet1              Intel(R) PRO/1000 MT Network Connection
+br-pif                 Hyper-V Virtual Ethernet Adapter #2
+Ethernet0              Intel(R) PRO/1000 MT Network Connection #2
+br-int                 Hyper-V Virtual Ethernet Adapter #3
 
 PS C:\package\binaries> Get-VMSwitch
 
@@ -303,12 +302,11 @@ Name     SwitchType NetAdapterInterfaceDescription
 external External   Intel(R) PRO/1000 MT Network Connection #2
 
 
-We can see that we have a switch(external) created upon adapter name 'Ethernet0'
-with an internal port under name 'vEthernet (external)'. Thus resulting into the
-following ovs-vsctl commands
+We can see that we have a switch(external) created upon adapter name
+'Ethernet0' with the internal ports under name 'br-pif' and 'br-int'. Thus
+resulting into the following ovs-vsctl commands
 
     % ovs-vsctl add-port br-pif Ethernet0
-    % ovs-vsctl add-port br-pif "vEthernet (external)"
 
 * Dumping the ports should show the additional ports that were just added.
   Sample output shows up as follows:
@@ -317,18 +315,17 @@ following ovs-vsctl commands
     system at ovs-system:
             lookups: hit:0 missed:0 lost:0
             flows: 0
-            port 4: vEthernet (external) (internal) <<< 'AllowManagementOS'
-                                                         adapter on
-                                                         Hyper-V switch
-            port 2: br-pif (internal)
-            port 1: br-int (internal)
+            port 2: br-pif (internal)               <<< internal port
+                                                        adapter on
+                                                        Hyper-V switch
+            port 1: br-int (internal)               <<< internal port
+                                                        adapter on
+                                                        Hyper-V switch
             port 3: Ethernet0                       <<< Physical NIC
 
     % ovs-vsctl show
     a56ec7b5-5b1f-49ec-a795-79f6eb63228b
         Bridge br-pif
-            Port "vEthernet (external)"
-                Interface "vEthernet (external)"
             Port br-pif
                 Interface br-pif
                     type: internal
@@ -374,8 +371,7 @@ with OVS extension enabled.
     system at ovs-system:
             lookups: hit:0 missed:0 lost:0
             flows: 0
-            port 4: vEthernet (external) (internal)
-            port 5: ovs-port-a
+            port 4: ovs-port-a
             port 2: br-pif (internal)
             port 1: br-int (internal
             port 3: Ethernet0
@@ -383,8 +379,6 @@ with OVS extension enabled.
     % ovs-vsctl show
     4cd86499-74df-48bd-a64d-8d115b12a9f2
         Bridge br-pif
-            Port "vEthernet (external)"
-                Interface "vEthernet (external)"
             Port "Ethernet0"
                 Interface "Ethernet0"
             Port br-pif
diff --git a/appveyor.yml b/appveyor.yml
index 422c4af..a152d1e 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -41,5 +41,5 @@ build_script:
 - C:\MinGW\msys\1.0\bin\bash -lc "cp /c/pthreads-win32/Pre-built.2/dll/x86/*.dll /c/openvswitch/."
 - C:\MinGW\msys\1.0\bin\bash -lc "mv /bin/link.exe /bin/link_copy.exe"
 - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./boot.sh"
-- C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./configure CC=build-aux/cccl LD=\"`which link`\" LIBS=\"-lws2_32 -liphlpapi\" --with-pthread=C:/pthreads-win32/Pre-built.2 --with-openssl=C:/OpenSSL-Win32 --with-vstudiotarget=\"Debug\""
+- C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./configure CC=build-aux/cccl LD=\"`which link`\" LIBS=\"-lws2_32 -liphlpapi -lwbemuuid -lole32 -loleaut32\" --with-pthread=C:/pthreads-win32/Pre-built.2 --with-openssl=C:/OpenSSL-Win32 --with-vstudiotarget=\"Debug\""
 - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && make"
diff --git a/lib/automake.mk b/lib/automake.mk
index affbb5c..80369f2 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -369,7 +369,9 @@ lib_libopenvswitch_la_SOURCES += \
 	lib/netlink-notifier.h \
 	lib/netlink-protocol.h \
 	lib/netlink-socket.c \
-	lib/netlink-socket.h
+	lib/netlink-socket.h \
+	lib/wmi.c \
+	lib/wmi.h
 endif
 
 if HAVE_POSIX_AIO
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index 015ba20..bcce709 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -58,6 +58,7 @@
 
 VLOG_DEFINE_THIS_MODULE(dpif_netlink);
 #ifdef _WIN32
+#include "wmi.h"
 enum { WINDOWS = 1 };
 #else
 enum { WINDOWS = 0 };
@@ -848,7 +849,15 @@ dpif_netlink_port_add__(struct dpif_netlink *dpif, struct netdev *netdev,
         netdev_linux_ethtool_set_flag(netdev, ETH_FLAG_LRO, "LRO", false);
 #endif
     }
-
+#ifdef _WIN32
+    if (request.type == OVS_VPORT_TYPE_INTERNAL) {
+        if (!create_wmi_port(name)){
+            VLOG_ERR("Could not create wmi internal port with name:%s", name);
+            vport_del_socksp(dpif, socksp);
+            return EINVAL;
+        };
+    }
+#endif
     tnl_cfg = netdev_get_tunnel_config(netdev);
     if (tnl_cfg && (tnl_cfg->dst_port != 0 || tnl_cfg->exts)) {
         ofpbuf_use_stack(&options, options_stub, sizeof options_stub);
@@ -940,6 +949,16 @@ dpif_netlink_port_del__(struct dpif_netlink *dpif, odp_port_t port_no)
     vport.cmd = OVS_VPORT_CMD_DEL;
     vport.dp_ifindex = dpif->dp_ifindex;
     vport.port_no = port_no;
+#ifdef _WIN32
+    struct dpif_port temp_dpif_port;
+    dpif_netlink_port_query__(dpif, port_no, NULL, &temp_dpif_port);
+    if (!strcmp(temp_dpif_port.type, "internal")) {
+        if (!delete_wmi_port(temp_dpif_port.name)){
+            VLOG_ERR("Could not delete wmi port with name: %s",
+                     temp_dpif_port.name);
+        };
+    }
+#endif
     error = dpif_netlink_vport_transact(&vport, NULL, NULL);
 
     vport_del_channels(dpif, port_no);
@@ -2442,7 +2461,7 @@ dpif_netlink_is_internal_device(const char *name)
 
     return reply.type == OVS_VPORT_TYPE_INTERNAL;
 }
-

+
 /* Parses the contents of 'buf', which contains a "struct ovs_header" followed
  * by Netlink attributes, into 'vport'.  Returns 0 if successful, otherwise a
  * positive errno value.
@@ -2946,7 +2965,7 @@ dpif_netlink_flow_get_stats(const struct dpif_netlink_flow *flow,
     stats->used = flow->used ? get_32aligned_u64(flow->used) : 0;
     stats->tcp_flags = flow->tcp_flags ? *flow->tcp_flags : 0;
 }
-

+
 /* Logs information about a packet that was recently lost in 'ch' (in
  * 'dpif_'). */
 static void
diff --git a/lib/wmi.c b/lib/wmi.c
new file mode 100644
index 0000000..736c424
--- /dev/null
+++ b/lib/wmi.c
@@ -0,0 +1,1197 @@
+/*
+ * Copyright (c) 2016 Cloudbase Solutions Srl
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+#include "wmi.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <Windows.h>
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(wmi);
+
+/* WMI Job values */
+enum JobState
+{
+    starting = 3,
+    running = 4,
+    completed = 7,
+    wait = 4096
+};
+
+/* This function will output the appropriate message for a given HRESULT */
+void
+get_hres_error(HRESULT hres)
+{
+    char *error_msg = NULL;
+
+    if (FACILITY_WINDOWS == HRESULT_FACILITY(hres)) {
+        hres = HRESULT_CODE(hres);
+    }
+
+    if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                      FORMAT_MESSAGE_FROM_SYSTEM,
+                      NULL, hres, 0, error_msg, 0, NULL) != 0) {
+        VLOG_WARN("%s", error_msg);
+        LocalFree(error_msg);
+    } else {
+        VLOG_WARN("Could not find HRESULT description for: %#x.", hres);
+    }
+
+    return;
+}
+
+boolean
+check_return_value(HRESULT hres)
+{
+    if (FAILED(hres)) {
+        get_hres_error(hres);
+        return false;
+    }
+
+    return true;
+}
+
+/* This function retrieves the UINT16 value from a given class object with
+ * the field name field_name */
+uint16_t
+get_uint16_t_value(IWbemClassObject* pcls_obj, wchar_t* field_name)
+{
+    uint16_t retval = 0;
+
+    VARIANT vt_prop;
+    VariantInit(&vt_prop);
+    HRESULT hres = pcls_obj->lpVtbl->Get(pcls_obj, field_name, 0, &vt_prop,
+                                         0, 0);
+    retval = V_UI2(&vt_prop);
+    VariantClear(&vt_prop);
+    check_return_value(hres);
+
+    return retval;
+}
+
+/* This function retrieves the UINT values from a given class object with
+ * the field name field_name */
+unsigned int
+get_uint_value(IWbemClassObject* pcls_obj, wchar_t* field_name)
+{
+    unsigned retval = 0;
+
+    VARIANT vt_prop;
+    VariantInit(&vt_prop);
+    HRESULT hres = pcls_obj->lpVtbl->Get(pcls_obj,field_name, 0, &vt_prop,
+                                         0, 0);
+    retval = V_UI4(&vt_prop);
+    VariantClear(&vt_prop);
+    check_return_value(hres);
+
+    return retval;
+}
+
+/* This function retrieves the unsigned short value from a given class object
+ * with the field name field_name */
+unsigned short
+get_ushort_value(IWbemClassObject* pcls_obj, wchar_t* field_name)
+{
+    unsigned short retval = 0;
+
+    VARIANT vt_prop;
+    VariantInit(&vt_prop);
+    HRESULT hres = pcls_obj->lpVtbl->Get(pcls_obj, field_name, 0, &vt_prop,
+                                         0, 0);
+    retval = V_UI2(&vt_prop);
+    VariantClear(&vt_prop);
+    check_return_value(hres);
+
+    return retval;
+}
+
+/* This function retrieves the BSTR value from a given class object with
+ * the field name field_name to a preallocated destination dest and with the
+ * maximum length max_dest_lgth */
+void
+get_str_value(IWbemClassObject* pcls_obj, wchar_t* field_name, wchar_t* dest,
+              int max_dest_lgth)
+{
+    VARIANT vt_prop;
+    VariantInit(&vt_prop);
+
+    HRESULT hres = pcls_obj->lpVtbl->Get(pcls_obj, field_name, 0, &vt_prop,
+                                         0, 0);
+
+    wcscpy_s(dest, max_dest_lgth, vt_prop.bstrVal);
+
+    VariantClear(&vt_prop);
+    check_return_value(hres);
+
+    return;
+}
+
+/* This function waits for a WMI job to finish and retrieves the error code
+ * if the job failed */
+HRESULT
+wait_for_job(IWbemServices* psvc, wchar_t* job_path)
+{
+    IWbemClassObject* pcls_obj = NULL;
+    HRESULT retval = 0;
+    uint16_t job_state = 0;
+    uint16_t error = 0;
+
+    do {
+        check_return_value(psvc->lpVtbl->GetObject(psvc, job_path, 0, NULL,
+                                                   &pcls_obj, NULL));
+
+        job_state = get_uint16_t_value(pcls_obj, L"JobState");
+
+
+        if (job_state == starting || job_state == running) {
+            Sleep(200);
+        } else if (job_state == completed) {
+            break;
+        } else {
+            /* Error occurred */
+            error = get_uint16_t_value(pcls_obj, L"ErrorCode");
+            VLOG_WARN("Job failed with error: %d", error);
+            retval = error;
+            break;
+        }
+
+        if (pcls_obj != NULL) {
+            pcls_obj->lpVtbl->Release(pcls_obj);
+            pcls_obj = NULL;
+        }
+    } while(TRUE);
+
+    if (pcls_obj != NULL) {
+        pcls_obj->lpVtbl->Release(pcls_obj);
+        pcls_obj = NULL;
+    }
+
+    return retval;
+}
+
+/* This function will initialize DCOM retrieving the WMI locator's ploc and
+ * the context associated to it */
+boolean
+initialize_wmi(IWbemLocator** ploc, IWbemContext** pcontext)
+{
+    HRESULT hres = 0;
+
+    /* Initialize COM */
+    hres = CoInitialize(NULL);
+
+    if (FAILED(hres)) {
+        return false;
+    }
+
+    /* Initialize COM security */
+    hres = CoInitializeSecurity(NULL,
+                                -1,
+                                NULL,
+                                NULL,
+                                RPC_C_AUTHN_LEVEL_DEFAULT,
+                                RPC_C_IMP_LEVEL_IMPERSONATE,
+                                NULL,
+                                EOAC_NONE,
+                                NULL);
+
+    if (FAILED(hres)) {
+        return false;
+    }
+
+    /* Fill context */
+    hres = CoCreateInstance(&CLSID_WbemContext,
+                            NULL,
+                            CLSCTX_INPROC_SERVER,
+                            &IID_IWbemContext,
+                            (void**)pcontext);
+
+    if (FAILED(hres)) {
+        return false;
+    }
+
+    fill_context(*pcontext);
+
+    /* Initialize locator's (ploc) to WMI */
+    hres = CoCreateInstance(&CLSID_WbemLocator,
+                            NULL,
+                            CLSCTX_INPROC_SERVER,
+                            &IID_IWbemLocator,
+                            (LPVOID *)ploc);
+
+    if (FAILED(hres)) {
+        return false;
+    }
+
+    return true;
+}
+
+/* This function connects the WMI locator's ploc to a given WMI provider
+ * defined in server and also sets the required security levels for a local
+ * connection to it */
+boolean
+connect_set_security(IWbemLocator* ploc, IWbemContext* pcontext,
+                     wchar_t* server, IWbemServices** psvc)
+{
+    HRESULT hres = 0;
+
+   /* Connect to server */
+    hres = ploc->lpVtbl->ConnectServer(ploc,
+                                       server,
+                                       NULL,
+                                       NULL,
+                                       0,
+                                       0,
+                                       0,
+                                       pcontext,
+                                       psvc);
+
+    if (FAILED(hres)) {
+        return false;
+    }
+
+    /* Set security levels */
+    hres = CoSetProxyBlanket((IUnknown *) *psvc,
+                             RPC_C_AUTHN_WINNT,
+                             RPC_C_AUTHZ_NONE,
+                             NULL,
+                             RPC_C_AUTHN_LEVEL_CALL,
+                             RPC_C_IMP_LEVEL_IMPERSONATE,
+                             NULL,
+                             EOAC_NONE);
+
+    if (FAILED(hres)) {
+        return false;
+    }
+
+    return true;
+}
+
+/* This function retrieves the first class object of a given enumeration
+ * outputted by a query and fails if it could not retrieve the object or there
+ * was no object to retrieve */
+boolean
+get_first_element(IEnumWbemClassObject* penumerate, IWbemClassObject** pcls_obj)
+{
+    ULONG retval = 0;
+
+    if (penumerate == NULL) {
+        VLOG_WARN("Enumeration Class Object is NULL. Cannot get the first object");
+        return false;
+    }
+
+    HRESULT hres = penumerate->lpVtbl->Next(penumerate, WBEM_INFINITE, 1,
+                                            pcls_obj, &retval);
+
+
+    if (retval == 0) {
+        return false;
+    }
+
+    return true;
+}
+
+/* This function transforms a char* into a wchar_t* */
+boolean
+tranform_wide(char* name, wchar_t* wide_name)
+{
+    ULONG size = strlen(name) + 1;
+
+    if (wide_name == NULL) {
+        VLOG_WARN("Parameter invalid");
+        return false;
+    }
+
+    mbstowcs(wide_name, name, size);
+
+    return true;
+}
+
+/* This function will delete a switch internal port with a given name as input
+ * executing "RemoveResourceSettings" as per documentation:
+ * https://msdn.microsoft.com/en-us/library/hh850277%28v=vs.85%29.aspx
+ * allocating the data and populating the needed fields to execute the
+ * method */
+boolean
+delete_wmi_port(char* name)
+{
+    HRESULT hres = 0;
+    boolean retval = true;
+
+    IWbemLocator* ploc = NULL;
+    IWbemServices* psvc = NULL;
+    IWbemContext* pcontext = NULL;
+    IWbemClassObject* pclass_instance = NULL;
+    IWbemClassObject* pinput_params = NULL;
+    IWbemClassObject* pcls_obj = NULL;
+    IWbemClassObject* pout_params = NULL;
+    IEnumWbemClassObject* penumerate = NULL;
+
+    VARIANT vt_prop;
+    VARIANT variant_array;
+    wchar_t* wide_name = NULL;
+    VariantInit(&vt_prop);
+    VariantInit(&variant_array);
+
+    LONG count[1];
+    SAFEARRAY* psa = SafeArrayCreateVector(VT_BSTR, 0, 1);
+
+    if (!initialize_wmi(&ploc, &pcontext)) {
+        VLOG_WARN("Could not initialize DCOM");
+        retval = false;
+        goto error;
+    }
+
+    if (!connect_set_security(ploc, pcontext, L"Root\\Virtualization\\v2",
+                              &psvc)) {
+        VLOG_WARN("Could not connect and set security for virtualization");
+        retval = false;
+        goto error;
+    }
+
+
+    /* Get the port with the element name equal to the name input */
+    wchar_t internal_port_query[2048];
+    wcscpy_s(internal_port_query, sizeof(internal_port_query),
+             L"SELECT * from Msvm_EthernetPortAllocationSettingData WHERE "
+             L"ElementName = \"");
+
+    wide_name = malloc((strlen(name) + 1) * sizeof(wchar_t));
+    if (wide_name == NULL) {
+        VLOG_WARN("Could not allocate memory for wide string");
+        retval = false;
+        goto error;
+    }
+
+    if (!tranform_wide(name, wide_name)) {
+        retval = false;
+        goto error;
+    }
+    wcscat_s(internal_port_query, sizeof(internal_port_query), wide_name);
+
+    wcscat_s(internal_port_query, sizeof(internal_port_query), L"\"");
+
+    hres = psvc->lpVtbl->ExecQuery(psvc,
+                                   L"WQL",
+                                   internal_port_query,
+                                   WBEM_FLAG_FORWARD_ONLY |
+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &penumerate);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    /* Get the element path on the switch which will be deleted */
+    if (!get_first_element(penumerate, &pcls_obj)) {
+        retval = false;
+        goto error;
+    }
+    penumerate->lpVtbl->Release(penumerate);
+    penumerate = NULL;
+
+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0, 0);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+    pcls_obj->lpVtbl->Release(pcls_obj);
+    pcls_obj = NULL;
+
+    /* Get the class object and the parameters it can have */
+    hres = psvc->lpVtbl->GetObject(psvc, L"Msvm_VirtualEthernetSwitchManagementService",
+                                   0, NULL, &pcls_obj, NULL);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    hres = pcls_obj->lpVtbl->GetMethod(pcls_obj, L"RemoveResourceSettings", 0,
+                                       &pinput_params, NULL);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+    pcls_obj->lpVtbl->Release(pcls_obj);
+    pcls_obj = NULL;
+
+    hres = pinput_params->lpVtbl->SpawnInstance(pinput_params, 0,
+                                                &pclass_instance);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    count[0] = 0;
+
+    hres = SafeArrayPutElement(psa, count, vt_prop.bstrVal);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    VariantClear(&vt_prop);
+    VariantInit(&vt_prop);
+    variant_array.vt = VT_ARRAY | VT_BSTR;
+    variant_array.parray = psa;
+
+    hres = pclass_instance->lpVtbl->Put(pclass_instance, L"ResourceSettings", 0,
+                                        &variant_array, 0);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    /* Get the object of the Msvm_VirtualEthernetSwitchManagementService which
+     * we need to invoke the port deletion */
+    hres = psvc->lpVtbl->ExecQuery(psvc,
+                                   L"WQL",
+                                   L"SELECT * FROM "
+                                   L"Msvm_VirtualEthernetSwitchManagementService",
+                                   WBEM_FLAG_FORWARD_ONLY |
+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &penumerate);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    if (!get_first_element(penumerate, &pcls_obj)) {
+        retval = false;
+        goto error;
+    }
+    penumerate->lpVtbl->Release(penumerate);
+    penumerate = NULL;
+
+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0, 0);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    pcls_obj->lpVtbl->Release(pcls_obj);
+    pcls_obj = NULL;
+
+    /* Invoke the delete port method */
+    hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal,
+                                    L"RemoveResourceSettings", 0,
+                                    pcontext, pclass_instance, &pout_params,
+                                    NULL);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+    VariantClear(&vt_prop);
+    VariantInit(&vt_prop);
+
+    hres = pout_params->lpVtbl->Get(pout_params, L"ReturnValue", 0,
+                                    &vt_prop, NULL, 0);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    UINT retvalue = get_uint_value(pout_params, L"ReturnValue");
+    if (retvalue != 0 && retvalue != wait) {
+        retval = false;
+        goto error;
+    }
+
+    if (retvalue == wait) {
+        WCHAR job_path[2048];
+        get_str_value(pout_params, L"Job", job_path,
+                      sizeof(job_path) / sizeof(WCHAR));
+        hres = wait_for_job(psvc, job_path);
+        if (FAILED(hres)) {
+            retval = false;
+        }
+    }
+
+error:
+    VariantClear(&vt_prop);
+
+    if (pcontext != NULL) {
+        pcontext->lpVtbl->Release(pcontext);
+        pcontext = NULL;
+    }
+    if (psa != NULL) {
+        SafeArrayDestroy(psa);
+        psa = NULL;
+    }
+    if (pcls_obj != NULL) {
+        pcls_obj->lpVtbl->Release(pcls_obj);
+        pcls_obj = NULL;
+    }
+    if (wide_name != NULL) {
+        free(wide_name);
+        wide_name = NULL;
+    }
+    if (!retval) {
+        get_hres_error(hres);
+    }
+    if (pinput_params != NULL) {
+        pinput_params->lpVtbl->Release(pinput_params);
+        pinput_params = NULL;
+    }
+    if (pout_params != NULL) {
+        pout_params->lpVtbl->Release(pout_params);
+        pout_params = NULL;
+    }
+    if (psvc != NULL) {
+        psvc->lpVtbl->Release(psvc);
+        psvc = NULL;
+    }
+    if (ploc != NULL) {
+        ploc->lpVtbl->Release(ploc);
+        ploc = NULL;
+    }
+    if (pclass_instance != NULL) {
+        pclass_instance->lpVtbl->Release(pclass_instance);
+        pclass_instance = NULL;
+    }
+    if (penumerate != NULL) {
+        penumerate->lpVtbl->Release(penumerate);
+        penumerate = NULL;
+    }
+
+    CoUninitialize();
+    return retval;
+}
+
+/* This function will create an internal port on the switch given a given name
+ * executing the method AddResourceSettings as per documentation:
+ * https://msdn.microsoft.com/en-us/library/hh850019%28v=vs.85%29.aspx
+ * It will verify if the port is already defined, in which case it will use
+ * the specific port, and if the forwarding extension "Open vSwitch Extension"
+ * is enabled and running only on a single switch.
+ * After the port is created and bound to the switch we will disable the
+ * created net adapter and rename it to match the OVS bridge name .*/
+boolean create_wmi_port(char* name) {
+    HRESULT hres = 0;
+    boolean retval = true;
+
+    BSTR text_object_string = NULL;
+
+    IWbemLocator *ploc = NULL;
+    IWbemContext *pcontext = NULL;
+    IWbemServices *psvc = NULL;
+    IEnumWbemClassObject* penumerate = NULL;
+    IWbemClassObject* defaultAllocationSettingData = NULL;
+    IWbemClassObject* defaultComputerSystem = NULL;
+    IWbemClassObject *pcls_obj = NULL;
+    IWbemClassObject* pclass = NULL;
+    IWbemClassObject* pinput_params = NULL;
+    IWbemClassObject* pclass_instance = NULL;
+    IWbemObjectTextSrc* text_object = NULL;
+    IWbemClassObject* pout_params = NULL;
+
+    wchar_t* wide_name = NULL;
+    VARIANT vt_prop;
+    VARIANT switch_setting_path;
+    VARIANT new_name;
+    SAFEARRAY* psa = SafeArrayCreateVector(VT_BSTR, 0, 1);
+    VARIANT variant_array;
+    LONG count[1];
+
+    VariantInit(&vt_prop);
+    VariantInit(&switch_setting_path);
+
+    if (!initialize_wmi(&ploc, &pcontext)) {
+        VLOG_WARN("Could not initialize DCOM");
+        retval = false;
+        goto error;
+    }
+
+    if (!connect_set_security(ploc, pcontext, L"Root\\Virtualization\\v2",
+                              &psvc)) {
+        VLOG_WARN("Could not connect and set security for virtualization");
+        retval = false;
+        goto error;
+    }
+
+    /* Check if the element already exists on the switch */
+    wchar_t internal_port_query[2048];
+    wcscpy_s(internal_port_query, sizeof(internal_port_query),
+             L"SELECT * FROM Msvm_InternalEthernetPort WHERE "
+             L"ElementName = \"");
+
+    wide_name = malloc((strlen(name) + 1) * sizeof(wchar_t));
+    if (wide_name == NULL) {
+        VLOG_WARN("Could not allocate memory for wide string");
+        retval = false;
+        goto error;
+    }
+
+    if (!tranform_wide(name, wide_name)) {
+        retval = false;
+        goto error;
+    }
+    wcscat_s(internal_port_query, sizeof(internal_port_query), wide_name);
+
+    wcscat_s(internal_port_query, sizeof(internal_port_query), L"\"");
+    hres = psvc->lpVtbl->ExecQuery(psvc,
+                                   L"WQL",
+                                   internal_port_query,
+                                   WBEM_FLAG_FORWARD_ONLY |
+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &penumerate);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    if (get_first_element(penumerate, &pcls_obj)) {
+        VLOG_WARN("Port with name: %s already defined on the switch", name);
+        goto error;
+    }
+    penumerate->lpVtbl->Release(penumerate);
+    penumerate = NULL;
+
+    /* Check if the extension is enabled and running. Also check if the
+     * the extension is enabled on more than one switch */
+    hres = psvc->lpVtbl->ExecQuery(psvc,
+                                   L"WQL",
+                                   L"SELECT * "
+                                   L"FROM Msvm_EthernetSwitchExtension "
+                                   L"WHERE "
+                                   L"ElementName=\"Open vSwitch Extension\"",
+                                   WBEM_FLAG_FORWARD_ONLY |
+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &penumerate);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    if (!get_first_element(penumerate, &pcls_obj)) {
+        VLOG_WARN("Open vSwitch Extension is not enabled on any switch");
+        retval = false;
+        goto error;
+    }
+    wcscpy_s(internal_port_query, sizeof(internal_port_query),
+             L"SELECT * FROM Msvm_VirtualEthernetSwitch WHERE Name = \"");
+
+    if (get_ushort_value(pcls_obj, L"EnabledState") == 2 &&
+        get_ushort_value(pcls_obj, L"HealthState") == 5)  {
+            hres = pcls_obj->lpVtbl->Get(pcls_obj, L"SystemName", 0,
+                                         &vt_prop, 0, 0);
+            if (FAILED(hres)) {
+                retval = false;
+                goto error;
+            }
+
+            wcscat_s(internal_port_query, sizeof(internal_port_query),
+                     vt_prop.bstrVal);
+    } else {
+        VLOG_WARN("Open vSwitch Extension is not running on any switch");
+        retval = false;
+        goto error;
+    }
+    VariantClear(&vt_prop);
+    pcls_obj->lpVtbl->Release(pcls_obj);
+    pcls_obj = NULL;
+
+    if (get_first_element(penumerate, &pcls_obj)) {
+        VLOG_WARN("The extension is activated on more than one switch, "
+                  "aborting operation. Please activate the extension on a "
+                  "single switch");
+        retval = false;
+        goto error;
+    }
+    penumerate->lpVtbl->Release(penumerate);
+    penumerate = NULL;
+    if (pcls_obj != NULL) {
+        pcls_obj->lpVtbl->Release(pcls_obj);
+        pcls_obj = NULL;
+    }
+
+    /* Get the switch object on which the extension is activated*/
+    wcscat_s(internal_port_query, sizeof(internal_port_query), L"\"");
+    hres = psvc->lpVtbl->ExecQuery(psvc,
+                                   L"WQL",
+                                   internal_port_query,
+                                   WBEM_FLAG_FORWARD_ONLY |
+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &penumerate);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    if (!get_first_element(penumerate, &pcls_obj)) {
+        VLOG_WARN("Could not get the switch object on which the extension is"
+                  "activated");
+        retval = false;
+        goto error;
+    }
+    penumerate->lpVtbl->Release(penumerate);
+    penumerate = NULL;
+
+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"ElementName", 0, &vt_prop, 0, 0);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    wcscpy_s(internal_port_query, sizeof(internal_port_query),
+             L"SELECT * FROM Msvm_VirtualEthernetSwitchSettingData WHERE "
+             L"ElementName = \"");
+
+    wcscat_s(internal_port_query, sizeof(internal_port_query),
+             vt_prop.bstrVal);
+    VariantClear(&vt_prop);
+
+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"Name", 0, &vt_prop, 0, 0);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+    pcls_obj->lpVtbl->Release(pcls_obj);
+    pcls_obj = NULL;
+
+    wcscat_s(internal_port_query, sizeof(internal_port_query),
+             L"\" AND VirtualSystemIdentifier = \"");
+    wcscat_s(internal_port_query, sizeof(internal_port_query),
+             vt_prop.bstrVal);
+    wcscat_s(internal_port_query, sizeof(internal_port_query),
+             L"\" AND InstanceID  = \"Microsoft:");
+    wcscat_s(internal_port_query, sizeof(internal_port_query),
+             vt_prop.bstrVal);
+    wcscat_s(internal_port_query, sizeof(internal_port_query),
+             L"\" AND Caption = \"Virtual Ethernet Switch Settings\" AND "
+             L"VirtualSystemType = \"DMTF:Virtual Ethernet Switch\"");
+
+    VariantClear(&vt_prop);
+
+    /* Retrieve the Msvm_VirtualEthernetSwitchSettingData pinned to the switch
+     * object on which the extension is activated */
+    hres = psvc->lpVtbl->ExecQuery(psvc,
+                                   L"WQL",
+                                   internal_port_query,
+                                   WBEM_FLAG_FORWARD_ONLY |
+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &penumerate);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    if (!get_first_element(penumerate, &pcls_obj)) {
+        VLOG_WARN("Could not get the first "
+                  "Msvm_VirtualEthernetSwitchSettingData object");
+        retval = false;
+        goto error;
+    }
+    penumerate->lpVtbl->Release(penumerate);
+    penumerate = NULL;
+
+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &switch_setting_path,
+                                 0, 0);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+    pcls_obj->lpVtbl->Release(pcls_obj);
+    pcls_obj = NULL;
+
+    /* Retrieve a default allocation port. This object will be later filled
+     * with optional data to create an switch internal port */
+    hres = psvc->lpVtbl->ExecQuery(psvc,
+                                   L"WQL",
+                                   L"SELECT * FROM "
+                                   L"Msvm_EthernetPortAllocationSettingData "
+                                   L"WHERE InstanceID LIKE '%%%%\\\\Default' "
+                                   L"AND ResourceSubType = "
+                                   L"'Microsoft:Hyper-V:Ethernet Connection'",
+                                   WBEM_FLAG_FORWARD_ONLY |
+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &penumerate);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    if (!get_first_element(penumerate, &defaultAllocationSettingData)) {
+        VLOG_WARN("Could not retrieve default allocation port object");
+        retval = false;
+        goto error;
+    }
+    penumerate->lpVtbl->Release(penumerate);
+    penumerate = NULL;
+
+    /* Retrieve the default computer system on which the port allocation will
+     * be hosted */
+    hres = psvc->lpVtbl->ExecQuery(psvc,
+                                   L"WQL",
+                                   L"SELECT * FROM Msvm_ComputerSystem WHERE "
+                                   L"Description = \"Microsoft Hosting "
+                                   L"Computer System\"",
+                                   WBEM_FLAG_FORWARD_ONLY |
+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &penumerate);
+
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    if (!get_first_element(penumerate, &defaultComputerSystem)) {
+        VLOG_WARN("Could not retrieve default computer system object");
+        retval = false;
+        goto error;
+    }
+
+    hres = defaultComputerSystem->lpVtbl->Get(defaultComputerSystem, L"__PATH",
+                                              0, &vt_prop, 0, 0);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+    penumerate->lpVtbl->Release(penumerate);
+    penumerate = NULL;
+
+    count[0] = 0;
+    hres = SafeArrayPutElement(psa, count, vt_prop.bstrVal);
+    VariantClear(&vt_prop);
+    variant_array.vt = VT_ARRAY | VT_BSTR;
+    variant_array.parray = psa;
+    hres = defaultAllocationSettingData->lpVtbl->Put(defaultAllocationSettingData,
+                                                     L"HostResource", 0,
+                                                     &variant_array, 0);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    hres = psvc->lpVtbl->GetObject(psvc,
+                                   L"Msvm_VirtualEthernetSwitchManagementService",
+                                   0, NULL, &pclass, NULL);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    hres = pclass->lpVtbl->GetMethod(pclass, L"AddResourceSettings", 0,
+                                     &pinput_params, NULL);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    hres = pinput_params->lpVtbl->SpawnInstance(pinput_params, 0,
+                                                &pclass_instance);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    /* Store the switch setting path retrieved above in the affected
+     * configuration field of the class instance */
+    hres = pclass_instance->lpVtbl->Put(pclass_instance,
+                                        L"AffectedConfiguration", 0,
+                                        &switch_setting_path, 0);
+
+    /* Store the port name in the ElementName field of the default allocation
+     * data */
+    vt_prop.vt = VT_BSTR;
+    vt_prop.bstrVal = SysAllocString(wide_name);
+    hres = defaultAllocationSettingData->lpVtbl->Put(defaultAllocationSettingData,
+                                                     L"ElementName", 0,
+                                                     &vt_prop, 0);
+    VariantClear(&vt_prop);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    /* Retrieve and store the serialized data of the modified default switch
+     * settings data */
+    hres = CoCreateInstance(&CLSID_WbemObjectTextSrc,
+                            NULL,
+                            CLSCTX_INPROC_SERVER,
+                            &IID_IWbemObjectTextSrc,
+                            (void**)&text_object);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    hres = text_object->lpVtbl->GetText(text_object, 0,
+                                        defaultAllocationSettingData,
+                                        WMI_OBJ_TEXT_WMI_DTD_2_0,
+                                        pcontext,
+                                        &text_object_string);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+    hres = SafeArrayDestroy(psa);
+    if (FAILED(hres)) {
+        VLOG_WARN("Could not clear the data of the array");
+        retval = false;
+        goto error;
+    }
+    psa = NULL;
+    psa = SafeArrayCreateVector(VT_BSTR, 0, 1);
+
+    count[0] = 0;
+    variant_array.parray = psa;
+    hres = SafeArrayPutElement(psa, count, text_object_string);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+    hres = pclass_instance->lpVtbl->Put(pclass_instance, L"ResourceSettings",
+                                        0, &variant_array, 0);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    /* Get the object of the switch service */
+    hres = psvc->lpVtbl->ExecQuery(psvc,
+                                   L"WQL",
+                                   L"SELECT * FROM "
+                                   L"Msvm_VirtualEthernetSwitchManagementService",
+                                   WBEM_FLAG_FORWARD_ONLY |
+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &penumerate);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    if (!get_first_element(penumerate, &pcls_obj)) {
+        VLOG_WARN("Could not get the object of the switch service");
+        retval = false;
+        goto error;
+    }
+    penumerate->lpVtbl->Release(penumerate);
+    penumerate = NULL;
+
+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0, 0);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+    pcls_obj->lpVtbl->Release(pcls_obj);
+    pcls_obj = NULL;
+
+    /* Try to add the port to the switch */
+    hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal,
+                                    L"AddResourceSettings", 0,
+                                    pcontext, pclass_instance, &pout_params,
+                                    NULL);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    UINT retvalue = get_uint_value(pout_params, L"ReturnValue");
+    if (retvalue != 0 && retvalue != wait) {
+        retval = false;
+        goto error;
+    }
+
+    if (retvalue == wait) {
+        WCHAR job_path[2048];
+        get_str_value(pout_params, L"Job", job_path,
+                      sizeof(job_path) / sizeof(WCHAR));
+        hres = wait_for_job(psvc, job_path);
+        if (FAILED(hres)) {
+            retval = false;
+            goto error;
+        }
+    }
+
+    pclass->lpVtbl->Release(pclass);
+    pclass = NULL;
+    pclass_instance->lpVtbl->Release(pclass_instance);
+    pclass_instance = NULL;
+    pinput_params->lpVtbl->Release(pinput_params);
+    pinput_params = NULL;
+    psvc->lpVtbl->Release(psvc);
+    psvc = NULL;
+    VariantClear(&vt_prop);
+
+    if (!connect_set_security(ploc, pcontext, L"Root\\StandardCimv2",
+                              &psvc)) {
+        VLOG_WARN("Could not connect and set security for CIM");
+        retval = false;
+        goto error;
+    }
+
+    wcscpy_s(internal_port_query, sizeof(internal_port_query),
+             L"SELECT * FROM MSFT_NetAdapter WHERE Name LIKE '%%");
+    wcscat_s(internal_port_query, sizeof(internal_port_query), wide_name);
+    wcscat_s(internal_port_query, sizeof(internal_port_query), L"%%'");
+
+    /* Get the object with the port name equal to name on the CIM */
+    hres = psvc->lpVtbl->ExecQuery(psvc,
+                                   L"WQL",
+                                   internal_port_query,
+                                   WBEM_FLAG_FORWARD_ONLY |
+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &penumerate);
+
+    if (!get_first_element(penumerate, &pcls_obj)) {
+        VLOG_WARN("Element name: %s not found in CIM", name);
+        retval = false;
+        goto error;
+    }
+    penumerate->lpVtbl->Release(penumerate);
+    penumerate = NULL;
+    pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0, 0);
+    pcls_obj->lpVtbl->Release(pcls_obj);
+    pcls_obj = NULL;
+
+    /* Disable the adapter with port name equal with name */
+    hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal, L"Disable", 0,
+                                    pcontext, NULL, NULL, NULL);
+
+    hres = psvc->lpVtbl->GetObject(psvc, L"MSFT_NetAdapter", 0, NULL, &pclass,
+                                   NULL);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    hres = pclass->lpVtbl->GetMethod(pclass, L"Rename", 0, &pinput_params,
+                                     NULL);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    hres = pinput_params->lpVtbl->SpawnInstance(pinput_params, 0,
+                                                &pclass_instance);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+
+    VariantInit(&new_name);
+    new_name.vt = VT_BSTR;
+    new_name.bstrVal = wide_name;
+    hres = pclass_instance->lpVtbl->Put(pclass_instance, L"NewName", 0,
+                                        &new_name, 0);
+    if (FAILED(hres)) {
+        retval = false;
+        goto error;
+    }
+    hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal, L"Rename", 0,
+                                    pcontext, pclass_instance, NULL, NULL);
+    if (FAILED(hres)) {
+        retval = false;
+    }
+
+error:
+    if (text_object_string != NULL) {
+        SysFreeString(text_object_string);
+        text_object_string = NULL;
+    }
+    if (psa != NULL) {
+        SafeArrayDestroy(psa);
+        psa = NULL;
+    }
+    if (ploc != NULL) {
+        ploc->lpVtbl->Release(ploc);
+        ploc = NULL;
+    }
+    if (pcontext != NULL) {
+        pcontext->lpVtbl->Release(pcontext);
+        pcontext = NULL;
+    }
+    if (psvc != NULL) {
+        psvc->lpVtbl->Release(psvc);
+        psvc = NULL;
+    }
+    if (penumerate != NULL) {
+        penumerate->lpVtbl->Release(penumerate);
+        penumerate = NULL;
+    }
+    if (defaultAllocationSettingData != NULL) {
+        defaultAllocationSettingData->lpVtbl->Release(defaultAllocationSettingData);
+        defaultAllocationSettingData = NULL;
+    }
+    if (defaultComputerSystem != NULL) {
+        defaultComputerSystem->lpVtbl->Release(defaultComputerSystem);
+        defaultComputerSystem = NULL;
+    }
+    if (pcls_obj != NULL) {
+        pcls_obj->lpVtbl->Release(pcls_obj);
+        pcls_obj = NULL;
+    }
+    if (pclass != NULL) {
+        pclass->lpVtbl->Release(pclass);
+        pclass = NULL;
+    }
+    if (pinput_params != NULL) {
+        pinput_params->lpVtbl->Release(pinput_params);
+        pinput_params = NULL;
+    }
+    if (pclass_instance != NULL) {
+        pclass_instance->lpVtbl->Release(pclass_instance);
+        pclass_instance = NULL;
+    }
+    if (text_object != NULL) {
+        text_object->lpVtbl->Release(text_object);
+        text_object = NULL;
+    }
+    if (pout_params != NULL) {
+        pout_params->lpVtbl->Release(pout_params);
+        pout_params = NULL;
+    }
+    if (wide_name != NULL) {
+        free(wide_name);
+        wide_name = NULL;
+    }
+    VariantClear(&vt_prop);
+    VariantClear(&switch_setting_path);
+
+    if (!retval) {
+        get_hres_error(hres);
+    }
+    CoUninitialize();
+    return retval;
+}
diff --git a/lib/wmi.h b/lib/wmi.h
new file mode 100644
index 0000000..0ce50c0
--- /dev/null
+++ b/lib/wmi.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016 Cloudbase Solutions Srl
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WMI_H
+#define WMI_H 1
+
+#include <windefs.h>
+#include <Wbemidl.h>
+
+static inline void fill_context(IWbemContext *pContext)
+{
+    VARIANT var;
+
+    /* IncludeQualifiers */
+    VariantInit(&var);
+    var.vt = VT_BOOL;
+    var.boolVal = VARIANT_TRUE;
+    pContext->lpVtbl->SetValue(pContext, L"IncludeQualifiers", 0, &var);
+    VariantClear(&var);
+
+    VariantInit(&var);
+    var.vt = VT_I4;
+    var.lVal = 0;
+    pContext->lpVtbl->SetValue(pContext, L"PathLevel", 0, &var);
+    VariantClear(&var);
+
+    /* ExcludeSystemProperties */
+    VariantInit(&var);
+    var.vt = VT_BOOL;
+    var.boolVal = VARIANT_FALSE;
+    pContext->lpVtbl->SetValue(pContext, L"ExcludeSystemProperties", 0, &var);
+    VariantClear(&var);
+}
+
+boolean create_wmi_port(char* name);
+boolean delete_wmi_port(char* name);
+
+#endif /* wmi.h */
-- 
1.9.5.msysgit.0
  



More information about the dev mailing list