[PATCH 04/12] hyperv: add support for creating network adapters

Matt Coleman mcoleman at datto.com
Fri Jan 22 20:18:35 UTC 2021


Co-authored-by: Sri Ramanujam <sramanujam at datto.com>
Signed-off-by: Matt Coleman <matt at datto.com>
---
 src/hyperv/hyperv_driver.c            | 138 ++++++++++++++++++++++++++
 src/hyperv/hyperv_wmi_classes.h       |   2 +
 src/hyperv/hyperv_wmi_generator.input |  32 ++++++
 3 files changed, 172 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index ca75de98a9..8c34f5addd 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -978,6 +978,132 @@ hypervDomainAttachSerial(virDomainPtr domain, virDomainChrDefPtr serial)
 }
 
 
+static int
+hypervDomainAttachSyntheticEthernetAdapter(virDomainPtr domain,
+                                           virDomainNetDefPtr net,
+                                           char *hostname)
+{
+    hypervPrivate *priv = domain->conn->privateData;
+    g_autofree char *portResourceType = NULL;
+    unsigned char vsiGuid[VIR_UUID_BUFLEN];
+    char guidString[VIR_UUID_STRING_BUFLEN];
+    g_autofree char *virtualSystemIdentifiers = NULL;
+    char macString[VIR_MAC_STRING_BUFLEN];
+    g_autofree char *macAddressNoColons = NULL;
+    g_autoptr(GHashTable) portResource = NULL;
+    g_auto(WsXmlDocH) sepsdResponse = NULL;
+    g_auto(virBuffer) query = VIR_BUFFER_INITIALIZER;
+    g_autoptr(Msvm_VirtualEthernetSwitch) vSwitch = NULL;
+    g_autofree char *enabledState = NULL;
+    g_autofree char *switch__PATH = NULL;
+    g_autofree char *sepsd__PATH = NULL;
+    g_autofree char *sepsdInstanceID = NULL;
+    g_autofree char *sepsdInstanceEscaped = NULL;
+    g_autofree char *connectionResourceType = NULL;
+    g_autoptr(GHashTable) connectionResource = NULL;
+
+    /*
+     * Step 1: Create the Msvm_SyntheticEthernetPortSettingData object
+     * that holds half the settings for the new adapter we are creating
+     */
+    portResourceType = g_strdup_printf("%d", MSVM_RASD_RESOURCETYPE_ETHERNET_ADAPTER);
+
+    virUUIDGenerate(vsiGuid);
+    virUUIDFormat(vsiGuid, guidString);
+    virtualSystemIdentifiers = g_strdup_printf("{%s}", guidString);
+
+    virMacAddrFormat(&net->mac, macString);
+    macAddressNoColons = virStringReplace(macString, ":", "");
+
+    /* prepare embedded param */
+    portResource = hypervCreateEmbeddedParam(Msvm_SyntheticEthernetPortSettingData_WmiInfo);
+    if (!portResource)
+        return -1;
+
+    if (hypervSetEmbeddedProperty(portResource, "ResourceType", portResourceType) < 0)
+        return -1;
+
+    if (hypervSetEmbeddedProperty(portResource, "ResourceSubType",
+                                  "Microsoft:Hyper-V:Synthetic Ethernet Port") < 0)
+        return -1;
+
+    if (hypervSetEmbeddedProperty(portResource,
+                                  "VirtualSystemIdentifiers", virtualSystemIdentifiers) < 0)
+        return -1;
+
+    if (hypervSetEmbeddedProperty(portResource, "Address", macAddressNoColons) < 0)
+        return -1;
+
+    if (hypervSetEmbeddedProperty(portResource, "StaticMacAddress", "true") < 0)
+        return -1;
+
+    if (hypervMsvmVSMSAddResourceSettings(domain, &portResource,
+                                          Msvm_SyntheticEthernetPortSettingData_WmiInfo,
+                                          &sepsdResponse) < 0)
+        return -1;
+
+    /*
+     * Step 2: Get the Msvm_VirtualEthernetSwitch object
+     */
+    virBufferAsprintf(&query,
+                      MSVM_VIRTUALETHERNETSWITCH_WQL_SELECT "WHERE Name='%s'",
+                      net->data.bridge.brname);
+
+    if (hypervGetWmiClass(Msvm_VirtualEthernetSwitch, &vSwitch) < 0)
+        return -1;
+
+    if (!vSwitch)
+        return -1;
+
+    /*
+     * Step 3: Create the Msvm_EthernetPortAllocationSettingData object that
+     * holds the other half of the network configuration
+     */
+    enabledState = g_strdup_printf("%d", MSVM_ETHERNETPORTALLOCATIONSETTINGDATA_ENABLEDSTATE_ENABLED);
+
+    /* build the two __PATH variables */
+    switch__PATH = g_strdup_printf("\\\\%s\\Root\\Virtualization\\V2:"
+                                   "Msvm_VirtualEthernetSwitch.CreationClassName=\"Msvm_VirtualEthernetSwitch\","
+                                   "Name=\"%s\"",
+                                   hostname, vSwitch->data->Name);
+
+    /* Get the sepsd instance ID out of the XML response */
+    sepsdInstanceID = hypervGetInstanceIDFromXMLResponse(sepsdResponse);
+    sepsdInstanceEscaped = virStringReplace(sepsdInstanceID, "\\", "\\\\");
+    sepsd__PATH = g_strdup_printf("\\\\%s\\root\\virtualization\\v2:"
+                                  "Msvm_SyntheticEthernetPortSettingData.InstanceID=\"%s\"",
+                                  hostname, sepsdInstanceEscaped);
+
+    connectionResourceType = g_strdup_printf("%d", MSVM_RASD_RESOURCETYPE_ETHERNET_CONNECTION);
+
+    connectionResource = hypervCreateEmbeddedParam(Msvm_EthernetPortAllocationSettingData_WmiInfo);
+    if (!connectionResource)
+        return -1;
+
+    if (hypervSetEmbeddedProperty(connectionResource, "EnabledState", enabledState) < 0)
+        return -1;
+
+    if (hypervSetEmbeddedProperty(connectionResource, "HostResource", switch__PATH) < 0)
+        return -1;
+
+    if (hypervSetEmbeddedProperty(connectionResource, "Parent", sepsd__PATH) < 0)
+        return -1;
+
+    if (hypervSetEmbeddedProperty(connectionResource, "ResourceType", connectionResourceType) < 0)
+        return -1;
+
+    if (hypervSetEmbeddedProperty(connectionResource,
+                                  "ResourceSubType", "Microsoft:Hyper-V:Ethernet Connection") < 0)
+        return -1;
+
+    if (hypervMsvmVSMSAddResourceSettings(domain, &connectionResource,
+                                          Msvm_EthernetPortAllocationSettingData_WmiInfo, NULL) < 0)
+        return -1;
+
+    return 0;
+}
+
+
 /*
  * Functions for deserializing device entries
  */
