diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index a3e6b95776..2a32f2ede3 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 */ @@ -2674,6 +2800,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: @@ -2777,6 +2911,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