+Alin Guru – Sorry for the confusion. Alin is currently respinning this series. There was an associated bug that got fixed and he is updating the documentation for 3rd patch. I will ack v6 of this series.
Alin – Can you provide an update on this? Should we get this series into master and then update it instead? Thanks, Sairam From: Guru Shetty <g...@ovn.org<mailto:g...@ovn.org>> Date: Thursday, November 10, 2016 at 10:25 AM To: Sairam Venugopal <vsai...@vmware.com<mailto:vsai...@vmware.com>> Cc: "d...@openvswitch.org<mailto:d...@openvswitch.org>" <d...@openvswitch.org<mailto:d...@openvswitch.org>> Subject: Re: [ovs-dev] [PATCH v4 1/3] Windows: Add internal switch port per OVS bridge On 7 November 2016 at 13:47, Sairam Venugopal <vsai...@vmware.com<mailto:vsai...@vmware.com>> wrote: I had acked it earlier. Will re-ack that patch if needed. Sai, I meant v5 of the series and not patch 5. I guess, that was the confusion? It is here: https://patchwork.ozlabs.org/patch/669585/<https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.ozlabs.org_patch_669585_&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=VKtO-HY4GAbaVjtPhMHt7u-D6Jam2Vj9dGEdSfXWHCc&e=> Thanks, Sairam On 11/4/16, 7:55 AM, "Guru Shetty" <g...@ovn.org<mailto:g...@ovn.org>> wrote: >On 10 October 2016 at 15:47, Sairam Venugopal ><vsai...@vmware.com<mailto:vsai...@vmware.com>> wrote: > >> Sorry for the delay in the review. >> >> Acked-by: Sairam Venugopal <vsai...@vmware.com<mailto:vsai...@vmware.com>> >> > >There is a v5 of this series. Would you mind looking at that. > > >> >> >> >> On 8/12/16, 6:06 PM, "Alin Serdean" >> <aserd...@cloudbasesolutions.com<mailto:aserd...@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 >> ><aserd...@cloudbasesolutions.com<mailto:aserd...@cloudbasesolutions.com>> >> >Acked-by: Paul Boca >> ><pb...@cloudbasesolutions.com<mailto:pb...@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<https://urldefense.proofpoint.com/v2/url?u=http-3A__automake.mk&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=7FMBKJHDwQ9SgM1pJC4UrMKEVV71xBFOUmT7cbbJ-lA&e=> >> > | 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<https://urldefense.proofpoint.com/v2/url?u=http-3A__automake.mk&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=7FMBKJHDwQ9SgM1pJC4UrMKEVV71xBFOUmT7cbbJ-lA&e=> >> > >> >b/lib/automake.mk<https://urldefense.proofpoint.com/v2/url?u=http-3A__automake.mk&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=7FMBKJHDwQ9SgM1pJC4UrMKEVV71xBFOUmT7cbbJ-lA&e=> >> >index 2faaeac..99bbdc0 100644 >> >--- >> >a/lib/automake.mk<https://urldefense.proofpoint.com/v2/url?u=http-3A__automake.mk&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=7FMBKJHDwQ9SgM1pJC4UrMKEVV71xBFOUmT7cbbJ-lA&e=> >> >+++ >> >b/lib/automake.mk<https://urldefense.proofpoint.com/v2/url?u=http-3A__automake.mk&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=7FMBKJHDwQ9SgM1pJC4UrMKEVV71xBFOUmT7cbbJ-lA&e=> >> >@@ -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<https://urldefense.proofpoint.com/v2/url?u=http-3A__temp-5Fdpif-5Fport.name&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=eQpxJWvhyOqNpoxEJmUQUV937loNokfnCs8JBuRfsZg&e=>)){ >> >+ VLOG_ERR("Could not delete wmi port with name: %s", >> >+ >> >temp_dpif_port.name<https://urldefense.proofpoint.com/v2/url?u=http-3A__temp-5Fdpif-5Fport.name&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=eQpxJWvhyOqNpoxEJmUQUV937loNokfnCs8JBuRfsZg&e=>); >> >+ }; >> >+ } >> >+#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 >> >d...@openvswitch.org<mailto:d...@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 >> d...@openvswitch.org<mailto:d...@openvswitch.org> >> >>https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailm >>an_listinfo_dev&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r= >>Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=s5NiOORo9oYojV_md5W4no7jk3y >>aVMhSM32myrFonRk&s=a2UZKIcPi4J9xe5RSgLj-CacGcP6Hrg_3HmYsCfPqyc&e= >> >_______________________________________________ >dev mailing list >d...@openvswitch.org<mailto:d...@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=s5NiOORo9oYojV_md5W4no7jk3yaVM >hSM32myrFonRk&s=a2UZKIcPi4J9xe5RSgLj-CacGcP6Hrg_3HmYsCfPqyc&e= _______________________________________________ dev mailing list d...@openvswitch.org<mailto:d...@openvswitch.org> https://mail.openvswitch.org/mailman/listinfo/ovs-dev<https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.openvswitch.org_mailman_listinfo_ovs-2Ddev&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=s7c7FvsOER1vHmCsJ9OFhdzWlk39ORsnlLSNPtZ14j0&e=> _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev