[ovs-dev] [PATCH v4 1/3] Windows: Add internal switch port per OVS bridge

Guru Shetty guru at ovn.org
Fri Nov 4 14:55:20 UTC 2016


On 10 October 2016 at 15:47, Sairam Venugopal <vsairam at vmware.com> wrote:

> Sorry for the delay in the review.
>
> Acked-by: Sairam Venugopal <vsairam at vmware.com>
>

There is a v5 of this series. Would you mind looking at that.


>
>
>
> On 8/12/16, 6:06 PM, "Alin Serdean" <aserdean at cloudbasesolutions.com>
> wrote:
>
> >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_VirtualEthernetSwitchManagemen
> tService
> >  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>
> >Acked-by: Paul Boca <pboca at cloudbasesolutions.com>
> >---
> >v4: address comments (sanitize input, short refactor)
> >    use full stop on comments
> >    update coding style
> >v3: rebase, add acked
> >v2: Address comments. Rebase
> >---
> > appveyor.yml       |    2 +-
> > lib/automake.mk    |    4 +-
> > lib/dpif-netlink.c |   21 +
> > lib/wmi.c          | 1276
> >++++++++++++++++++++++++++++++++++++++++++++++++++++
> > lib/wmi.h          |   51 +++
> > 5 files changed, 1352 insertions(+), 2 deletions(-)
> > create mode 100644 lib/wmi.c
> > create mode 100644 lib/wmi.h
> >
> >diff --git a/appveyor.yml b/appveyor.yml
> >index 0fd003b..1061df6 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 2faaeac..99bbdc0 100644
> >--- a/lib/automake.mk
> >+++ b/lib/automake.mk
> >@@ -387,7 +387,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 a39faa2..c8b0e37 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 };
> >@@ -849,6 +850,16 @@ dpif_netlink_port_add__(struct dpif_netlink *dpif,
> >struct netdev *netdev,
> > #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 +951,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);
> >diff --git a/lib/wmi.c b/lib/wmi.c
> >new file mode 100644
> >index 0000000..67f0873
> >--- /dev/null
> >+++ b/lib/wmi.c
> >@@ -0,0 +1,1276 @@
> >+/*
> >+ * 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
> >+ *
> >+ *
> >https://urldefense.proofpoint.com/v2/url?u=http-
> 3A__www.apache.org_license
> >s_LICENSE-2D2.0&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-
> YihVMNtXt-uEs&r=D
> >cruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=
> 1NgcutJOUfLwjikmUhz6W0zVXDR35
> >T75FV8sqiZ8ki8&s=6YJXIuUkmHpuGcJw64GoPVKdYVnqhnBsGxStg7axmxs&e=
> >+ *
> >+ * 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 job_status
> >+{
> >+    job_starting = 3,
> >+    job_running = 4,
> >+    job_completed = 7,
> >+    job_wait = 4096
> >+};
> >+
> >+static char *
> >+sanitize_port_name(char *name)
> >+{
> >+    char *p1, *p2;
> >+    p1 = p2 = name;
> >+
> >+    while (*p1) {
> >+        if ((*p1) == '\'' || (*p1) == '\"') {
> >+            p1++;
> >+        } else {
> >+            *p2 = *p1;
> >+            p2++;
> >+            p1++;
> >+        }
> >+    }
> >+    *p2 = '\0';
> >+    return name;
> >+}
> >+
> >+/* This function will output the appropriate message for a given
> >HRESULT.*/
> >+static void
> >+get_hres_error(HRESULT hres)
> >+{
> >+    char *error_msg = NULL;
> >+
> >+    if (FACILITY_WINDOWS == HRESULT_FACILITY(hres)) {
> >+        hres = HRESULT_CODE(hres);
> >+    }
> >+
> >+    VLOG_ERR("%s", ovs_format_message(hres));
> >+}
> >+
> >+static boolean
> >+check_return_value(HRESULT hres)
> >+{
> >+    if (FAILED(hres)) {
> >+        get_hres_error(hres);
> >+        return false;
> >+    }
> >+
> >+    return true;
> >+}
> >+
> >+static HRESULT
> >+get_variant_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
> >+                  VARIANT *value)
> >+{
> >+    HRESULT hres;
> >+
> >+    VariantInit(value);
> >+
> >+    hres = pcls_obj->lpVtbl->Get(pcls_obj, field_name, 0, value, 0, 0);
> >+
> >+    if (FAILED(hres)) {
> >+        VariantClear(value);
> >+    }
> >+
> >+    return hres;
> >+}
> >+
> >+/* This function retrieves the uint16_t value from a given class object
> >with
> >+ * the field name field_name. */
> >+static HRESULT
> >+get_uint16_t_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
> >+                   uint16_t *value)
> >+{
> >+    VARIANT vt_prop;
> >+    HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
> >+    *value = V_UI2(&vt_prop);
> >+
> >+    return hres;
> >+}
> >+
> >+/* This function retrieves the unsigned int values from a given class
> >object
> >+ * with the field name field_name. */
> >+static HRESULT
> >+get_uint_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
> >+               unsigned int *value)
> >+{
> >+    VARIANT vt_prop;
> >+    HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
> >+    *value = V_UI4(&vt_prop);
> >+
> >+    return hres;
> >+}
> >+
> >+/* This function retrieves the unsigned short value from a given class
> >object
> >+ * with the field name field_name. */
> >+static HRESULT
> >+get_ushort_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
> >+                 unsigned short *value)
> >+{
> >+    VARIANT vt_prop;
> >+    HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
> >+    *value = V_UI2(&vt_prop);
> >+
> >+    return hres;
> >+}
> >+
> >+/* 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. */
> >+static HRESULT
> >+get_str_value(IWbemClassObject *pcls_obj, wchar_t *field_name, wchar_t
> >*dest,
> >+              int max_dest_lgth)
> >+{
> >+    VARIANT vt_prop;
> >+    HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
> >+
> >+    if (wcscpy_s(dest, max_dest_lgth, vt_prop.bstrVal)) {
> >+        VariantClear(&vt_prop);
> >+        VLOG_WARN("get_str_value, wcscpy_s failed :%s",
> >ovs_strerror(errno));
> >+        return WBEM_E_FAILED;
> >+    }
> >+
> >+    VariantClear(&vt_prop);
> >+    return S_OK;
> >+}
> >+
> >+/* This function waits for a WMI job to finish and retrieves the error
> >code
> >+ * if the job failed */
> >+static 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 {
> >+        if(!check_return_value(psvc->lpVtbl->GetObject(psvc, job_path,
> >0, NULL,
> >+                                                       &pcls_obj,
> >NULL))) {
> >+            retval = WBEM_E_FAILED;
> >+            break;
> >+        }
> >+
> >+        retval = get_uint16_t_value(pcls_obj, L"JobState", &job_state);
> >+        if (FAILED(retval)) {
> >+            break;
> >+        }
> >+
> >+        if (job_state == job_starting || job_state == job_running) {
> >+            Sleep(200);
> >+        } else if (job_state == job_completed) {
> >+            break;
> >+        } else {
> >+            /* Error occurred. */
> >+            retval = get_uint16_t_value(pcls_obj, L"ErrorCode", &error);
> >+            if (FAILED(retval)) {
> >+                break;
> >+            }
> >+            VLOG_WARN("Job failed with error: %d", error);
> >+            retval = WBEM_E_FAILED;;
> >+            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. */
> >+static 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. */
> >+static 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 */
> >+static boolean
> >+get_first_element(IEnumWbemClassObject *penumerate,
> >+                  IWbemClassObject **pcls_obj)
> >+{
> >+    unsigned long 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 (!check_return_value(hres) || retval == 0) {
> >+        return false;
> >+    }
> >+
> >+    return true;
> >+}
> >+
> >+/* This function is a wrapper that transforms a char * into a wchar_t *
> >*/
> >+static boolean
> >+tranform_wide(char *name, wchar_t *wide_name)
> >+{
> >+    unsigned long size = strlen(name) + 1;
> >+    long long ret = 0;
> >+
> >+    if (wide_name == NULL) {
> >+        VLOG_WARN("Provided wide string is NULL");
> >+        return false;
> >+    }
> >+
> >+    ret = mbstowcs(wide_name, name, size);
> >+
> >+    if (ret == -1) {
> >+        VLOG_WARN("Invalid multibyte character is encountered");
> >+        return false;
> >+    } else if (ret == size) {
> >+        VLOG_WARN("Returned wide string not NULL terminated");
> >+        return false;
> >+    }
> >+
> >+    return true;
> >+}
> >+
> >+/* This function will delete a switch internal port with a given name as
> >input
> >+ * executing "RemoveResourceSettings" as per documentation:
> >+ *
> >https://urldefense.proofpoint.com/v2/url?u=https-
> 3A__msdn.microsoft.com_en
> >-2Dus_library_hh850277-2528v-3Dvs.85-2529.aspx&d=CwIGaQ&c=
> Sqcl0Ez6M0X8aeM6
> >7LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOW
> pJgEcEmNR3JEQ&
> >m=1NgcutJOUfLwjikmUhz6W0zVXDR35T75FV8sqiZ8ki8&s=
> tLEsQhF14PQ5LahGIKh2T8Z5h-
> >JPdlzvoU3ecWYc9hg&e=
> >+ * 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;
> >+
> >+    sanitize_port_name(name);
> >+    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 (psa == NULL) {
> >+        VLOG_WARN("Could not allocate memory for a SAFEARRAY");
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    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] = L"SELECT * from "
> >+        L"Msvm_EthernetPortAllocationSettingData  WHERE 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;
> >+    }
> >+
> >+    unsigned int retvalue = 0;
> >+    hres = get_uint_value(pout_params, L"ReturnValue", &retvalue);
> >+    if (FAILED(hres)) {
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    if (retvalue != 0 && retvalue != job_wait) {
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    if (retvalue == job_wait) {
> >+        WCHAR job_path[2048];
> >+        hres = get_str_value(pout_params, L"Job", job_path,
> >+                             sizeof(job_path) / sizeof(WCHAR));
> >+        if (FAILED(hres)) {
> >+            retval = false;
> >+            goto error;
> >+    }
> >+        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://urldefense.proofpoint.com/v2/url?u=https-
> 3A__msdn.microsoft.com_en
> >-2Dus_library_hh850019-2528v-3Dvs.85-2529.aspx&d=CwIGaQ&c=
> Sqcl0Ez6M0X8aeM6
> >7LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOW
> pJgEcEmNR3JEQ&
> >m=1NgcutJOUfLwjikmUhz6W0zVXDR35T75FV8sqiZ8ki8&s=
> KtkOaMFPsRkI7S8YEFN7XDLQgu
> >UWKnLJ-moHTsCF8Mo&e= .
> >+ * 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 *default_settings_data = NULL;
> >+    IWbemClassObject *default_system = 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);
> >+    sanitize_port_name(name);
> >+
> >+    if (psa == NULL) {
> >+        VLOG_WARN("Could not allocate memory for a SAFEARRAY");
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    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] = L"SELECT * FROM "
> >+    L"Msvm_InternalEthernetPort WHERE 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\" "
> >+                                   L"AND EnabledState=2 "
> >+                                   L"AND HealthState=5",
> >+                                   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 =
> >\"");
> >+
> >+    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);
> >+
> >+    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, &default_settings_data)) {
> >+        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, &default_system)) {
> >+        VLOG_WARN("Could not retrieve default computer system object");
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    hres = default_system->lpVtbl->Get(default_system, 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);
> >+
> >+    if (FAILED(hres)) {
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    VariantClear(&vt_prop);
> >+    variant_array.vt = VT_ARRAY | VT_BSTR;
> >+    variant_array.parray = psa;
> >+    hres = default_settings_data->lpVtbl->Put(default_settings_data,
> >+                                              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);
> >+
> >+    if (FAILED(hres)) {
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    /* 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 = default_settings_data->lpVtbl->Put(default_settings_data,
> >+                                              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,
> >+                                        default_settings_data,
> >+                                        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 = SafeArrayCreateVector(VT_BSTR, 0, 1);
> >+
> >+    if (psa == NULL) {
> >+        VLOG_WARN("Could not allocate memory for a SAFEARRAY");
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    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;
> >+    }
> >+
> >+    unsigned int retvalue = 0;
> >+    hres = get_uint_value(pout_params, L"ReturnValue", &retvalue);
> >+    if (FAILED(hres)) {
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    if (retvalue != 0 && retvalue != job_wait) {
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    if (retvalue == job_wait) {
> >+        WCHAR job_path[2048];
> >+        hres = get_str_value(pout_params, L"Job", job_path,
> >+                             sizeof(job_path) / sizeof(WCHAR));
> >+        if (FAILED(hres)) {
> >+            retval = false;
> >+            goto error;
> >+        }
> >+        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);
> >+
> >+    if (FAILED(hres)) {
> >+        retval = false;
> >+        goto error;
> >+    }
> >+
> >+    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 (default_settings_data != NULL) {
> >+        default_settings_data->lpVtbl->Release(default_settings_data);
> >+        default_settings_data = NULL;
> >+    }
> >+    if (default_system != NULL) {
> >+        default_system->lpVtbl->Release(default_system);
> >+        default_system = 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..28910e7
> >--- /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
> >+ *
> >+ *
> >https://urldefense.proofpoint.com/v2/url?u=http-
> 3A__www.apache.org_license
> >s_LICENSE-2D2.0&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-
> YihVMNtXt-uEs&r=D
> >cruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=
> 1NgcutJOUfLwjikmUhz6W0zVXDR35
> >T75FV8sqiZ8ki8&s=6YJXIuUkmHpuGcJw64GoPVKdYVnqhnBsGxStg7axmxs&e=
> >+ *
> >+ * 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 */
> >--
> >2.9.2.windows.1
> >
> >_______________________________________________
> >dev mailing list
> >dev at openvswitch.org
> >https://urldefense.proofpoint.com/v2/url?u=http-
> 3A__openvswitch.org_mailma
> >n_listinfo_dev&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-
> YihVMNtXt-uEs&r=Dc
> >ruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=
> 1NgcutJOUfLwjikmUhz6W0zVXDR35T
> >75FV8sqiZ8ki8&s=YMq7EI4iHIjlQKCYB1Lil7Pq3-80pelN7ZKYA4JvBb4&e=
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>



More information about the dev mailing list