Co-authored-by: Sri Ramanujam <sramanujam(a)datto.com>
Signed-off-by: Matt Coleman <matt(a)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