Import KVM VM: Autodetect vlan id from bridge name (#11507)
* Get vlan from bridge name while importing kvm instances
* Fix LibvirtReplugNicCommandWrapperTest
* Cleanup MultiNetworkSelection.vue
* getting the vlanid from the /proc/net/vlan/<pif> file instead of the bridge name
* Update plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetUnmanagedInstancesCommandWrapper.java
Co-authored-by: dahn <daan.hoogland@gmail.com>
* Don't call sendValuesTimed from getDefaultNetwork as it's causing an infinte loop
* set default network values in setDefaultValues instead of getDefaultNetwork
---------
Co-authored-by: Wei Zhou <weizhou@apache.org>
Co-authored-by: dahn <daan.hoogland@gmail.com>
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 19c6e71..2d63a66 100644
--- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -1797,6 +1797,20 @@
return "";
}
+ public Integer getVlanIdForBridge(final String bridge) {
+ String pif = matchPifFileInDirectory(bridge);
+ final File vlanfile = new File("/proc/net/vlan/" + pif);
+ if (vlanfile.isFile()) {
+ String vlan = Script.runSimpleBashScript("awk '/VID:/ {print $3}' /proc/net/vlan/" + pif);
+ try {
+ return Integer.parseInt(vlan);
+ } catch (final NumberFormatException e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
static String [] ifNamePatterns = {
"^eth",
"^bond",
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetUnmanagedInstancesCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetUnmanagedInstancesCommandWrapper.java
index e807bf3..b382613 100644
--- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetUnmanagedInstancesCommandWrapper.java
+++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetUnmanagedInstancesCommandWrapper.java
@@ -132,7 +132,7 @@
}
instance.setPowerState(getPowerState(libvirtComputingResource.getVmState(conn,domain.getName())));
instance.setMemory((int) LibvirtComputingResource.getDomainMemory(domain) / 1024);
- instance.setNics(getUnmanagedInstanceNics(parser.getInterfaces()));
+ instance.setNics(getUnmanagedInstanceNics(libvirtComputingResource, parser.getInterfaces()));
instance.setDisks(getUnmanagedInstanceDisks(parser.getDisks(),libvirtComputingResource, conn, domain.getName()));
instance.setVncPassword(getFormattedVncPassword(parser.getVncPasswd()));
if (parser.getBootType() != null) {
@@ -169,7 +169,7 @@
}
}
- private List<UnmanagedInstanceTO.Nic> getUnmanagedInstanceNics(List<LibvirtVMDef.InterfaceDef> interfaces) {
+ private List<UnmanagedInstanceTO.Nic> getUnmanagedInstanceNics(LibvirtComputingResource libvirtComputingResource, List<LibvirtVMDef.InterfaceDef> interfaces) {
final ArrayList<UnmanagedInstanceTO.Nic> nics = new ArrayList<>(interfaces.size());
int counter = 0;
for (LibvirtVMDef.InterfaceDef interfaceDef : interfaces) {
@@ -180,6 +180,10 @@
nic.setNetwork(interfaceDef.getDevName());
nic.setPciSlot(interfaceDef.getSlot().toString());
nic.setVlan(interfaceDef.getVlanTag());
+ if (nic.getVlan() == -1
+ && LibvirtVMDef.InterfaceDef.GuestNetType.BRIDGE.equals(interfaceDef.getNetType())) {
+ nic.setVlan(libvirtComputingResource.getVlanIdForBridge(interfaceDef.getBrName()));
+ }
nics.add(nic);
}
return nics;
diff --git a/ui/src/views/compute/wizard/MultiNetworkSelection.vue b/ui/src/views/compute/wizard/MultiNetworkSelection.vue
index 92d4a43..0e9983b 100644
--- a/ui/src/views/compute/wizard/MultiNetworkSelection.vue
+++ b/ui/src/views/compute/wizard/MultiNetworkSelection.vue
@@ -47,7 +47,7 @@
<a-select
style="width: 100%"
v-if="validNetworks[record.id] && validNetworks[record.id].length > 0"
- :defaultValue="validNetworks[record.id][0].id"
+ :defaultValue="getDefaultNetwork(record)"
@change="val => handleNetworkChange(record, val)"
showSearch
optionFilterProp="label"
@@ -265,7 +265,16 @@
this.values = {}
this.ipAddresses = {}
for (const item of this.items) {
- var network = this.validNetworks[item.id]?.[0] || null
+ let network = null
+ if (item.vlanid && item.vlanid !== -1) {
+ const matched = this.validNetworks[item.id].filter(x => Number(x.vlan) === item.vlanid)
+ if (matched.length > 0) {
+ network = matched[0]
+ }
+ }
+ if (!network) {
+ network = this.validNetworks[item.id]?.[0] || null
+ }
this.values[item.id] = network ? network.id : ''
this.ipAddresses[item.id] = (!network || network.type === 'L2') ? null : 'auto'
this.setIpAddressEnabled(item, network)
@@ -280,6 +289,9 @@
}
this.sendValuesTimed()
},
+ getDefaultNetwork (record) {
+ return this.values[record.id] || this.validNetworks[record.id]?.[0]?.id
+ },
sendValuesTimed () {
clearTimeout(this.sendValuesTimer)
this.sendValuesTimer = setTimeout(() => {