@@ -2685,6 +2811,14 @@ hypervDomainDefineXML(virConnectPtr conn, const char *xml)
         }
     }
 
+    /* Attach networks */
+    for (i = 0; i < def->nnets; i++) {
+        if (hypervDomainAttachSyntheticEthernetAdapter(domain, def->nets[i], hostname) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not attach network %lu"), i);
+            goto error;
+        }
+    }
+
     return domain;
 
  error:
@@ -2788,6 +2922,10 @@ hypervDomainAttachDeviceFlags(virDomainPtr domain, const char *xml, unsigned int
         if (hypervDomainAttachSerial(domain, dev->data.chr) < 0)
             return -1;
         break;
+    case VIR_DOMAIN_DEVICE_NET:
+        if (hypervDomainAttachSyntheticEthernetAdapter(domain, dev->data.net, hostname) < 0)
+            return -1;
+        break;
     default:
         /* unsupported device type */
         virReportError(VIR_ERR_INTERNAL_ERROR,
diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h
index eea24235a5..86a7124799 100644
--- a/src/hyperv/hyperv_wmi_classes.h
+++ b/src/hyperv/hyperv_wmi_classes.h
@@ -108,6 +108,7 @@ enum _Msvm_ResourceAllocationSettingData_ResourceType {
     MSVM_RASD_RESOURCETYPE_OTHER = 1,
     MSVM_RASD_RESOURCETYPE_IDE_CONTROLLER = 5,
     MSVM_RASD_RESOURCETYPE_PARALLEL_SCSI_HBA = 6,
+    MSVM_RASD_RESOURCETYPE_ETHERNET_ADAPTER = 10,
     MSVM_RASD_RESOURCETYPE_DISKETTE_DRIVE = 14,
     MSVM_RASD_RESOURCETYPE_CD_DRIVE = 15,
     MSVM_RASD_RESOURCETYPE_DVD_DRIVE = 16,
@@ -115,6 +116,7 @@ enum _Msvm_ResourceAllocationSettingData_ResourceType {
     MSVM_RASD_RESOURCETYPE_STORAGE_EXTENT = 19,
     MSVM_RASD_RESOURCETYPE_SERIAL_PORT = 21,
     MSVM_RASD_RESOURCETYPE_LOGICAL_DISK = 31,
+    MSVM_RASD_RESOURCETYPE_ETHERNET_CONNECTION = 33,
 };
 
 
diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input
index df240361e6..f9d486bd4c 100644
--- a/src/hyperv/hyperv_wmi_generator.input
+++ b/src/hyperv/hyperv_wmi_generator.input
@@ -936,3 +936,35 @@ class Msvm_VirtualEthernetSwitch
     uint32   MaxVMQOffloads
     uint32   MaxIOVOffloads
 end
+
+
+class Msvm_VirtualEthernetSwitchManagementService
+    string   InstanceID
+    string   Caption
+    string   Description
+    string   ElementName
+    datetime InstallDate
+    string   Name
+    uint16   OperationalStatus[]
+    string   StatusDescriptions[]
+    string   Status
+    uint16   HealthState
+    uint16   CommunicationStatus
+    uint16   DetailedStatus
+    uint16   OperatingStatus
+    uint16   PrimaryStatus
+    uint16   EnabledState
+    string   OtherEnabledState
+    uint16   RequestedState
+    uint16   EnabledDefault
+    datetime TimeOfLastStateChange
+    uint16   AvailableRequestedStates[]
+    uint16   TransitioningToState
+    string   SystemCreationClassName
+    string   SystemName
+    string   CreationClassName
+    string   PrimaryOwnerName
+    string   PrimaryOwnerContact
+    string   StartMode
+    boolean  Started
+end
-- 
2.30.0





More information about the libvir-list mailing list