This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 4a42e7e vmware, ui: update portgroup on network update (#5470)
4a42e7e is described below
commit 4a42e7ef9e2dd0766d9a3f425a7e8fbd66d0bdce
Author: Abhishek Kumar <[email protected]>
AuthorDate: Sun Oct 3 14:41:42 2021 +0530
vmware, ui: update portgroup on network update (#5470)
Enhanced update network form in the UI.
On network offering change for an isolated network,
- VMware portgroup should be updated accordingly.
- VMs on the network should be placed on the correct VMware portgroup based
on the network rate,
https://docs.cloudstack.apache.org/en/latest/adminguide/service_offerings.html#network-throttling.
Signed-off-by: Abhishek Kumar <[email protected]>
---
.../java/com/cloud/vm/VirtualMachineManager.java | 2 +-
.../com/cloud/vm/VirtualMachineManagerImpl.java | 18 +-
.../com/cloud/hypervisor/HypervisorGuruBase.java | 40 ++--
.../cloud/network/NetworkMigrationManagerImpl.java | 2 +-
.../java/com/cloud/network/NetworkModelImpl.java | 51 ++--
.../java/com/cloud/network/NetworkServiceImpl.java | 51 +++-
ui/public/locales/en.json | 7 +
ui/src/config/section/network.js | 11 +-
ui/src/views/AutogenView.vue | 7 +
ui/src/views/network/UpdateNetwork.vue | 257 +++++++++++++++++++++
ui/src/views/offering/AddNetworkOffering.vue | 51 ++--
.../hypervisor/vmware/mo/HypervisorHostHelper.java | 18 +-
12 files changed, 403 insertions(+), 112 deletions(-)
diff --git a/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java
b/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java
index f02395e..9ee2c2a 100644
--- a/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java
+++ b/engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java
@@ -221,7 +221,7 @@ public interface VirtualMachineManager extends Manager {
*/
VirtualMachineTO toVmTO(VirtualMachineProfile profile);
- boolean replugNic(Network network, NicTO nic, VirtualMachineTO vm,
ReservationContext context, DeployDestination dest) throws
ConcurrentOperationException,
+ boolean replugNic(Network network, NicTO nic, VirtualMachineTO vm, Host
dest) throws ConcurrentOperationException,
ResourceUnavailableException, InsufficientCapacityException;
VirtualMachine reConfigureVm(String vmUuid, ServiceOffering
oldServiceOffering, ServiceOffering newServiceOffering, Map<String, String>
customParameters, boolean sameHost) throws ResourceUnavailableException,
ConcurrentOperationException,
diff --git
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
index 854d5a2..3aa8a50 100755
---
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
+++
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -43,7 +43,6 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import com.cloud.api.ApiDBUtils;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
@@ -129,6 +128,7 @@ import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.manager.Commands;
import com.cloud.agent.manager.allocator.HostAllocator;
import com.cloud.alert.AlertManager;
+import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.dao.DomainRouterJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.vo.DomainRouterJoinVO;
@@ -4047,16 +4047,6 @@ public class VirtualMachineManagerImpl extends
ManagerBase implements VirtualMac
//3) Convert nicProfile to NicTO
final NicTO nicTO = toNicTO(nic,
vmProfile.getVirtualMachine().getHypervisorType());
- if (network != null) {
- final Map<NetworkOffering.Detail, String> details =
networkOfferingDetailsDao.getNtwkOffDetails(network.getNetworkOfferingId());
- if (details != null) {
-
details.putIfAbsent(NetworkOffering.Detail.PromiscuousMode,
NetworkOrchestrationService.PromiscuousMode.value().toString());
-
details.putIfAbsent(NetworkOffering.Detail.MacAddressChanges,
NetworkOrchestrationService.MacAddressChanges.value().toString());
-
details.putIfAbsent(NetworkOffering.Detail.ForgedTransmits,
NetworkOrchestrationService.ForgedTransmits.value().toString());
- }
- nicTO.setDetails(details);
- }
-
//4) plug the nic to the vm
s_logger.debug("Plugging nic for vm " + vm + " in network " +
network);
@@ -4566,7 +4556,7 @@ public class VirtualMachineManagerImpl extends
ManagerBase implements VirtualMac
}
@Override
- public boolean replugNic(final Network network, final NicTO nic, final
VirtualMachineTO vm, final ReservationContext context, final DeployDestination
dest) throws ConcurrentOperationException,
+ public boolean replugNic(final Network network, final NicTO nic, final
VirtualMachineTO vm, final Host host) throws ConcurrentOperationException,
ResourceUnavailableException, InsufficientCapacityException {
boolean result = true;
@@ -4576,14 +4566,14 @@ public class VirtualMachineManagerImpl extends
ManagerBase implements VirtualMac
final ReplugNicCommand replugNicCmd = new
ReplugNicCommand(nic, vm.getName(), vm.getType(), vm.getDetails());
final Commands cmds = new Commands(Command.OnError.Stop);
cmds.addCommand("replugnic", replugNicCmd);
- _agentMgr.send(dest.getHost().getId(), cmds);
+ _agentMgr.send(host.getId(), cmds);
final ReplugNicAnswer replugNicAnswer =
cmds.getAnswer(ReplugNicAnswer.class);
if (replugNicAnswer == null || !replugNicAnswer.getResult()) {
s_logger.warn("Unable to replug nic for vm " +
vm.getName());
result = false;
}
} catch (final OperationTimedoutException e) {
- throw new AgentUnavailableException("Unable to plug nic for
router " + vm.getName() + " in network " + network, dest.getHost().getId(), e);
+ throw new AgentUnavailableException("Unable to plug nic for
router " + vm.getName() + " in network " + network, host.getId(), e);
}
} else {
s_logger.warn("Unable to apply ReplugNic, vm " + router + " is not
in the right state " + router.getState());
diff --git a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java
b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java
index 5965e89..c3a087a 100644
--- a/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/main/java/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -25,8 +25,11 @@ import javax.inject.Inject;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.backup.Backup;
import
org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Command;
@@ -36,6 +39,7 @@ import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.gpu.GPU;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
+import com.cloud.network.Network;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkDetailVO;
@@ -61,9 +65,6 @@ import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicSecondaryIpDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
-import org.apache.cloudstack.framework.config.ConfigKey;
-import org.apache.cloudstack.framework.config.Configurable;
-import org.apache.commons.lang3.StringUtils;
public abstract class HypervisorGuruBase extends AdapterBase implements
HypervisorGuru, Configurable {
public static final Logger s_logger =
Logger.getLogger(HypervisorGuruBase.class);
@@ -97,6 +98,24 @@ public abstract class HypervisorGuruBase extends AdapterBase
implements Hypervis
public static ConfigKey<Boolean>
VmMinCpuSpeedEqualsCpuSpeedDividedByCpuOverprovisioningFactor = new
ConfigKey<Boolean>("Advanced", Boolean.class,
"vm.min.cpu.speed.equals.cpu.speed.divided.by.cpu.overprovisioning.factor",
"true",
"If we set this to 'true', a minimum CPU speed (cpu speed/
cpu.overprovisioning.factor) will be set on the VM, independent of using a
scalable service offering or not.", true, ConfigKey.Scope.Cluster);
+ private Map<NetworkOffering.Detail, String> getNicDetails(Network network)
{
+ if (network == null) {
+ s_logger.debug("Unable to get NIC details as the network is null");
+ return null;
+ }
+ Map<NetworkOffering.Detail, String> details =
networkOfferingDetailsDao.getNtwkOffDetails(network.getNetworkOfferingId());
+ if (details != null) {
+ details.putIfAbsent(NetworkOffering.Detail.PromiscuousMode,
NetworkOrchestrationService.PromiscuousMode.value().toString());
+ details.putIfAbsent(NetworkOffering.Detail.MacAddressChanges,
NetworkOrchestrationService.MacAddressChanges.value().toString());
+ details.putIfAbsent(NetworkOffering.Detail.ForgedTransmits,
NetworkOrchestrationService.ForgedTransmits.value().toString());
+ }
+ NetworkDetailVO pvlantypeDetail =
networkDetailsDao.findDetail(network.getId(), ApiConstants.ISOLATED_PVLAN_TYPE);
+ if (pvlantypeDetail != null) {
+ details.putIfAbsent(NetworkOffering.Detail.pvlanType,
pvlantypeDetail.getValue());
+ }
+ return details;
+ }
+
@Override
public NicTO toNicTO(NicProfile profile) {
NicTO to = new NicTO();
@@ -140,6 +159,7 @@ public abstract class HypervisorGuruBase extends
AdapterBase implements Hypervis
//FixMe: uuid and secondary IPs can be made part of nic profile
to.setUuid(UUID.randomUUID().toString());
}
+ to.setDetails(getNicDetails(network));
//check whether the this nic has secondary ip addresses set
//set nic secondary ip address in NicTO which are used for security
group
@@ -217,20 +237,6 @@ public abstract class HypervisorGuruBase extends
AdapterBase implements Hypervis
nicProfile.setBroadcastType(BroadcastDomainType.Native);
}
NicTO nicTo = toNicTO(nicProfile);
- final NetworkVO network =
_networkDao.findByUuid(nicTo.getNetworkUuid());
- if (network != null) {
- final Map<NetworkOffering.Detail, String> details =
networkOfferingDetailsDao.getNtwkOffDetails(network.getNetworkOfferingId());
- if (details != null) {
-
details.putIfAbsent(NetworkOffering.Detail.PromiscuousMode,
NetworkOrchestrationService.PromiscuousMode.value().toString());
-
details.putIfAbsent(NetworkOffering.Detail.MacAddressChanges,
NetworkOrchestrationService.MacAddressChanges.value().toString());
-
details.putIfAbsent(NetworkOffering.Detail.ForgedTransmits,
NetworkOrchestrationService.ForgedTransmits.value().toString());
- }
- NetworkDetailVO pvlantypeDetail =
networkDetailsDao.findDetail(network.getId(), ApiConstants.ISOLATED_PVLAN_TYPE);
- if (pvlantypeDetail != null) {
- details.putIfAbsent(NetworkOffering.Detail.pvlanType,
pvlantypeDetail.getValue());
- }
- nicTo.setDetails(details);
- }
nics[i++] = nicTo;
}
diff --git
a/server/src/main/java/com/cloud/network/NetworkMigrationManagerImpl.java
b/server/src/main/java/com/cloud/network/NetworkMigrationManagerImpl.java
index 956f1fb..a5f56d6 100644
--- a/server/src/main/java/com/cloud/network/NetworkMigrationManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/NetworkMigrationManagerImpl.java
@@ -556,7 +556,7 @@ public class NetworkMigrationManagerImpl implements
NetworkMigrationManager {
try {
nicProfile = _networkMgr.prepareNic(vmProfile, dest, context,
nicProfile.getId(), networkInNewPhysicalNet);
- _itMgr.replugNic(networkInNewPhysicalNet,
_itMgr.toNicTO(nicProfile, host.getHypervisorType()), _itMgr.toVmTO(vmProfile),
context, dest);
+ _itMgr.replugNic(networkInNewPhysicalNet,
_itMgr.toNicTO(nicProfile, host.getHypervisorType()), _itMgr.toVmTO(vmProfile),
dest.getHost());
} catch (ResourceUnavailableException |
InsufficientCapacityException e) {
throw new CloudRuntimeException("Migration of Nic failed", e);
}
diff --git a/server/src/main/java/com/cloud/network/NetworkModelImpl.java
b/server/src/main/java/com/cloud/network/NetworkModelImpl.java
index 5725764..3e3c3e0 100644
--- a/server/src/main/java/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/main/java/com/cloud/network/NetworkModelImpl.java
@@ -34,17 +34,15 @@ import java.util.TreeSet;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import com.cloud.utils.StringUtils;
-import org.apache.cloudstack.context.CallContext;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.log4j.Logger;
-
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
+import org.apache.cloudstack.context.CallContext;
import
org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.log4j.Logger;
import com.cloud.api.ApiDBUtils;
import com.cloud.configuration.Config;
@@ -116,6 +114,7 @@ import com.cloud.user.AccountVO;
import com.cloud.user.DomainManager;
import com.cloud.user.User;
import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.StringUtils;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
@@ -1014,24 +1013,34 @@ public class NetworkModelImpl extends ManagerBase
implements NetworkModel, Confi
// or on NULL from network.throttling.rate
// For others: Use network rate from their network offering,
// or on NULL from network.throttling.rate setting at
zone > global level
- //
http://docs.cloudstack.apache.org/projects/cloudstack-administration/en/latest/service_offerings.html#network-throttling
+ //
http://docs.cloudstack.apache.org/en/latest/adminguide/service_offerings.html#network-throttling
if (vm != null) {
- if (vm.getType() == Type.User) {
- final Nic nic = _nicDao.findByNtwkIdAndInstanceId(networkId,
vmId);
- if (nic != null && nic.isDefaultNic()) {
- return
_configMgr.getServiceOfferingNetworkRate(vm.getServiceOfferingId(),
network.getDataCenterId());
- }
- }
- if (vm.getType() == Type.DomainRouter && (network.getTrafficType()
== TrafficType.Public || network.getTrafficType() == TrafficType.Guest)) {
- for (final Nic nic: _nicDao.listByVmId(vmId)) {
- final NetworkVO nw =
_networksDao.findById(nic.getNetworkId());
- if (nw.getTrafficType() == TrafficType.Guest) {
- return
_configMgr.getNetworkOfferingNetworkRate(nw.getNetworkOfferingId(),
network.getDataCenterId());
+ switch (vm.getType()) {
+ case User:
+ final Nic nic =
_nicDao.findByNtwkIdAndInstanceId(networkId, vmId);
+ if (nic != null && nic.isDefaultNic()) {
+ return
_configMgr.getServiceOfferingNetworkRate(vm.getServiceOfferingId(),
network.getDataCenterId());
}
- }
- }
- if (vm.getType() == Type.ConsoleProxy || vm.getType() ==
Type.SecondaryStorageVm) {
- return -1;
+ break;
+ case DomainRouter:
+ if (TrafficType.Guest.equals(network.getTrafficType())) {
+ final Nic routerNic =
_nicDao.findByNtwkIdAndInstanceId(networkId, vmId);
+ if (routerNic != null) {
+ return
_configMgr.getNetworkOfferingNetworkRate(network.getNetworkOfferingId(),
network.getDataCenterId());
+ }
+ } else if
(TrafficType.Public.equals(network.getTrafficType())) {
+ List<NicVO> routerNics = _nicDao.listByVmId(vmId);
+ for (final Nic routerNic : routerNics) {
+ final NetworkVO nw =
_networksDao.findById(routerNic.getNetworkId());
+ if (TrafficType.Guest.equals(nw.getTrafficType()))
{
+ return
_configMgr.getNetworkOfferingNetworkRate(nw.getNetworkOfferingId(),
network.getDataCenterId());
+ }
+ }
+ }
+ break;
+ case ConsoleProxy:
+ case SecondaryStorageVm:
+ return -1;
}
}
if (ntwkOff != null) {
diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
index f289557..7a79cfa 100644
--- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
@@ -16,6 +16,9 @@
// under the License.
package com.cloud.network;
+import static org.apache.commons.lang.StringUtils.isBlank;
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
@@ -38,7 +41,6 @@ import java.util.UUID;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
-import com.cloud.network.Network.PVlanType;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ApiConstants;
@@ -92,11 +94,14 @@ import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.UnsupportedServiceException;
+import com.cloud.host.Host;
import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.IpAddress.State;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.IpAddresses;
+import com.cloud.network.Network.PVlanType;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.BroadcastDomainType;
@@ -187,6 +192,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExceptionUtil;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.Nic;
+import com.cloud.vm.NicProfile;
import com.cloud.vm.NicSecondaryIp;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
@@ -195,15 +201,15 @@ import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineManager;
+import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.VirtualMachineProfileImpl;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicSecondaryIpDao;
import com.cloud.vm.dao.NicSecondaryIpVO;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
-import static org.apache.commons.lang.StringUtils.isBlank;
-import static org.apache.commons.lang.StringUtils.isNotBlank;
-
/**
* NetworkServiceImpl implements NetworkService.
*/
@@ -327,6 +333,8 @@ public class NetworkServiceImpl extends ManagerBase
implements NetworkService, C
AccountService _accountService;
@Inject
NetworkAccountDao _networkAccountDao;
+ @Inject
+ VirtualMachineManager vmManager;
int _cidrLimit;
boolean _allowSubdomainNetworkAccess;
@@ -2144,6 +2152,38 @@ public class NetworkServiceImpl extends ManagerBase
implements NetworkService, C
return vms.isEmpty();
}
+ private void replugNicsForUpdatedNetwork(NetworkVO network) throws
ResourceUnavailableException, InsufficientCapacityException {
+ List<NicVO> nics = _nicDao.listByNetworkId(network.getId());
+ Network updatedNetwork = getNetwork(network.getId());
+ for (NicVO nic : nics) {
+ long vmId = nic.getInstanceId();
+ VMInstanceVO vm = _vmDao.findById(vmId);
+ if (vm == null) {
+ s_logger.error(String.format("Cannot replug NIC: %s as VM for
it is not found with ID: %d", nic, vmId));
+ continue;
+ }
+ if
(!Hypervisor.HypervisorType.VMware.equals(vm.getHypervisorType())) {
+ s_logger.debug(String.format("Cannot replug NIC: %s for VM: %s
as it is not on VMware", nic, vm));
+ continue;
+ }
+ if (!VirtualMachine.Type.User.equals(vm.getType())) {
+ s_logger.debug(String.format("Cannot replug NIC: %s for VM: %s
as it is not a user VM", nic, vm));
+ continue;
+ }
+ if (!VirtualMachine.State.Running.equals(vm.getState())) {
+ s_logger.debug(String.format("Cannot replug NIC: %s for VM: %s
as it is not in running state", nic, vm));
+ continue;
+ }
+ Host host = _hostDao.findById(vm.getHostId());
+ VirtualMachineProfile vmProfile = new
VirtualMachineProfileImpl(vm, null, null, null, null);
+ NicProfile nicProfile = new NicProfile(nic, network,
nic.getBroadcastUri(), nic.getIsolationUri(),
+ _networkModel.getNetworkRate(network.getId(), vm.getId()),
+
_networkModel.isSecurityGroupSupportedInNetwork(updatedNetwork),
+
_networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(),
network));
+ vmManager.replugNic(updatedNetwork, vmManager.toNicTO(nicProfile,
vm.getHypervisorType()), vmManager.toVmTO(vmProfile), host);
+ }
+ }
+
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_UPDATE, eventDescription
= "updating network", async = true)
@@ -2545,6 +2585,9 @@ public class NetworkServiceImpl extends ManagerBase
implements NetworkService, C
throw e;
}
}
+ if (networkOfferingChanged) {
+ replugNicsForUpdatedNetwork(network);
+ }
}
// 4) if network has been upgraded from a non
persistent ntwk offering to a persistent ntwk offering,
diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json
index ba60c9c..58aef78 100644
--- a/ui/public/locales/en.json
+++ b/ui/public/locales/en.json
@@ -820,6 +820,7 @@
"label.disksizeusedgb": "Used",
"label.display.text": "Display Text",
"label.displayname": "Display Name",
+"label.displaynetwork": "Display Network",
"label.displaytext": "Description",
"label.distributedvpcrouter": "Distributed VPC Router",
"label.dns": "DNS",
@@ -2241,6 +2242,7 @@
"label.untagged": "Untagged",
"label.update.instance.group": "Update Instance Group",
"label.update.ip.range": "Update IP range",
+"label.update.network": "Update Network",
"label.update.physical.network": "Update Physical Network",
"label.update.project.resources": "Update project resources",
"label.update.project.role": "Update project role",
@@ -3080,6 +3082,10 @@
"message.network.error": "Network Error",
"message.network.error.description": "Unable to reach the management server or
a browser extension may be blocking the network request.",
"message.network.hint": "Configure network components and
public/guest/management traffic including IP addresses.",
+"message.network.offering.change.warning": "WARNING: Changing the offering
will cause connectivity downtime for the VMs with NICs in the network.",
+"message.network.offering.forged.transmits": "Applicable for guest networks on
VMware hypervisor only.\nReject - The switch drops any outbound frame from a
virtual machine adapter with a source MAC address that is different from the
one in the .vmx configuration file.\nAccept - The switch does not perform
filtering, and permits all outbound frames.\nNone - Default to value from
global setting.",
+"message.network.offering.mac.address.changes": "Applicable for guest networks
on VMware hypervisor only.\nReject - If the guest OS changes the effective MAC
address of the virtual machine to a value that is different from the MAC
address of the VM network adapter (set in the .vmx configuration file), the
switch drops all inbound frames to the adapter.\nIf the guest OS changes the
effective MAC address of the virtual machine back to the MAC address of the VM
network adapter, the virtual [...]
+"message.network.offering.promiscuous.mode": "Applicable for guest networks on
VMware hypervisor only.\nReject - The switch drops any outbound frame from a
virtual machine adapter with a source MAC address that is different from the
one in the .vmx configuration file.\nAccept - The switch does not perform
filtering, and permits all outbound frames.\nNone - Default to value from
global setting.",
"message.network.remote.access.vpn.configuration": "Remote Access VPN
configuration has been generated, but it failed to apply. Please check
connectivity of the network element, then re-try.",
"message.network.removenic": "Please confirm that want to remove this NIC,
which will also remove the associated network from the VM.",
"message.network.secondaryip": "Please confirm that you would like to acquire
a new secondary IP for this NIC. \n NOTE: You need to manually configure the
newly-acquired secondary IP inside the virtual machine.",
@@ -3291,6 +3297,7 @@
"message.success.update.ipaddress": "Successfully updated IP Address",
"message.success.update.iprange": "Successfully updated IP range",
"message.success.update.kubeversion": "Successfully updated Kubernetes
supported version",
+"message.success.update.network": "Successfully updated Network",
"message.success.update.user": "Successfully updated user",
"message.success.upgrade.kubernetes": "Successfully upgraded Kubernetes
cluster",
"message.success.upload": "Upload Successfully",
diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js
index 9c4b38b..a91e6b5 100644
--- a/ui/src/config/section/network.js
+++ b/ui/src/config/section/network.js
@@ -75,15 +75,10 @@ export default {
{
api: 'updateNetwork',
icon: 'edit',
- label: 'label.edit',
+ label: 'label.update.network',
dataView: true,
- args: (record) => {
- var fields = ['name', 'displaytext', 'guestvmcidr']
- if (record.type === 'Isolated') {
- fields.push(...['networkofferingid', 'networkdomain'])
- }
- return fields
- }
+ popup: true,
+ component: () => import('@/views/network/UpdateNetwork.vue')
},
{
api: 'restartNetwork',
diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue
index 8330857..360f621 100644
--- a/ui/src/views/AutogenView.vue
+++ b/ui/src/views/AutogenView.vue
@@ -1073,6 +1073,13 @@ export default {
params.isofilter = 'executable'
} else if (possibleApi === 'listHosts') {
params.type = 'routing'
+ } else if (possibleApi === 'listNetworkOfferings' && this.resource) {
+ if (this.resource.type) {
+ params.guestiptype = this.resource.type
+ }
+ if (!this.resource.vpcid) {
+ params.forvpc = false
+ }
}
if (showIcon) {
params.showicon = true
diff --git a/ui/src/views/network/UpdateNetwork.vue
b/ui/src/views/network/UpdateNetwork.vue
new file mode 100644
index 0000000..68f4a6f
--- /dev/null
+++ b/ui/src/views/network/UpdateNetwork.vue
@@ -0,0 +1,257 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// 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.
+
+<template>
+ <div class="form-layout" v-ctrl-enter="handleSubmit">
+ <a-spin :spinning="loading">
+ <a-form
+ :form="form"
+ @submit="handleSubmit"
+ layout="vertical">
+ <a-form-item>
+ <tooltip-label slot="label" :title="$t('label.name')"
:tooltip="apiParams.name.description"/>
+ <a-input
+ v-decorator="['name', {
+ rules: [{ required: true, message:
`${$t('message.error.required.input')}` }]
+ }]"
+ :placeholder="apiParams.name.description"
+ autoFocus />
+ </a-form-item>
+ <a-form-item>
+ <tooltip-label slot="label" :title="$t('label.displaytext')"
:tooltip="apiParams.displaytext.description"/>
+ <a-input
+ v-decorator="['displaytext', {
+ rules: [{ required: true, message:
`${$t('message.error.required.input')}` }]
+ }]"
+ :placeholder="apiParams.displaytext.description"
+ autoFocus />
+ </a-form-item>
+ <a-form-item v-if="isUpdatingIsolatedNetwork">
+ <tooltip-label slot="label" :title="$t('label.networkofferingid')"
:tooltip="apiParams.networkofferingid.description"/>
+ <span v-if="networkOffering.id && networkOffering.id !=
resource.networkofferingid">
+ <a-alert type="warning">
+ <span slot="message"
v-html="$t('message.network.offering.change.warning')" />
+ </a-alert>
+ <br/>
+ </span>
+ <a-select
+ id="offering-selection"
+ v-decorator="['networkofferingid', {}]"
+ showSearch
+ optionFilterProp="children"
+ :filterOption="(input, option) => {
+ return
option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase())
>= 0
+ }"
+ :loading="networkOfferingLoading"
+ :placeholder="apiParams.networkofferingid.description"
+ @change="val => { networkOffering = networkOfferings[val] }">
+ <a-select-option v-for="(opt, optIndex) in networkOfferings"
:key="optIndex">
+ {{ opt.displaytext || opt.name }}
+ </a-select-option>
+ </a-select>
+ </a-form-item>
+ <a-form-item>
+ <tooltip-label slot="label" :title="$t('label.guestvmcidr')"
:tooltip="apiParams.guestvmcidr.description"/>
+ <a-input
+ v-decorator="['guestvmcidr', {}]"
+ :placeholder="apiParams.guestvmcidr.description"
+ @change="(e) => { cidrChanged = e.target.value !== resource.cidr
}" />
+ </a-form-item>
+ <a-form-item v-if="cidrChanged">
+ <tooltip-label slot="label" :title="$t('label.changecidr')"
:tooltip="apiParams.changecidr.description"/>
+ <a-switch v-decorator="['changecidr', {}]" />
+ </a-form-item>
+ <a-form-item v-if="isUpdatingIsolatedNetwork">
+ <tooltip-label slot="label" :title="$t('label.networkdomain')"
:tooltip="apiParams.guestvmcidr.description"/>
+ <a-input
+ v-decorator="['networkdomain', {}]"
+ :placeholder="apiParams.networkdomain.description"
+ autoFocus />
+ </a-form-item>
+ <a-form-item v-if="resource.redundantrouter">
+ <tooltip-label slot="label" :title="$t('label.updateinsequence')"
:tooltip="apiParams.updateinsequence.description"/>
+ <a-switch v-decorator="['maclearning', {initialValue: false}]" />
+ </a-form-item>
+ <a-form-item v-if="isAdmin()">
+ <tooltip-label slot="label" :title="$t('label.displaynetwork')"
:tooltip="apiParams.displaynetwork.description"/>
+ <a-switch v-decorator="['displaynetwork', {}]"
:defaultChecked="resource.displaynetwork" />
+ </a-form-item>
+ <a-form-item v-if="isAdmin()">
+ <tooltip-label slot="label" :title="$t('label.forced')"
:tooltip="apiParams.forced.description"/>
+ <a-switch v-decorator="['forced', {}]" />
+ </a-form-item>
+
+ <div :span="24" class="action-button">
+ <a-button @click="closeAction">{{ $t('label.cancel') }}</a-button>
+ <a-button :loading="loading" ref="submit" type="primary"
@click="handleSubmit">{{ this.$t('label.ok') }}</a-button>
+ </div>
+ </a-form>
+ </a-spin>
+ </div>
+</template>
+
+<script>
+import { api } from '@/api'
+import TooltipLabel from '@/components/widgets/TooltipLabel'
+
+export default {
+ name: 'UpdateNetwork',
+ components: {
+ TooltipLabel
+ },
+ props: {
+ resource: {
+ type: Object,
+ required: true
+ }
+ },
+ data () {
+ return {
+ resourceValues: {},
+ networkOfferings: [],
+ networkOfferingLoading: false,
+ networkOffering: {},
+ cidrChanged: false,
+ loading: false
+ }
+ },
+ beforeCreate () {
+ this.form = this.$form.createForm(this)
+ this.apiParams = this.$getApiParams('updateNetwork')
+ },
+ created () {
+ this.resourceValues = {
+ name: this.resource.name,
+ displaytext: this.resource.displaytext,
+ guestvmcidr: this.resource.cidr
+ }
+ if (this.isUpdatingIsolatedNetwork) {
+ this.resourceValues.networkdomain = this.resource.networkdomain
+ }
+ for (var field in this.resourceValues) {
+ var fieldValue = this.resourceValues[field]
+ if (fieldValue) {
+ this.form.getFieldDecorator(field, { initialValue: fieldValue })
+ }
+ }
+ this.fetchData()
+ },
+ computed: {
+ isUpdatingIsolatedNetwork () {
+ return this.resource && this.resource.type === 'Isolated'
+ }
+ },
+ methods: {
+ isAdmin () {
+ return ['Admin'].includes(this.$store.getters.userInfo.roletype)
+ },
+ fetchData () {
+ this.fetchNetworkOfferingData()
+ },
+ arrayHasItems (array) {
+ return array !== null && array !== undefined && Array.isArray(array) &&
array.length > 0
+ },
+ fetchNetworkOfferingData () {
+ this.networkOfferings = []
+ if (!this.isUpdatingIsolatedNetwork) return
+ const params = {
+ zoneid: this.resource.zoneid,
+ state: 'Enabled',
+ guestiptype: this.resource.type,
+ forvpc: !!this.resource.vpcid
+ }
+ this.networkOfferingLoading = true
+ api('listNetworkOfferings', params).then(json => {
+ this.networkOfferings =
json.listnetworkofferingsresponse.networkoffering
+ }).finally(() => {
+ this.networkOfferingLoading = false
+ if (this.arrayHasItems(this.networkOfferings)) {
+ for (var i = 0; i < this.networkOfferings.length; i++) {
+ if (this.networkOfferings[i].id ===
this.resource.networkofferingid) {
+ this.networkOffering = this.networkOfferings[i]
+ this.form.setFieldsValue({
+ networkofferingid: i
+ })
+ break
+ }
+ }
+ }
+ })
+ },
+ handleSubmit (e) {
+ e.preventDefault()
+ if (this.loading) return
+ this.form.validateFields((err, values) => {
+ if (err) {
+ return
+ }
+ this.loading = true
+ var manualFields = ['name', 'networkofferingid']
+ const params = {
+ id: this.resource.id,
+ name: values.name
+ }
+ for (var field in values) {
+ if (manualFields.includes(field)) continue
+ var fieldValue = values[field]
+ if (fieldValue !== undefined &&
+ fieldValue !== null &&
+ (!(field in this.resourceValues) || this.resourceValues[field] !==
fieldValue)) {
+ params[field] = fieldValue
+ }
+ }
+ if (values.networkofferingid !== undefined &&
+ values.networkofferingid != null &&
+ this.networkOfferings &&
+ this.networkOfferings[values.networkofferingid].id !==
this.resource.networkofferingid) {
+ params.networkofferingid =
this.networkOfferings[values.networkofferingid].id
+ }
+ api('updateNetwork', params).then(json => {
+ const jobId = json.updatenetworkresponse.jobid
+ this.$pollJob({
+ jobId,
+ title: this.$t('label.update.network'),
+ description: this.resource.name,
+ loadingMessage: `${this.$t('label.update.network')}
${this.resource.name} ${this.$t('label.in.progress')}`,
+ catchMessage: this.$t('error.fetching.async.job.result'),
+ successMessage: `${this.$t('message.success.update.network')}
${this.resource.name}`
+ })
+ this.closeAction()
+ }).catch(error => {
+ this.$notifyError(error)
+ }).finally(() => {
+ this.loading = false
+ })
+ })
+ },
+ closeAction () {
+ this.$emit('close-action')
+ }
+ }
+}
+</script>
+
+<style scoped lang="less">
+ .form-layout {
+ width: 60vw;
+
+ @media (min-width: 500px) {
+ width: 450px;
+ }
+ }
+
+</style>
diff --git a/ui/src/views/offering/AddNetworkOffering.vue
b/ui/src/views/offering/AddNetworkOffering.vue
index 1c4c1ef..c0f2bdb 100644
--- a/ui/src/views/offering/AddNetworkOffering.vue
+++ b/ui/src/views/offering/AddNetworkOffering.vue
@@ -108,13 +108,13 @@
</a-radio-button>
</a-radio-group>
</a-form-item>
- <a-form-item :label="$t('label.promiscuousmode')">
+ <a-form-item>
+ <tooltip-label slot="label" :title="$t('label.promiscuousmode')"
:tooltip="$t('message.network.offering.promiscuous.mode')"/>
<a-radio-group
v-decorator="['promiscuousmode', {
- initialValue: promiscuousMode
+ initialValue: ''
}]"
- buttonStyle="solid"
- @change="selected => {
handlePromiscuousModeChange(selected.target.value) }">
+ buttonStyle="solid">
<a-radio-button value="">
{{ $t('label.none') }}
</a-radio-button>
@@ -126,13 +126,13 @@
</a-radio-button>
</a-radio-group>
</a-form-item>
- <a-form-item :label="$t('label.macaddresschanges')">
+ <a-form-item>
+ <tooltip-label slot="label" :title="$t('label.macaddresschanges')"
:tooltip="$t('message.network.offering.mac.address.changes')"/>
<a-radio-group
v-decorator="['macaddresschanges', {
- initialValue: macAddressChanges
+ initialValue: ''
}]"
- buttonStyle="solid"
- @change="selected => {
handleMacAddressChangesChange(selected.target.value) }">
+ buttonStyle="solid">
<a-radio-button value="">
{{ $t('label.none') }}
</a-radio-button>
@@ -144,13 +144,13 @@
</a-radio-button>
</a-radio-group>
</a-form-item>
- <a-form-item :label="$t('label.forgedtransmits')">
+ <a-form-item>
+ <tooltip-label slot="label" :title="$t('label.forgedtransmits')"
:tooltip="$t('message.network.offering.forged.transmits')"/>
<a-radio-group
v-decorator="['forgedtransmits', {
- initialValue: forgedTransmits
+ initialValue: ''
}]"
- buttonStyle="solid"
- @change="selected => {
handleForgedTransmitsChange(selected.target.value) }">
+ buttonStyle="solid">
<a-radio-button value="">
{{ $t('label.none') }}
</a-radio-button>
@@ -418,9 +418,6 @@ export default {
hasAdvanceZone: false,
requiredNetworkOfferingExists: false,
guestType: 'isolated',
- promiscuousMode: '',
- macAddressChanges: '',
- forgedTransmits: '',
selectedDomains: [],
selectedZones: [],
forVpc: false,
@@ -502,15 +499,6 @@ export default {
handleGuestTypeChange (val) {
this.guestType = val
},
- handlePromiscuousModeChange (val) {
- this.promiscuousMode = val
- },
- handleMacAddressChangesChange (val) {
- this.macAddressChanges = val
- },
- handleForgedTransmitsChange (val) {
- this.forgedTransmits = val
- },
fetchSupportedServiceData () {
const params = {}
params.listAll = true
@@ -697,7 +685,8 @@ export default {
var self = this
var selectedServices = null
var keys = Object.keys(values)
- var ignoredKeys = ['state', 'status', 'allocationstate', 'forvpc',
'specifyvlan', 'ispublic', 'domainid', 'zoneid', 'egressdefaultpolicy',
'promiscuousmode', 'macaddresschanges', 'forgedtransmits', 'isolation',
'supportspublicaccess']
+ const detailsKey = ['promiscuousmode', 'macaddresschanges',
'forgedtransmits']
+ const ignoredKeys = [...detailsKey, 'state', 'status',
'allocationstate', 'forvpc', 'specifyvlan', 'ispublic', 'domainid', 'zoneid',
'egressdefaultpolicy', 'isolation', 'supportspublicaccess']
keys.forEach(function (key, keyIndex) {
if (self.isSupportedServiceObject(values[key])) {
if (selectedServices == null) {
@@ -840,14 +829,10 @@ export default {
if ('egressdefaultpolicy' in values && values.egressdefaultpolicy !==
'allow') {
params.egressdefaultpolicy = false
}
- if (values.promiscuousmode) {
- params['details[0].promiscuousMode'] = values.promiscuousmode
- }
- if (values.macaddresschanges) {
- params['details[0].macaddresschanges'] = values.macaddresschanges
- }
- if (values.forgedtransmits) {
- params['details[0].forgedtransmits'] = values.forgedtransmits
+ for (const key of detailsKey) {
+ if (values[key]) {
+ params['details[0].' + key] = values[key]
+ }
}
if (values.ispublic !== true) {
var domainIndexes = values.domainid
diff --git
a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
index ba45391..7ffd8b5 100644
---
a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
+++
b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
@@ -525,17 +525,9 @@ public class HypervisorHostHelper {
}
/**
- * @param ethPortProfileName
- * @param namePrefix
- * @param hostMo
- * @param vlanId
- * @param networkRateMbps
- * @param networkRateMulticastMbps
- * @param timeOutMs
- * @param vSwitchType
- * @param numPorts
- * @param details
- * @return
+ * Prepares network (for non-standard virtual switch) for the VM NIC based
on the parameters.
+ * Can create a new portgroup or update an existing.
+ * @return Pair of network's ManagedObjectReference and name
* @throws Exception
*/
@@ -1416,10 +1408,10 @@ public class HypervisorHostHelper {
return false;
}
- if (secPolicyInSpec != null && securityPolicy != null
+ if (secPolicyInSpec != null
&& ((securityPolicy.isAllowPromiscuous() != null &&
!securityPolicy.isAllowPromiscuous().equals(secPolicyInSpec.isAllowPromiscuous()))
|| (securityPolicy.isForgedTransmits() != null &&
!securityPolicy.isForgedTransmits().equals(secPolicyInSpec.isForgedTransmits()))
- || (securityPolicy.isMacChanges() != null &&
securityPolicy.isMacChanges().equals(secPolicyInSpec.isMacChanges())))) {
+ || (securityPolicy.isMacChanges() != null &&
!securityPolicy.isMacChanges().equals(secPolicyInSpec.isMacChanges())))) {
return false;
}