Merge branch 'nsx-integration' of https://github.com/apache/cloudstack into nsx-integration

This commit is contained in:
Pearl Dsilva 2023-10-23 11:53:01 -04:00
commit 2fe8e9cd96
64 changed files with 2340 additions and 645 deletions

View File

@ -96,6 +96,8 @@ public interface NetworkGuru extends Adapter {
*/
Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, String name, Long vpcId, Account owner);
void setup(Network network, long networkId);
/**
* For guest networks that are in Allocated state after the design stage,
* resources are allocated when the guest network is actually being used

View File

@ -29,7 +29,8 @@ public interface VpcOffering extends InternalIdentity, Identity {
public static final String defaultVPCOfferingName = "Default VPC offering";
public static final String defaultVPCNSOfferingName = "Default VPC offering with Netscaler";
public static final String redundantVPCOfferingName = "Redundant VPC offering";
public static final String DEFAULT_VPC_NSX_OFFERING_NAME = "VPC offering with NSX";
public static final String DEFAULT_VPC_NAT_NSX_OFFERING_NAME = "VPC offering with NSX - NAT Mode";
public static final String DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME = "VPC offering with NSX - Route Mode";
/**
*
@ -54,6 +55,10 @@ public interface VpcOffering extends InternalIdentity, Identity {
*/
boolean isDefault();
boolean isForNsx();
String getNsxMode();
/**
* @return service offering id used by VPC virtual router
*/

View File

@ -36,7 +36,8 @@ public interface VpcProvisioningService {
VpcOffering createVpcOffering(String name, String displayText, List<String> supportedServices,
Map<String, List<String>> serviceProviders,
Map serviceCapabilitystList, NetUtils.InternetProtocol internetProtocol,
Long serviceOfferingId, List<Long> domainIds, List<Long> zoneIds, VpcOffering.State state);
Long serviceOfferingId, Boolean forNsx, String mode,
List<Long> domainIds, List<Long> zoneIds, VpcOffering.State state);
Pair<List<? extends VpcOffering>,Integer> listVpcOfferings(ListVPCOfferingsCmd cmd);

View File

@ -43,6 +43,11 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, MacLearning, RelatedNetworkOffering, domainid, zoneid, pvlanType, internetProtocol
}
public enum NsxMode {
NATTED,
ROUTED
}
public final static String SystemPublicNetwork = "System-Public-Network";
public final static String SystemControlNetwork = "System-Control-Network";
public final static String SystemManagementNetwork = "System-Management-Network";
@ -52,7 +57,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
public final static String DefaultSharedNetworkOfferingWithSGService = "DefaultSharedNetworkOfferingWithSGService";
public static final String DEFAULT_TUNGSTEN_SHARED_NETWORK_OFFERING_WITH_SGSERVICE = "DefaultTungstenSharedNetworkOfferingWithSGService";
public static final String DEFAULT_NSX_OFFERING = "DefaultNSXNetworkOffering";
public static final String DEFAULT_NAT_NSX_OFFERING = "DefaultNATNSXNetworkOffering";
public static final String DEFAULT_ROUTER_NSX_OFFERING = "DefaultRouteNSXNetworkOffering";
public final static String QuickCloudNoServices = "QuickCloudNoServices";
public final static String DefaultIsolatedNetworkOfferingWithSourceNatService = "DefaultIsolatedNetworkOfferingWithSourceNatService";
public final static String OvsIsolatedNetworkOfferingWithSourceNatService = "OvsIsolatedNetworkOfferingWithSourceNatService";
@ -93,6 +99,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
boolean isForNsx();
String getNsxMode();
TrafficType getTrafficType();
boolean isSpecifyVlan();

View File

@ -294,6 +294,7 @@ public class ApiConstants {
public static final String MIGRATION_TYPE = "migrationtype";
public static final String MEMORY = "memory";
public static final String MODE = "mode";
public static final String NSX_MODE = "nsxmode";
public static final String NAME = "name";
public static final String METHOD_NAME = "methodname";
public static final String NETWORK_DOMAIN = "networkdomain";

View File

@ -24,7 +24,10 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import com.cloud.network.Network;
import com.cloud.network.VirtualRouterProvider;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.collections.CollectionUtils;
@ -47,6 +50,15 @@ import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.Availability;
import com.cloud.user.Account;
import static com.cloud.network.Network.Service.Dhcp;
import static com.cloud.network.Network.Service.Dns;
import static com.cloud.network.Network.Service.Lb;
import static com.cloud.network.Network.Service.StaticNat;
import static com.cloud.network.Network.Service.SourceNat;
import static com.cloud.network.Network.Service.PortForwarding;
import static com.cloud.network.Network.Service.NetworkACL;
import static com.cloud.network.Network.Service.UserData;
@APICommand(name = "createNetworkOffering", description = "Creates a network offering.", responseObject = NetworkOfferingResponse.class, since = "3.0.0",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class CreateNetworkOfferingCmd extends BaseCmd {
@ -127,6 +139,18 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
description = "true if network offering is meant to be used for VPC, false otherwise.")
private Boolean forVpc;
@Parameter(name = ApiConstants.FOR_NSX,
type = CommandType.BOOLEAN,
description = "true if network offering is meant to be used for NSX, false otherwise.",
since = "4.20.0")
private Boolean forNsx;
@Parameter(name = ApiConstants.NSX_MODE,
type = CommandType.STRING,
description = "Indicates the mode with which the network will operate. Valid option: NATTED or ROUTED",
since = "4.20.0")
private String nsxMode;
@Parameter(name = ApiConstants.FOR_TUNGSTEN,
type = CommandType.BOOLEAN,
description = "true if network offering is meant to be used for Tungsten-Fabric, false otherwise.")
@ -211,7 +235,24 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
}
public List<String> getSupportedServices() {
return supportedServices == null ? new ArrayList<String>() : supportedServices;
if (!forNsx) {
return supportedServices == null ? new ArrayList<String>() : supportedServices;
} else {
List<String> services = new ArrayList<>(List.of(
Dhcp.getName(),
Dns.getName(),
StaticNat.getName(),
SourceNat.getName(),
PortForwarding.getName(),
UserData.getName(),
Lb.getName()
));
if (Boolean.TRUE.equals(forVpc)) {
services.add(NetworkACL.getName());
return services;
}
return services;
}
}
public String getGuestIpType() {
@ -241,6 +282,14 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
return forVpc;
}
public Boolean isForNsx() {
return forNsx;
}
public String getNsxMode() {
return nsxMode;
}
public Boolean getForTungsten() {
return forTungsten;
}
@ -261,9 +310,8 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
}
public Map<String, List<String>> getServiceProviders() {
Map<String, List<String>> serviceProviderMap = null;
if (serviceProviderList != null && !serviceProviderList.isEmpty()) {
serviceProviderMap = new HashMap<String, List<String>>();
Map<String, List<String>> serviceProviderMap = new HashMap<String, List<String>>();
if (serviceProviderList != null && !serviceProviderList.isEmpty() && !isForNsx()) {
Collection servicesCollection = serviceProviderList.values();
Iterator iter = servicesCollection.iterator();
while (iter.hasNext()) {
@ -279,11 +327,29 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
providerList.add(provider);
serviceProviderMap.put(service, providerList);
}
} else if (Boolean.TRUE.equals(forNsx)) {
getServiceProviderMapForNsx(serviceProviderMap);
}
return serviceProviderMap;
}
private void getServiceProviderMapForNsx(Map<String, List<String>> serviceProviderMap) {
String routerProvider = Boolean.TRUE.equals(getForVpc()) ? VirtualRouterProvider.Type.VPCVirtualRouter.name() :
VirtualRouterProvider.Type.VirtualRouter.name();
List<String> unsupportedServices = List.of("Vpn", "SecurityGroup", "Connectivity",
"Gateway", "Firewall", "BaremetalPxeService");
List<String> routerSupported = List.of("Dhcp", "Dns", "UserData");
List<String> allServices = Service.listAllServices().stream().map(Service::getName).collect(Collectors.toList());
for (String service : allServices) {
if (unsupportedServices.contains(service))
continue;
if (routerSupported.contains(service))
serviceProviderMap.put(service, List.of(routerProvider));
else
serviceProviderMap.put(service, List.of(Network.Provider.Nsx.getName()));
}
}
public Map<Capability, String> getServiceCapabilities(Service service) {
Map<Capability, String> capabilityMap = null;

View File

@ -23,8 +23,13 @@ import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.Network;
import com.cloud.network.VirtualRouterProvider;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.collections.CollectionUtils;
@ -45,6 +50,15 @@ import com.cloud.exception.ResourceAllocationException;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.user.Account;
import static com.cloud.network.Network.Service.Dhcp;
import static com.cloud.network.Network.Service.Dns;
import static com.cloud.network.Network.Service.Lb;
import static com.cloud.network.Network.Service.StaticNat;
import static com.cloud.network.Network.Service.SourceNat;
import static com.cloud.network.Network.Service.PortForwarding;
import static com.cloud.network.Network.Service.NetworkACL;
import static com.cloud.network.Network.Service.UserData;
@APICommand(name = "createVPCOffering", description = "Creates VPC offering", responseObject = VpcOfferingResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd {
@ -62,7 +76,6 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd {
@Parameter(name = ApiConstants.SUPPORTED_SERVICES,
type = CommandType.LIST,
required = true,
collectionType = CommandType.STRING,
description = "services supported by the vpc offering")
private List<String> supportedServices;
@ -101,6 +114,18 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd {
since = "4.13")
private List<Long> zoneIds;
@Parameter(name = ApiConstants.FOR_NSX,
type = CommandType.BOOLEAN,
description = "true if network offering is meant to be used for NSX, false otherwise.",
since = "4.20.0")
private Boolean forNsx;
@Parameter(name = ApiConstants.NSX_MODE,
type = CommandType.STRING,
description = "Indicates the mode with which the network will operate. Valid option: NATTED or ROUTED",
since = "4.20.0")
private String nsxMode;
@Parameter(name = ApiConstants.ENABLE,
type = CommandType.BOOLEAN,
description = "set to true if the offering is to be enabled during creation. Default is false",
@ -120,13 +145,35 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd {
}
public List<String> getSupportedServices() {
if (!forNsx && CollectionUtils.isEmpty(supportedServices)) {
throw new InvalidParameterValueException("Supported services needs to be provided");
}
if (forNsx) {
return List.of(
Dhcp.getName(),
Dns.getName(),
Lb.getName(),
StaticNat.getName(),
SourceNat.getName(),
NetworkACL.getName(),
PortForwarding.getName(),
UserData.getName()
);
}
return supportedServices;
}
public Boolean isForNsx() {
return !Objects.isNull(forNsx) && forNsx;
}
public String getNsxMode() {
return nsxMode;
}
public Map<String, List<String>> getServiceProviders() {
Map<String, List<String>> serviceProviderMap = null;
if (serviceProviderList != null && !serviceProviderList.isEmpty()) {
serviceProviderMap = new HashMap<String, List<String>>();
Map<String, List<String>> serviceProviderMap = new HashMap<String, List<String>>();;
if (serviceProviderList != null && !serviceProviderList.isEmpty() && !isForNsx()) {
Collection<? extends Map<String, String>> servicesCollection = serviceProviderList.values();
Iterator<? extends Map<String, String>> iter = servicesCollection.iterator();
while (iter.hasNext()) {
@ -134,7 +181,7 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd {
if (s_logger.isTraceEnabled()) {
s_logger.trace("service provider entry specified: " + obj);
}
HashMap<String, String> services = (HashMap<String, String>)obj;
HashMap<String, String> services = (HashMap<String, String>) obj;
String service = services.get("service");
String provider = services.get("provider");
List<String> providerList = null;
@ -146,11 +193,28 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd {
providerList.add(provider);
serviceProviderMap.put(service, providerList);
}
} else if (Boolean.TRUE.equals(forNsx)) {
getServiceProviderMapForNsx(serviceProviderMap);
}
return serviceProviderMap;
}
private void getServiceProviderMapForNsx(Map<String, List<String>> serviceProviderMap) {
List<String> unsupportedServices = List.of("Vpn", "BaremetalPxeService", "SecurityGroup", "Connectivity",
"Gateway", "Firewall");
List<String> routerSupported = List.of("Dhcp", "Dns", "UserData");
List<String> allServices = Network.Service.listAllServices().stream().map(Network.Service::getName).collect(Collectors.toList());
for (String service : allServices) {
if (unsupportedServices.contains(service))
continue;
if (routerSupported.contains(service))
serviceProviderMap.put(service, List.of(VirtualRouterProvider.Type.VPCVirtualRouter.name()));
else
serviceProviderMap.put(service, List.of(Network.Provider.Nsx.getName()));
}
}
public Map<String, List<String>> getServiceCapabilityList() {
return serviceCapabilityList;
}

View File

@ -107,6 +107,10 @@ public class NetworkOfferingResponse extends BaseResponseWithAnnotations {
@Param(description = "true if network offering can be used by Tungsten-Fabric networks only")
private Boolean forTungsten;
@SerializedName(ApiConstants.NSX_MODE)
@Param(description = "Mode in which the network will operate. This parameter is only relevant for NSX offerings")
private String nsxMode;
@SerializedName(ApiConstants.IS_PERSISTENT)
@Param(description = "true if network offering supports persistent networks, false otherwise")
private Boolean isPersistent;
@ -227,6 +231,10 @@ public class NetworkOfferingResponse extends BaseResponseWithAnnotations {
this.forTungsten = forTungsten;
}
public void setNsxMode(String nsxMode) {
this.nsxMode = nsxMode;
}
public void setIsPersistent(Boolean isPersistent) {
this.isPersistent = isPersistent;
}

View File

@ -63,9 +63,17 @@ public class VpcOfferingResponse extends BaseResponse {
private Boolean supportsDistributedRouter;
@SerializedName((ApiConstants.SUPPORTS_REGION_LEVEL_VPC))
@Param(description = " indicated if the offering can support region level vpc", since = "4.4")
@Param(description = "indicated if the offering can support region level vpc", since = "4.4")
private Boolean supportsRegionLevelVpc;
@SerializedName(ApiConstants.FOR_NSX)
@Param(description = "true if vpc offering can be used by NSX networks only")
private Boolean forNsx;
@SerializedName(ApiConstants.NSX_MODE)
@Param(description = "Mode in which the network will operate. This parameter is only relevant for NSX offerings")
private String nsxMode;
@SerializedName(ApiConstants.DOMAIN_ID)
@Param(description = "the domain ID(s) this disk offering belongs to. Ignore this information as it is not currently applicable.")
private String domainId;
@ -138,6 +146,14 @@ public class VpcOfferingResponse extends BaseResponse {
this.domain = domain;
}
public void setForNsx(Boolean forNsx) {
this.forNsx = forNsx;
}
public void setNsxMode(String nsxMode) {
this.nsxMode = nsxMode;
}
public String getZoneId() {
return zoneId;
}

View File

@ -52,15 +52,15 @@ public class CreateVPCOfferingCmdTest {
IllegalAccessException {
CreateVPCOfferingCmd cmd = new CreateVPCOfferingCmd();
ApiCmdTestUtil.set(cmd, ApiConstants.SERVICE_PROVIDER_LIST, new HashMap<String, Map<String, String>>());
Assert.assertNull(cmd.getServiceProviders());
Assert.assertTrue(cmd.getServiceProviders().isEmpty());
}
@Test
public void getDetailsNull() throws IllegalArgumentException,
public void getDetailsEmpty() throws IllegalArgumentException,
IllegalAccessException {
CreateVPCOfferingCmd cmd = new CreateVPCOfferingCmd();
ApiCmdTestUtil.set(cmd, ApiConstants.SERVICE_PROVIDER_LIST, null);
Assert.assertNull(cmd.getServiceProviders());
Assert.assertTrue(cmd.getServiceProviders().isEmpty());
}
@Test

View File

@ -225,7 +225,7 @@ public interface ConfigurationManager {
Integer networkRate, Map<Service, Set<Provider>> serviceProviderMap, boolean isDefault, Network.GuestType type, boolean systemOnly, Long serviceOfferingId,
boolean conserveMode, Map<Service, Map<Capability, String>> serviceCapabilityMap, boolean specifyIpRanges, boolean isPersistent,
Map<NetworkOffering.Detail, String> details, boolean egressDefaultPolicy, Integer maxconn, boolean enableKeepAlive, Boolean forVpc,
Boolean forTungsten, Boolean forNsx, List<Long> domainIds, List<Long> zoneIds, boolean enableOffering, final NetUtils.InternetProtocol internetProtocol);
Boolean forTungsten, Boolean forNsx, String mode, List<Long> domainIds, List<Long> zoneIds, boolean enableOffering, final NetUtils.InternetProtocol internetProtocol);
Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, boolean forVirtualNetwork, boolean forSystemVms, Long podId, String startIP, String endIP,
String vlanGateway, String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr)

View File

@ -48,6 +48,8 @@ import javax.inject.Inject;
import javax.naming.ConfigurationException;
import javax.persistence.EntityExistsException;
import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.user.dao.AccountDao;
@ -392,6 +394,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
private AccountDao accountDao;
@Inject
private VpcDao vpcDao;
@Inject
private DomainDao domainDao;
VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this);
@ -1470,7 +1474,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
}
private void setVmNetworkDetails(VMInstanceVO vm, VirtualMachineTO vmTO) {
public void setVmNetworkDetails(VMInstanceVO vm, VirtualMachineTO vmTO) {
if (VirtualMachine.Type.User.equals(vm.getType())) {
List<UserVmJoinVO> userVmJoinVOs = userVmJoinDao.searchByIds(vm.getId());
Map<Long, String> networkToNetworkNameMap = new HashMap<>();
@ -1478,12 +1482,26 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
for (UserVmJoinVO userVmJoinVO : userVmJoinVOs) {
NetworkVO networkVO = _networkDao.findById(userVmJoinVO.getNetworkId());
Account acc = accountDao.findById(networkVO.getAccountId());
String networkName = acc.getAccountName() + "-" ;
Domain domain = domainDao.findById(networkVO.getDomainId());
DataCenter zone = _dcDao.findById(vm.getDataCenterId());
if (Objects.isNull(zone)) {
throw new CloudRuntimeException(String.format("Failed to find zone with ID: %s", vm.getDataCenterId()));
}
if (Objects.isNull(acc)) {
throw new CloudRuntimeException(String.format("Failed to find account with ID: %s", networkVO.getAccountId()));
}
if (Objects.isNull(domain)) {
throw new CloudRuntimeException(String.format("Failed to find domain with ID: %s", networkVO.getDomainId()));
}
String networkName = String.format("D%s-A%s-Z%s", domain.getId(), acc.getId(), zone.getId());
if (Objects.isNull(networkVO.getVpcId())) {
networkName += networkVO.getName();
networkName += "-S"+networkVO.getId();
} else {
VpcVO vpc = vpcDao.findById(networkVO.getVpcId());
networkName += (vpc.getName() + "-" + networkVO.getName());
if (Objects.isNull(vpc)) {
throw new CloudRuntimeException(String.format("Failed to find VPC with ID: %s", networkVO.getVpcId()));
}
networkName = String.format("%s-V%s-S%s", networkName, vpc.getId(), networkVO.getId());
}
networkToNetworkNameMap.put(networkVO.getId(), networkName);
}

View File

@ -540,27 +540,27 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
if (_networkOfferingDao.findByUniqueName(NetworkOffering.QuickCloudNoServices) == null) {
offering = _configMgr.createNetworkOffering(NetworkOffering.QuickCloudNoServices, "Offering for QuickCloud with no services", TrafficType.Guest, null, true,
Availability.Optional, null, new HashMap<Network.Service, Set<Network.Provider>>(), true, Network.GuestType.Shared, false, null, true, null, true,
false, null, false, null, true, false, false, false, null, null, true, null);
false, null, false, null, true, false, false, false, null, null, null, true, null);
}
//#2 - SG enabled network offering
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedNetworkOfferingWithSGService) == null) {
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedNetworkOfferingWithSGService, "Offering for Shared Security group enabled networks",
TrafficType.Guest, null, true, Availability.Optional, null, defaultSharedNetworkOfferingProviders, true, Network.GuestType.Shared, false, null, true,
null, true, false, null, false, null, true, false, false, false, null, null, true, null);
null, true, false, null, false, null, true, false, false, false, null, null, null, true, null);
}
//#3 - shared network offering with no SG service
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedNetworkOffering) == null) {
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedNetworkOffering, "Offering for Shared networks", TrafficType.Guest, null, true,
Availability.Optional, null, defaultSharedNetworkOfferingProviders, true, Network.GuestType.Shared, false, null, true, null, true, false, null, false,
null, true, false, false, false, null, null, true, null);
null, true, false, false, false, null,null, null, true, null);
}
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DEFAULT_TUNGSTEN_SHARED_NETWORK_OFFERING_WITH_SGSERVICE) == null) {
offering = _configMgr.createNetworkOffering(NetworkOffering.DEFAULT_TUNGSTEN_SHARED_NETWORK_OFFERING_WITH_SGSERVICE, "Offering for Tungsten Shared Security group enabled networks",
TrafficType.Guest, null, true, Availability.Optional, null, defaultTungstenSharedSGEnabledNetworkOfferingProviders, true, Network.GuestType.Shared, false, null, true,
null, true, false, null, false, null, true, false, true, false, null, null, true, null);
null, true, false, null, false, null, true, false, true, false, null, null,null, true, null);
offering.setState(NetworkOffering.State.Enabled);
_networkOfferingDao.update(offering.getId(), offering);
}
@ -570,14 +570,14 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService,
"Offering for Isolated networks with Source Nat service enabled", TrafficType.Guest, null, false, Availability.Required, null,
defaultIsolatedSourceNatEnabledNetworkOfferingProviders, true, Network.GuestType.Isolated, false, null, true, null, false, false, null, false, null,
true, false, false, false, null, null, true, null);
true, false, false, false, null, null,null, true, null);
}
//#5 - default vpc offering with LB service
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks) == null) {
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks,
"Offering for Isolated VPC networks with Source Nat service enabled", TrafficType.Guest, null, false, Availability.Optional, null,
defaultVPCOffProviders, true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, true, null);
defaultVPCOffProviders, true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, null,true, null);
}
//#6 - default vpc offering with no LB service
@ -586,14 +586,14 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
defaultVPCOffProviders.remove(Service.Lb);
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksNoLB,
"Offering for Isolated VPC networks with Source Nat service enabled and LB service disabled", TrafficType.Guest, null, false, Availability.Optional,
null, defaultVPCOffProviders, true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, true, null);
null, defaultVPCOffProviders, true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, null,true, null);
}
//#7 - isolated offering with source nat disabled
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOffering) == null) {
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOffering, "Offering for Isolated networks with no Source Nat service",
TrafficType.Guest, null, true, Availability.Optional, null, defaultIsolatedNetworkOfferingProviders, true, Network.GuestType.Isolated, false, null,
true, null, true, false, null, false, null, true, false, false, false, null, null, true, null);
true, null, true, false, null, false, null, true, false, false, false, null, null, null, true, null);
}
//#8 - network offering with internal lb service
@ -615,7 +615,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB) == null) {
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB,
"Offering for Isolated VPC networks with Internal Lb support", TrafficType.Guest, null, false, Availability.Optional, null, internalLbOffProviders,
true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, true, null);
true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, null, true, null);
offering.setInternalLb(true);
offering.setPublicLb(false);
_networkOfferingDao.update(offering.getId(), offering);
@ -646,7 +646,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedEIPandELBNetworkOffering) == null) {
offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedEIPandELBNetworkOffering,
"Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, null, true, Availability.Optional, null,
netscalerServiceProviders, true, Network.GuestType.Shared, false, null, true, serviceCapabilityMap, true, false, null, false, null, true, false, false, false, null, null, true, null);
netscalerServiceProviders, true, Network.GuestType.Shared, false, null, true, serviceCapabilityMap, true, false, null, false, null, true, false, false, false, null, null, null, true, null);
offering.setDedicatedLB(false);
_networkOfferingDao.update(offering.getId(), offering);
}
@ -812,6 +812,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
}
});
guru.setup(network, relatedFile);
}
if (networks.size() < 1) {

View File

@ -35,6 +35,18 @@ import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
@ -155,6 +167,16 @@ public class VirtualMachineManagerImplTest {
private UserVmDao userVmDaoMock;
@Mock
private UserVmVO userVmMock;
@Mock
private NetworkDao networkDao;
@Mock
private AccountDao accountDao;
@Mock
private DomainDao domainDao;
@Mock
private DataCenterDao dcDao;
@Mock
private VpcDao vpcDao;
@Before
public void setup() {
@ -895,4 +917,45 @@ public class VirtualMachineManagerImplTest {
map.put(Mockito.mock(Volume.class), pool2);
virtualMachineManagerImpl.checkAndAttemptMigrateVmAcrossCluster(vm, destinationClusterId, map);
}
@Test
public void checkIfVmNetworkDetailsReturnedIsCorrect() {
VMInstanceVO vm = new VMInstanceVO(1L, 1L, "VM1", "i-2-2-VM",
VirtualMachine.Type.User, 1L, HypervisorType.KVM, 1L, 1L, 1L,
1L, false, false);
VirtualMachineTO vmTO = new VirtualMachineTO() {};
UserVmJoinVO userVm = new UserVmJoinVO();
NetworkVO networkVO = mock(NetworkVO.class);
AccountVO accountVO = mock(AccountVO.class);
DomainVO domainVO = mock(DomainVO.class);
domainVO.setName("testDomain");
DataCenterVO dataCenterVO = mock(DataCenterVO.class);
VpcVO vpcVO = mock(VpcVO.class);
networkVO.setAccountId(1L);
networkVO.setName("testNet");
networkVO.setVpcId(1L);
accountVO.setAccountName("testAcc");
vpcVO.setName("VPC1");
List<UserVmJoinVO> userVms = List.of(userVm);
Mockito.when(userVmJoinDaoMock.searchByIds(anyLong())).thenReturn(userVms);
Mockito.when(networkDao.findById(anyLong())).thenReturn(networkVO);
Mockito.when(accountDao.findById(anyLong())).thenReturn(accountVO);
Mockito.when(domainDao.findById(anyLong())).thenReturn(domainVO);
Mockito.when(dcDao.findById(anyLong())).thenReturn(dataCenterVO);
Mockito.when(vpcDao.findById(anyLong())).thenReturn(vpcVO);
Mockito.when(dataCenterVO.getId()).thenReturn(1L);
when(accountVO.getId()).thenReturn(2L);
Mockito.when(domainVO.getId()).thenReturn(3L);
Mockito.when(vpcVO.getId()).thenReturn(4L);
Mockito.when(networkVO.getId()).thenReturn(5L);
virtualMachineManagerImpl.setVmNetworkDetails(vm, vmTO);
assertEquals(vmTO.getNetworkIdToNetworkNameMap().size(), 1);
assertEquals(vmTO.getNetworkIdToNetworkNameMap().get(5L), "D3-A2-Z1-V4-S5");
}
}

View File

@ -58,6 +58,12 @@ public class VpcOfferingVO implements VpcOffering {
@Column(name = "default")
boolean isDefault = false;
@Column(name = "for_nsx")
boolean forNsx = false;
@Column(name = "nsx_mode")
String nsxMode;
@Column(name = GenericDao.REMOVED_COLUMN)
Date removed;
@ -144,6 +150,22 @@ public class VpcOfferingVO implements VpcOffering {
return isDefault;
}
public boolean isForNsx() {
return forNsx;
}
public void setForNsx(boolean forNsx) {
this.forNsx = forNsx;
}
public String getNsxMode() {
return nsxMode;
}
public void setNsxMode(String nsxMode) {
this.nsxMode = nsxMode;
}
public void setUniqueName(String uniqueName) {
this.uniqueName = uniqueName;
}

View File

@ -139,6 +139,9 @@ public class NetworkOfferingVO implements NetworkOffering {
@Column(name = "for_nsx")
boolean forNsx = false;
@Column(name = "nsx_mode")
String nsxMode;
@Column(name = "egress_default_policy")
boolean egressdefaultpolicy;
@ -207,6 +210,15 @@ public class NetworkOfferingVO implements NetworkOffering {
this.forNsx = forNsx;
}
@Override
public String getNsxMode() {
return nsxMode;
}
public void setNsxMode(String nsxMode) {
this.nsxMode = nsxMode;
}
@Override
public long getId() {
return id;

View File

@ -214,8 +214,11 @@ BEGIN
-- NSX Plugin --
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.network_offerings','for_nsx', 'int(1) unsigned DEFAULT "0" COMMENT "is nsx enabled for the resource"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.network_offerings','nsx_mode', 'varchar(32) COMMENT "mode in which the network would route traffic"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','for_nsx', 'int(1) unsigned DEFAULT "0" COMMENT "is nsx enabled for the resource"');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','nsx_mode', 'varchar(32) COMMENT "mode in which the network would route traffic"');
-- Network offering with multi-domains and multi-zones
-- Network offering with NSX related columns
DROP VIEW IF EXISTS `cloud`.`network_offering_view`;
CREATE VIEW `cloud`.`network_offering_view` AS
SELECT
@ -259,6 +262,7 @@ SELECT
`network_offerings`.`for_vpc` AS `for_vpc`,
`network_offerings`.`for_tungsten` AS `for_tungsten`,
`network_offerings`.`for_nsx` AS `for_nsx`,
`network_offerings`.`nsx_mode` AS `nsx_mode`,
`network_offerings`.`service_package_id` AS `service_package_id`,
GROUP_CONCAT(DISTINCT(domain.id)) AS domain_id,
GROUP_CONCAT(DISTINCT(domain.uuid)) AS domain_uuid,
@ -398,3 +402,46 @@ CREATE VIEW `cloud`.`snapshot_view` AS
OR (`snapshot_zone_ref`.`zone_id` = `data_center`.`id`))))
LEFT JOIN `resource_tags` ON ((`resource_tags`.`resource_id` = `snapshots`.`id`)
AND (`resource_tags`.`resource_type` = 'Snapshot')));
-- VPC offering with NSX related columns
DROP VIEW IF EXISTS `cloud`.`vpc_offering_view`;
CREATE VIEW `cloud`.`vpc_offering_view` AS
SELECT
`vpc_offerings`.`id` AS `id`,
`vpc_offerings`.`uuid` AS `uuid`,
`vpc_offerings`.`name` AS `name`,
`vpc_offerings`.`unique_name` AS `unique_name`,
`vpc_offerings`.`display_text` AS `display_text`,
`vpc_offerings`.`state` AS `state`,
`vpc_offerings`.`default` AS `default`,
`vpc_offerings`.`for_nsx` AS `for_nsx`,
`vpc_offerings`.`nsx_mode` AS `nsx_mode`,
`vpc_offerings`.`created` AS `created`,
`vpc_offerings`.`removed` AS `removed`,
`vpc_offerings`.`service_offering_id` AS `service_offering_id`,
`vpc_offerings`.`supports_distributed_router` AS `supports_distributed_router`,
`vpc_offerings`.`supports_region_level_vpc` AS `supports_region_level_vpc`,
`vpc_offerings`.`redundant_router_service` AS `redundant_router_service`,
`vpc_offerings`.`sort_key` AS `sort_key`,
GROUP_CONCAT(DISTINCT(domain.id)) AS domain_id,
GROUP_CONCAT(DISTINCT(domain.uuid)) AS domain_uuid,
GROUP_CONCAT(DISTINCT(domain.name)) AS domain_name,
GROUP_CONCAT(DISTINCT(domain.path)) AS domain_path,
GROUP_CONCAT(DISTINCT(zone.id)) AS zone_id,
GROUP_CONCAT(DISTINCT(zone.uuid)) AS zone_uuid,
GROUP_CONCAT(DISTINCT(zone.name)) AS zone_name,
`offering_details`.value AS internet_protocol
FROM
`cloud`.`vpc_offerings`
LEFT JOIN
`cloud`.`vpc_offering_details` AS `domain_details` ON `domain_details`.`offering_id` = `vpc_offerings`.`id` AND `domain_details`.`name`='domainid'
LEFT JOIN
`cloud`.`domain` AS `domain` ON FIND_IN_SET(`domain`.`id`, `domain_details`.`value`)
LEFT JOIN
`cloud`.`vpc_offering_details` AS `zone_details` ON `zone_details`.`offering_id` = `vpc_offerings`.`id` AND `zone_details`.`name`='zoneid'
LEFT JOIN
`cloud`.`data_center` AS `zone` ON FIND_IN_SET(`zone`.`id`, `zone_details`.`value`)
LEFT JOIN
`cloud`.`vpc_offering_details` AS `offering_details` ON `offering_details`.`offering_id` = `vpc_offerings`.`id` AND `offering_details`.`name`='internetprotocol'
GROUP BY
`vpc_offerings`.`id`;

View File

@ -138,6 +138,11 @@ public class ContrailGuru extends AdapterBase implements NetworkGuru {
return network;
}
@Override
public void setup(Network network, long networkId) {
// do nothing
}
@Override
public Network implement(Network network, NetworkOffering offering, DeployDestination destination, ReservationContext context)
throws InsufficientVirtualNetworkCapacityException {

View File

@ -219,7 +219,7 @@ public class ContrailManagerImpl extends ManagerBase implements ContrailManager
ConfigurationManager configMgr = (ConfigurationManager) _configService;
NetworkOfferingVO voffer = configMgr.createNetworkOffering(offeringName, offeringDisplayText,
TrafficType.Public, null, true, Availability.Optional, null, serviceProviderMap, true,
Network.GuestType.Shared, false, null, false, null, true, false, null, true, null, false, false, false, false, null, null, true, null);
Network.GuestType.Shared, false, null, false, null, true, false, null, true, null, false, false, false, false, null, null, null, true, null);
long id = voffer.getId();
_networkOfferingDao.update(id, voffer);
return _networkOfferingDao.findById(id);
@ -254,7 +254,7 @@ public class ContrailManagerImpl extends ManagerBase implements ContrailManager
ConfigurationManager configMgr = (ConfigurationManager)_configService;
NetworkOfferingVO voffer =
configMgr.createNetworkOffering(offeringName, offeringDisplayText, TrafficType.Guest, null, false, Availability.Optional, null, serviceProviderMap, true,
Network.GuestType.Isolated, false, null, false, null, false, true, null, true, null, false, offeringName.equals(vpcRouterOfferingName), false, false, null, null, true, null);
Network.GuestType.Isolated, false, null, false, null, false, true, null, true, null, false, offeringName.equals(vpcRouterOfferingName), false, false, null, null, null, true, null);
if (offeringName.equals(vpcRouterOfferingName)) {
voffer.setInternalLb(true);
}
@ -295,7 +295,7 @@ public class ContrailManagerImpl extends ManagerBase implements ContrailManager
}
serviceProviderMap.put(svc, providerSet);
}
vpcOffer = _vpcProvSvc.createVpcOffering(juniperVPCOfferingName, juniperVPCOfferingDisplayText, services, serviceProviderMap, null, null, null, null, null, VpcOffering.State.Enabled);
vpcOffer = _vpcProvSvc.createVpcOffering(juniperVPCOfferingName, juniperVPCOfferingDisplayText, services, serviceProviderMap, null, null, null, false, null, null, null, VpcOffering.State.Enabled);
long id = vpcOffer.getId();
_vpcOffDao.update(id, (VpcOfferingVO)vpcOffer);
return _vpcOffDao.findById(id);

View File

@ -20,22 +20,35 @@ import java.util.List;
public class CreateNsxDhcpRelayConfigCommand extends NsxCommand {
private Long vpcId;
private String vpcName;
private long networkId;
private String networkName;
private List<String> addresses;
public CreateNsxDhcpRelayConfigCommand(String zoneName, Long zoneId, String accountName, Long accountId,
String vpcName, String networkName, List<String> addresses) {
super(zoneName, zoneId, accountName, accountId);
public CreateNsxDhcpRelayConfigCommand(long domainId, long accountId, long zoneId,
Long vpcId, String vpcName, long networkId, String networkName,
List<String> addresses) {
super(domainId, accountId, zoneId);
this.vpcId = vpcId;
this.vpcName = vpcName;
this.networkId = networkId;
this.networkName = networkName;
this.addresses = addresses;
}
public Long getVpcId() {
return vpcId;
}
public String getVpcName() {
return vpcName;
}
public long getNetworkId() {
return networkId;
}
public String getNetworkName() {
return networkName;
}

View File

@ -16,23 +16,51 @@
// under the License.
package org.apache.cloudstack.agent.api;
import com.cloud.network.dao.NetworkVO;
import java.util.Objects;
public class CreateNsxSegmentCommand extends CreateNsxTier1GatewayCommand {
private NetworkVO tierNetwork;
public CreateNsxSegmentCommand(String zoneName, Long zoneId, String accountName, Long accountId, String vpcName, NetworkVO tierNetwork) {
super(zoneName, zoneId, accountName, accountId, vpcName);
this.tierNetwork = tierNetwork;
public class CreateNsxSegmentCommand extends NsxCommand {
private Long vpcId;
private String vpcName;
private long networkId;
private String networkName;
private String networkGateway;
private String networkCidr;
public CreateNsxSegmentCommand(long domainId, long accountId, long zoneId,
Long vpcId, String vpcName, long networkId, String networkName,
String networkGateway, String networkCidr) {
super(domainId, accountId, zoneId);
this.vpcId = vpcId;
this.vpcName = vpcName;
this.networkId = networkId;
this.networkName = networkName;
this.networkGateway = networkGateway;
this.networkCidr = networkCidr;
}
public NetworkVO getTierNetwork() {
return tierNetwork;
public Long getVpcId() {
return vpcId;
}
public void setTierNetwork(NetworkVO tierNetwork) {
this.tierNetwork = tierNetwork;
public String getVpcName() {
return vpcName;
}
public long getNetworkId() {
return networkId;
}
public String getNetworkName() {
return networkName;
}
public String getNetworkGateway() {
return networkGateway;
}
public String getNetworkCidr() {
return networkCidr;
}
@Override
@ -41,11 +69,11 @@ public class CreateNsxSegmentCommand extends CreateNsxTier1GatewayCommand {
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
CreateNsxSegmentCommand command = (CreateNsxSegmentCommand) o;
return Objects.equals(tierNetwork, command.tierNetwork);
return Objects.equals(networkName, command.networkName);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), tierNetwork);
return Objects.hash(super.hashCode(), networkName);
}
}

View File

@ -19,21 +19,23 @@ package org.apache.cloudstack.agent.api;
import java.util.Objects;
public class CreateNsxTier1GatewayCommand extends NsxCommand {
private long vpcId;
private String vpcName;
public CreateNsxTier1GatewayCommand(String zoneName, Long zoneId, String accountName, Long accountId, String vpcName) {
super(zoneName, zoneId, accountName, accountId);
public CreateNsxTier1GatewayCommand(long domainId, long accountId, long zoneId, long vpcId, String vpcName) {
super(domainId, accountId, zoneId);
this.vpcId = vpcId;
this.vpcName = vpcName;
}
public long getVpcId() {
return vpcId;
}
public String getVpcName() {
return vpcName;
}
public void setVpcName(String vpcName) {
this.vpcName = vpcName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View File

@ -16,10 +16,36 @@
// under the License.
package org.apache.cloudstack.agent.api;
import com.cloud.network.dao.NetworkVO;
public class DeleteNsxSegmentCommand extends NsxCommand {
public class DeleteNsxSegmentCommand extends CreateNsxSegmentCommand {
public DeleteNsxSegmentCommand(String accountName, String vpcName, NetworkVO network) {
super(null, network.getDataCenterId(), accountName, network.getAccountId(), vpcName, network);
private Long vpcId;
private String vpcName;
private long networkId;
private String networkName;
public DeleteNsxSegmentCommand(long domainId, long accountId, long zoneId, Long vpcId,
String vpcName, long networkId, String networkName) {
super(domainId, accountId, zoneId);
this.vpcId = vpcId;
this.vpcName = vpcName;
this.networkId = networkId;
this.networkName = networkName;
}
public Long getVpcId() {
return vpcId;
}
public String getVpcName() {
return vpcName;
}
public long getNetworkId() {
return networkId;
}
public String getNetworkName() {
return networkName;
}
}

View File

@ -16,9 +16,22 @@
// under the License.
package org.apache.cloudstack.agent.api;
public class DeleteNsxTier1GatewayCommand extends CreateNsxTier1GatewayCommand {
public class DeleteNsxTier1GatewayCommand extends NsxCommand {
public DeleteNsxTier1GatewayCommand(String zoneName, Long zoneId, String accountName, Long accountId, String vpcName) {
super(zoneName, zoneId, accountName, accountId, vpcName);
private Long vpcId;
private String vpcName;
public DeleteNsxTier1GatewayCommand(long domainId, long accountId, long zoneId, Long vpcId, String vpcName) {
super(domainId, accountId, zoneId);
this.vpcId = vpcId;
this.vpcName = vpcName;
}
public Long getVpcId() {
return vpcId;
}
public String getVpcName() {
return vpcName;
}
}

View File

@ -21,49 +21,31 @@ import com.cloud.agent.api.Command;
import java.util.Objects;
public class NsxCommand extends Command {
private String zoneName;
private Long zoneId;
private String accountName;
private Long accountId;
private long zoneId;
private long accountId;
private long domainId;
public NsxCommand(String zoneName, Long zoneId, String accountName, Long accountId) {
this.zoneName = zoneName;
public NsxCommand() {
}
public NsxCommand(long domainId, long accountId, long zoneId) {
this.zoneId = zoneId;
this.accountName = accountName;
this.accountId = accountId;
this.domainId = domainId;
}
public String getZoneName() {
return zoneName;
}
public void setZoneName(String zoneName) {
this.zoneName = zoneName;
}
public Long getZoneId() {
public long getZoneId() {
return zoneId;
}
public void setZoneId(Long zoneId) {
this.zoneId = zoneId;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public Long getAccountId() {
public long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
public long getDomainId() {
return domainId;
}
@Override
public boolean executeInSequence() {
return false;
@ -75,11 +57,11 @@ public class NsxCommand extends Command {
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
NsxCommand that = (NsxCommand) o;
return Objects.equals(zoneName, that.zoneName) && Objects.equals(zoneId, that.zoneId) && Objects.equals(accountName, that.accountName) && Objects.equals(accountId, that.accountId);
return Objects.equals(zoneId, that.zoneId) && Objects.equals(accountId, that.accountId) && Objects.equals(domainId, that.domainId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), zoneName, zoneId, accountName, accountId);
return Objects.hash(super.hashCode(), zoneId, accountId, domainId);
}
}

View File

@ -16,7 +16,6 @@
// under the License.
package org.apache.cloudstack.resource;
import com.amazonaws.util.CollectionUtils;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
@ -24,29 +23,15 @@ import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.resource.ServerResource;
import com.cloud.utils.exception.CloudRuntimeException;
import com.vmware.nsx.model.TransportZone;
import com.vmware.nsx.model.TransportZoneListResult;
import com.vmware.nsx_policy.infra.DhcpRelayConfigs;
import com.vmware.nsx_policy.infra.Segments;
import com.vmware.nsx_policy.infra.Sites;
import com.vmware.nsx_policy.infra.Tier1s;
import com.vmware.nsx_policy.infra.sites.EnforcementPoints;
import com.vmware.nsx_policy.infra.tier_0s.LocaleServices;
import com.vmware.nsx_policy.model.ApiError;
import com.vmware.nsx_policy.model.DhcpRelayConfig;
import com.vmware.nsx_policy.model.EnforcementPointListResult;
import com.vmware.nsx_policy.model.LocaleServicesListResult;
import com.vmware.nsx_policy.model.Segment;
import com.vmware.nsx_policy.model.SegmentSubnet;
import com.vmware.nsx_policy.model.SiteListResult;
import com.vmware.nsx_policy.model.Tier1;
import com.vmware.vapi.bindings.Service;
import com.vmware.vapi.std.errors.Error;
import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.StartupNsxCommand;
import org.apache.cloudstack.agent.api.CreateNsxDhcpRelayConfigCommand;
@ -54,36 +39,21 @@ import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand;
import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand;
import org.apache.cloudstack.service.NsxApi;
import org.apache.cloudstack.utils.NsxApiClientUtils;
import org.apache.cloudstack.service.NsxApiClient;
import org.apache.cloudstack.utils.NsxControllerUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import javax.naming.ConfigurationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.util.Objects.isNull;
import static org.apache.cloudstack.utils.NsxApiClientUtils.RouteAdvertisementType.TIER1_CONNECTED;
import static org.apache.cloudstack.utils.NsxApiClientUtils.RouteAdvertisementType.TIER1_IPSEC_LOCAL_ENDPOINT;
import static org.apache.cloudstack.utils.NsxApiClientUtils.HAMode.ACTIVE_STANDBY;
import static org.apache.cloudstack.utils.NsxApiClientUtils.FailoverMode.PREEMPTIVE;
import static org.apache.cloudstack.utils.NsxApiClientUtils.PoolAllocation.ROUTING;
import static org.apache.cloudstack.utils.NsxApiClientUtils.TransportType.OVERLAY;
import static org.apache.cloudstack.utils.NsxApiClientUtils.createApiClient;
public class NsxResource implements ServerResource {
private static final Logger LOGGER = Logger.getLogger(NsxResource.class);
private static final String TIER_0_GATEWAY_PATH_PREFIX = "/infra/tier-0s/";
private static final String TIER_1_GATEWAY_PATH_PREFIX = "/infra/tier-1s/";
private static final String DHCP_RELAY_CONFIGS_PATH_PREFIX = "/infra/dhcp-relay-configs";
private static final String Tier_1_LOCALE_SERVICE_ID = "default";
private static final String TIER_1_RESOURCE_TYPE = "Tier1";
private static final String SEGMENT_RESOURCE_TYPE = "Segment";
private String name;
protected String hostname;
protected String username;
@ -95,13 +65,12 @@ public class NsxResource implements ServerResource {
protected String transportZone;
protected String zoneId;
protected NsxApi nsxApi;
protected NsxApiClient nsxApiClient;
@Override
public Host.Type getType() {
return Host.Type.Routing;
}
@Override
public StartupCommand[] initialize() {
StartupNsxCommand sc = new StartupNsxCommand();
@ -236,56 +205,44 @@ public class NsxResource implements ServerResource {
throw new ConfigurationException("Missing NSX transportZone");
}
nsxApi = new NsxApi();
nsxApi.setApiClient(createApiClient(hostname, port, username, password.toCharArray()));
nsxApiClient = new NsxApiClient(hostname, port, username, password.toCharArray());
return true;
}
private String getDhcpRelayConfig(String zoneName, String accountName, String vpcName, String networkName) {
return String.format("%s-%s-%s-%s-Relay", zoneName, accountName, vpcName, networkName);
}
private Answer executeRequest(CreateNsxDhcpRelayConfigCommand cmd) {
String zoneName = cmd.getZoneName();
String accountName = cmd.getAccountName();
long zoneId = cmd.getZoneId();
long domainId = cmd.getDomainId();
long accountId = cmd.getAccountId();
long vpcId = cmd.getVpcId();
long networkId = cmd.getNetworkId();
String vpcName = cmd.getVpcName();
String networkName = cmd.getNetworkName();
List<String> addresses = cmd.getAddresses();
String dhcpRelayConfigName = getDhcpRelayConfig(zoneName, accountName, vpcName, networkName);
String dhcpRelayConfigName = NsxControllerUtils.getNsxDhcpRelayConfigId(zoneId, domainId, accountId, vpcId, networkId);
String msg = String.format("Creating DHCP relay config with name %s on network %s of VPC %s",
dhcpRelayConfigName, networkName, vpcName);
LOGGER.debug(msg);
try {
DhcpRelayConfigs service = (DhcpRelayConfigs) nsxService.apply(DhcpRelayConfigs.class);
DhcpRelayConfig config = new DhcpRelayConfig.Builder()
.setServerAddresses(addresses)
.setId(dhcpRelayConfigName)
.setDisplayName(dhcpRelayConfigName)
.build();
service.patch(dhcpRelayConfigName, config);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
msg = String.format("Error creating the DHCP relay config with name %s: %s", dhcpRelayConfigName, ae.getErrorMessage());
LOGGER.error(msg);
return new NsxAnswer(cmd, new CloudRuntimeException(ae.getErrorMessage()));
nsxApiClient.createDhcpRelayConfig(dhcpRelayConfigName, addresses);
} catch (CloudRuntimeException e) {
msg = String.format("Error creating the DHCP relay config with name %s: %s", dhcpRelayConfigName, e.getMessage());
LOGGER.error(msg, e);
return new NsxAnswer(cmd, e);
}
String segmentName = String.format("%s-%s-%s", accountName, vpcName, networkName);
String segmentName = NsxControllerUtils.getNsxSegmentId(domainId, accountId, zoneId, vpcId, networkId);
String dhcpConfigPath = String.format("%s/%s", DHCP_RELAY_CONFIGS_PATH_PREFIX, dhcpRelayConfigName);
try {
LOGGER.debug(String.format("Adding the creating DHCP relay config %s to the segment %s", dhcpConfigPath, segmentName));
Segments segmentService = (Segments) nsxService.apply(Segments.class);
Segment segment = segmentService.get(segmentName);
Segment segment = nsxApiClient.getSegmentById(segmentName);
segment.setDhcpConfigPath(dhcpConfigPath);
segmentService.patch(segmentName, segment);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
msg = String.format("Error adding the DHCP relay config with name %s to the segment %s: %s", dhcpRelayConfigName, segmentName, ae.getErrorMessage());
nsxApiClient.updateSegment(segmentName, segment);
} catch (CloudRuntimeException e) {
msg = String.format("Error adding the DHCP relay config with name %s to the segment %s: %s", dhcpRelayConfigName, segmentName, e.getMessage());
LOGGER.error(msg);
return new NsxAnswer(cmd, new CloudRuntimeException(ae.getErrorMessage()));
return new NsxAnswer(cmd, e);
}
return new NsxAnswer(cmd, true, "");
@ -295,63 +252,21 @@ public class NsxResource implements ServerResource {
return new ReadyAnswer(cmd);
}
private Function<Class<? extends Service>, Service> nsxService = svcClass -> nsxApi.getApiClient().createStub(svcClass);
private Answer executeRequest(CreateNsxTier1GatewayCommand cmd) {
String name = getTier1GatewayName(cmd);
Tier1 tier1 = getTier1Gateway(name);
if (tier1 != null) {
throw new InvalidParameterValueException(String.format("VPC network with name %s exists in NSX zone: %s and account %s", name, cmd.getZoneName(), cmd.getAccountName()));
}
String tier0GatewayPath = TIER_0_GATEWAY_PATH_PREFIX + tier0Gateway;
Tier1s tier1service = (Tier1s) nsxService.apply(Tier1s.class);
tier1 = new Tier1.Builder()
.setTier0Path(tier0GatewayPath)
.setResourceType(TIER_1_RESOURCE_TYPE)
.setPoolAllocation(ROUTING.name())
.setHaMode(ACTIVE_STANDBY.name())
.setFailoverMode(PREEMPTIVE.name())
.setRouteAdvertisementTypes(List.of(TIER1_CONNECTED.name(), TIER1_IPSEC_LOCAL_ENDPOINT.name()))
.setId(name)
.setDisplayName(name)
.build();
String name = NsxControllerUtils.getTier1GatewayName(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(), cmd.getVpcId());
try {
tier1service.patch(name, tier1);
createTier1LocaleServices(name, edgeCluster);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
return new NsxAnswer(cmd, new CloudRuntimeException(ae.getErrorMessage()));
}
return new NsxAnswer(cmd, true, "");
}
/**
* To instantiate Tier-1 in Edge Cluster
* @return
*/
private boolean createTier1LocaleServices(String tier1Id, String edgeCluster) {
try {
List<com.vmware.nsx_policy.model.LocaleServices> localeServices = getTier0LocalServices(tier0Gateway);
com.vmware.nsx_policy.infra.tier_1s.LocaleServices tier1LocalService = (com.vmware.nsx_policy.infra.tier_1s.LocaleServices) nsxService.apply(com.vmware.nsx_policy.infra.tier_1s.LocaleServices.class);
com.vmware.nsx_policy.model.LocaleServices localeService = new com.vmware.nsx_policy.model.LocaleServices.Builder()
.setEdgeClusterPath(localeServices.get(0).getEdgeClusterPath()).build();
tier1LocalService.patch(tier1Id, Tier_1_LOCALE_SERVICE_ID, localeService);
return true;
} catch (Error error) {
throw new CloudRuntimeException(String.format("Failed to instantiate tier-1 gateway %s in edge cluster %s", tier1Id, edgeCluster));
nsxApiClient.createTier1Gateway(name, tier0Gateway, edgeCluster);
return new NsxAnswer(cmd, true, "");
} catch (CloudRuntimeException e) {
LOGGER.error(String.format("Cannot create tier 1 gateway %s (VPC: %s): %s", name, cmd.getVpcName(), e.getMessage()));
return new NsxAnswer(cmd, e);
}
}
private Answer executeRequest(DeleteNsxTier1GatewayCommand cmd) {
String tier1Id = NsxControllerUtils.getTier1GatewayName(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(), cmd.getVpcId());
try {
String tier1Id = getTier1GatewayName(cmd);
com.vmware.nsx_policy.infra.tier_1s.LocaleServices localeService = (com.vmware.nsx_policy.infra.tier_1s.LocaleServices)
nsxService.apply(com.vmware.nsx_policy.infra.tier_1s.LocaleServices.class);
localeService.delete(tier1Id, Tier_1_LOCALE_SERVICE_ID);
Tier1s tier1service = (Tier1s) nsxService.apply(Tier1s.class);
tier1service.delete(tier1Id);
nsxApiClient.deleteTier1Gateway(tier1Id);
} catch (Exception e) {
return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage()));
}
@ -360,140 +275,62 @@ public class NsxResource implements ServerResource {
private Answer executeRequest(CreateNsxSegmentCommand cmd) {
try {
SiteListResult sites = getSites();
String errorMsg = null;
if (CollectionUtils.isNullOrEmpty(sites.getResults())) {
errorMsg = String.format("Failed to create network: %s as no sites are found in the linked NSX infrastructure", cmd.getTierNetwork().getName());
SiteListResult sites = nsxApiClient.getSites();
String errorMsg;
String networkName = cmd.getNetworkName();
if (CollectionUtils.isEmpty(sites.getResults())) {
errorMsg = String.format("Failed to create network: %s as no sites are found in the linked NSX infrastructure", networkName);
LOGGER.error(errorMsg);
return new NsxAnswer(cmd, new CloudRuntimeException(errorMsg));
}
String siteId = sites.getResults().get(0).getId();
EnforcementPointListResult epList = getEnforcementPoints(siteId);
if (CollectionUtils.isNullOrEmpty(epList.getResults())) {
errorMsg = String.format("Failed to create network: %s as no enforcement points are found in the linked NSX infrastructure", cmd.getTierNetwork().getName());
EnforcementPointListResult epList = nsxApiClient.getEnforcementPoints(siteId);
if (CollectionUtils.isEmpty(epList.getResults())) {
errorMsg = String.format("Failed to create network: %s as no enforcement points are found in the linked NSX infrastructure", networkName);
LOGGER.error(errorMsg);
return new NsxAnswer(cmd, new CloudRuntimeException(errorMsg));
}
String enforcementPointPath = epList.getResults().get(0).getPath();
TransportZoneListResult transportZoneListResult = getTransportZones();
if (CollectionUtils.isNullOrEmpty(transportZoneListResult.getResults())) {
errorMsg = String.format("Failed to create network: %s as no transport zones were found in the linked NSX infrastructure", cmd.getTierNetwork().getName());
TransportZoneListResult transportZoneListResult = nsxApiClient.getTransportZones();
if (CollectionUtils.isEmpty(transportZoneListResult.getResults())) {
errorMsg = String.format("Failed to create network: %s as no transport zones were found in the linked NSX infrastructure", networkName);
LOGGER.error(errorMsg);
return new NsxAnswer(cmd, new CloudRuntimeException(errorMsg));
}
List<TransportZone> transportZones = transportZoneListResult.getResults().stream().filter(tz -> tz.getDisplayName().equals(transportZone)).collect(Collectors.toList());
if (CollectionUtils.isNullOrEmpty(transportZones)) {
errorMsg = String.format("Failed to create network: %s as no transport zone of name %s was found in the linked NSX infrastructure", cmd.getTierNetwork().getName(), transportZone);
if (CollectionUtils.isEmpty(transportZones)) {
errorMsg = String.format("Failed to create network: %s as no transport zone of name %s was found in the linked NSX infrastructure", networkName, transportZone);
LOGGER.error(errorMsg);
return new NsxAnswer(cmd, new CloudRuntimeException(errorMsg));
}
String segmentName = getSegmentName(cmd.getAccountName(), cmd.getTierNetwork().getName(), cmd.getVpcName());
Segments segmentService = (Segments) nsxService.apply(Segments.class);
SegmentSubnet subnet = new SegmentSubnet.Builder()
.setGatewayAddress(cmd.getTierNetwork().getGateway() + "/" + cmd.getTierNetwork().getCidr().split("/")[1]).build();
Segment segment = new Segment.Builder()
.setResourceType(SEGMENT_RESOURCE_TYPE)
.setId(segmentName)
.setDisplayName(segmentName)
.setConnectivityPath(isNull(cmd.getVpcName()) ? TIER_0_GATEWAY_PATH_PREFIX + tier0Gateway
: TIER_1_GATEWAY_PATH_PREFIX + getTier1GatewayName(cmd))
.setAdminState(NsxApiClientUtils.AdminState.UP.name())
.setSubnets(List.of(subnet))
.setTransportZonePath(enforcementPointPath + "/transport-zones/" + transportZones.get(0).getId())
.build();
segmentService.patch(segmentName, segment);
String segmentName = NsxControllerUtils.getNsxSegmentId(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(), cmd.getVpcId(), cmd.getNetworkId());
String gatewayAddress = cmd.getNetworkGateway() + "/" + cmd.getNetworkCidr().split("/")[1];
nsxApiClient.createSegment(cmd.getZoneId(), cmd.getDomainId(), cmd.getAccountId(), cmd.getVpcId(),
segmentName, gatewayAddress, tier0Gateway, enforcementPointPath, transportZones);
} catch (Exception e) {
LOGGER.error(String.format("Failed to create network: %s", cmd.getTierNetwork().getName()));
LOGGER.error(String.format("Failed to create network: %s", cmd.getNetworkName()));
return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage()));
}
return new NsxAnswer(cmd, true, null);
}
private NsxAnswer executeRequest(DeleteNsxSegmentCommand cmd) {
String segmentName = NsxControllerUtils.getNsxSegmentId(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(),
cmd.getVpcId(), cmd.getNetworkId());
try {
Thread.sleep(30*1000);
String segmentName = getSegmentName(cmd.getAccountName(), cmd.getTierNetwork().getName(), cmd.getVpcName());
Segments segmentService = (Segments) nsxService.apply(Segments.class);
segmentService.delete(segmentName);
DhcpRelayConfigs dhcpRelayConfig = (DhcpRelayConfigs) nsxService.apply(DhcpRelayConfigs.class);
dhcpRelayConfig.delete(getDhcpRelayId(cmd.getZoneName(), cmd.getAccountName(), cmd.getVpcName(), cmd.getTierNetwork().getName()));
nsxApiClient.deleteSegment(cmd.getZoneId(), cmd.getDomainId(), cmd.getAccountId(), cmd.getVpcId(), cmd.getNetworkId(), segmentName);
} catch (Exception e) {
LOGGER.error(String.format("Failed to delete NSX segment: %s", getSegmentName(cmd.getAccountName(), cmd.getTierNetwork().getName(), cmd.getVpcName())));
LOGGER.error(String.format("Failed to delete NSX segment: %s", segmentName));
return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage()));
}
return new NsxAnswer(cmd, true, null);
}
private List<com.vmware.nsx_policy.model.LocaleServices> getTier0LocalServices(String tier0Gateway) {
try {
LocaleServices tier0LocaleServices = (LocaleServices) nsxService.apply(LocaleServices.class);
LocaleServicesListResult result = tier0LocaleServices.list(tier0Gateway, null, false, null, null, null, null);
return result.getResults();
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Failed to fetch locale services for tier gateway %s due to %s", tier0Gateway, e.getMessage()));
}
}
private Tier1 getTier1Gateway(String tier1GatewayId) {
try {
Tier1s tier1service = (Tier1s) nsxService.apply(Tier1s.class);
return tier1service.get(tier1GatewayId);
} catch (Exception e) {
LOGGER.debug(String.format("NSX Tier-1 gateway with name: %s not found", tier1GatewayId));
}
return null;
}
private SiteListResult getSites() {
try {
Sites sites = (Sites) nsxService.apply(Sites.class);
return sites.list(null, false, null, null, null, null);
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Failed to fetch service segment list due to %s", e.getMessage()));
}
}
private EnforcementPointListResult getEnforcementPoints(String siteId) {
try {
EnforcementPoints enforcementPoints = (EnforcementPoints) nsxService.apply(EnforcementPoints.class);
return enforcementPoints.list(siteId, null, false, null, null, null, null);
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Failed to fetch service segment list due to %s", e.getMessage()));
}
}
private TransportZoneListResult getTransportZones() {
try {
com.vmware.nsx.TransportZones transportZones = (com.vmware.nsx.TransportZones) nsxService.apply(com.vmware.nsx.TransportZones.class);
return transportZones.list(null, null, true, null, true, null, null, null, OVERLAY.name(), null);
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Failed to fetch service segment list due to %s", e.getMessage()));
}
}
private String getTier1GatewayName(CreateNsxTier1GatewayCommand cmd) {
return cmd.getZoneName() + "-" + cmd.getAccountName() + "-" + cmd.getVpcName();
}
private String getSegmentName(String accountName, String tierNetworkName, String vpcName) {
String segmentName = accountName + "-";
if (isNull(vpcName)) {
return segmentName + tierNetworkName;
}
return segmentName + vpcName + "-" + tierNetworkName;
}
private String getDhcpRelayId(String zoneName, String accountName, String vpcName, String networkName) {
String suffix = "-Relay";
if (isNull(vpcName)) {
return zoneName + "-" + accountName + "-" + networkName + suffix;
}
return String.format("%s-%s-%s-%s%s", zoneName, accountName, vpcName, networkName, suffix);
}
@Override
public boolean start() {
return true;

View File

@ -1,32 +0,0 @@
// 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.
package org.apache.cloudstack.service;
import com.vmware.vapi.client.ApiClient;
public class NsxApi {
ApiClient apiClient;
public ApiClient getApiClient() {
return apiClient;
}
public void setApiClient(ApiClient apiClient) {
this.apiClient = apiClient;
}
}

View File

@ -0,0 +1,293 @@
// 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.
package org.apache.cloudstack.service;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.utils.exception.CloudRuntimeException;
import com.vmware.nsx.model.TransportZone;
import com.vmware.nsx.model.TransportZoneListResult;
import com.vmware.nsx_policy.infra.DhcpRelayConfigs;
import com.vmware.nsx_policy.infra.Segments;
import com.vmware.nsx_policy.infra.Sites;
import com.vmware.nsx_policy.infra.Tier1s;
import com.vmware.nsx_policy.infra.sites.EnforcementPoints;
import com.vmware.nsx_policy.infra.tier_0s.LocaleServices;
import com.vmware.nsx_policy.model.ApiError;
import com.vmware.nsx_policy.model.DhcpRelayConfig;
import com.vmware.nsx_policy.model.EnforcementPointListResult;
import com.vmware.nsx_policy.model.LocaleServicesListResult;
import com.vmware.nsx_policy.model.Segment;
import com.vmware.nsx_policy.model.SegmentSubnet;
import com.vmware.nsx_policy.model.SiteListResult;
import com.vmware.nsx_policy.model.Tier1;
import com.vmware.vapi.bindings.Service;
import com.vmware.vapi.bindings.StubConfiguration;
import com.vmware.vapi.cis.authn.SecurityContextFactory;
import com.vmware.vapi.client.ApiClient;
import com.vmware.vapi.client.ApiClients;
import com.vmware.vapi.client.Configuration;
import com.vmware.vapi.core.ExecutionContext;
import com.vmware.vapi.internal.protocol.RestProtocol;
import com.vmware.vapi.internal.protocol.client.rest.authn.BasicAuthenticationAppender;
import com.vmware.vapi.protocol.HttpConfiguration;
import com.vmware.vapi.std.errors.Error;
import org.apache.cloudstack.utils.NsxControllerUtils;
import org.apache.log4j.Logger;
import java.util.List;
import java.util.function.Function;
import static java.util.Objects.isNull;
public class NsxApiClient {
private final Function<Class<? extends Service>, Service> nsxService;
public static final int RESPONSE_TIMEOUT_SECONDS = 60;
private static final Logger LOGGER = Logger.getLogger(NsxApiClient.class);
// Constants
private static final String TIER_1_RESOURCE_TYPE = "Tier1";
private static final String Tier_1_LOCALE_SERVICE_ID = "default";
private static final String SEGMENT_RESOURCE_TYPE = "Segment";
private static final String TIER_0_GATEWAY_PATH_PREFIX = "/infra/tier-0s/";
private static final String TIER_1_GATEWAY_PATH_PREFIX = "/infra/tier-1s/";
private enum PoolAllocation { ROUTING, LB_SMALL, LB_MEDIUM, LB_LARGE, LB_XLARGE }
private enum TYPE { ROUTED, NATTED }
private enum HAMode { ACTIVE_STANDBY, ACTIVE_ACTIVE }
private enum FailoverMode { PREEMPTIVE, NON_PREEMPTIVE }
private enum AdminState { UP, DOWN }
private enum TransportType { OVERLAY, VLAN }
public enum RouteAdvertisementType { TIER1_STATIC_ROUTES, TIER1_CONNECTED, TIER1_NAT,
TIER1_LB_VIP, TIER1_LB_SNAT, TIER1_DNS_FORWARDER_IP, TIER1_IPSEC_LOCAL_ENDPOINT
}
public NsxApiClient(String hostname, String port, String username, char[] password) {
String controllerUrl = String.format("https://%s:%s", hostname, port);
HttpConfiguration.SslConfiguration.Builder sslConfigBuilder = new HttpConfiguration.SslConfiguration.Builder();
sslConfigBuilder
.disableCertificateValidation()
.disableHostnameVerification();
HttpConfiguration.SslConfiguration sslConfig = sslConfigBuilder.getConfig();
HttpConfiguration httpConfig = new HttpConfiguration.Builder()
.setSoTimeout(RESPONSE_TIMEOUT_SECONDS * 1000)
.setSslConfiguration(sslConfig).getConfig();
StubConfiguration stubConfig = new StubConfiguration();
ExecutionContext.SecurityContext securityContext = SecurityContextFactory
.createUserPassSecurityContext(username, password);
stubConfig.setSecurityContext(securityContext);
Configuration.Builder configBuilder = new Configuration.Builder()
.register(Configuration.HTTP_CONFIG_CFG, httpConfig)
.register(Configuration.STUB_CONFIG_CFG, stubConfig)
.register(RestProtocol.REST_REQUEST_AUTHENTICATOR_CFG, new BasicAuthenticationAppender());
Configuration config = configBuilder.build();
ApiClient apiClient = ApiClients.newRestClient(controllerUrl, config);
nsxService = apiClient::createStub;
}
public void createDhcpRelayConfig(String dhcpRelayConfigName, List<String> addresses) {
try {
DhcpRelayConfigs service = (DhcpRelayConfigs) nsxService.apply(DhcpRelayConfigs.class);
DhcpRelayConfig config = new DhcpRelayConfig.Builder()
.setServerAddresses(addresses)
.setId(dhcpRelayConfigName)
.setDisplayName(dhcpRelayConfigName)
.build();
service.patch(dhcpRelayConfigName, config);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
String msg = String.format("Error creating the DHCP relay config with name %s: %s", dhcpRelayConfigName, ae.getErrorMessage());
LOGGER.error(msg);
throw new CloudRuntimeException(ae.getErrorMessage());
}
}
public Segment getSegmentById(String segmentName) {
try {
Segments segmentService = (Segments) nsxService.apply(Segments.class);
return segmentService.get(segmentName);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
String msg = String.format("Error obtaining the segment with name %s: %s", segmentName, ae.getErrorMessage());
LOGGER.error(msg);
throw new CloudRuntimeException(ae.getErrorMessage());
}
}
public void updateSegment(String segmentName, Segment segment) {
try {
Segments segmentService = (Segments) nsxService.apply(Segments.class);
segmentService.patch(segmentName, segment);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
String msg = String.format("Error updating the segment with name %s: %s", segmentName, ae.getErrorMessage());
LOGGER.error(msg);
throw new CloudRuntimeException(ae.getErrorMessage());
}
}
private Tier1 getTier1Gateway(String tier1GatewayId) {
try {
Tier1s tier1service = (Tier1s) nsxService.apply(Tier1s.class);
return tier1service.get(tier1GatewayId);
} catch (Exception e) {
LOGGER.debug(String.format("NSX Tier-1 gateway with name: %s not found", tier1GatewayId));
}
return null;
}
private List<com.vmware.nsx_policy.model.LocaleServices> getTier0LocalServices(String tier0Gateway) {
try {
LocaleServices tier0LocaleServices = (LocaleServices) nsxService.apply(LocaleServices.class);
LocaleServicesListResult result = tier0LocaleServices.list(tier0Gateway, null, false, null, null, null, null);
return result.getResults();
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Failed to fetch locale services for tier gateway %s due to %s", tier0Gateway, e.getMessage()));
}
}
/**
* To instantiate Tier-1 in Edge Cluster
*/
private void createTier1LocaleServices(String tier1Id, String edgeCluster, String tier0Gateway) {
try {
List<com.vmware.nsx_policy.model.LocaleServices> localeServices = getTier0LocalServices(tier0Gateway);
com.vmware.nsx_policy.infra.tier_1s.LocaleServices tier1LocalService = (com.vmware.nsx_policy.infra.tier_1s.LocaleServices) nsxService.apply(com.vmware.nsx_policy.infra.tier_1s.LocaleServices.class);
com.vmware.nsx_policy.model.LocaleServices localeService = new com.vmware.nsx_policy.model.LocaleServices.Builder()
.setEdgeClusterPath(localeServices.get(0).getEdgeClusterPath()).build();
tier1LocalService.patch(tier1Id, Tier_1_LOCALE_SERVICE_ID, localeService);
} catch (Error error) {
throw new CloudRuntimeException(String.format("Failed to instantiate tier-1 gateway %s in edge cluster %s", tier1Id, edgeCluster));
}
}
public void createTier1Gateway(String name, String tier0Gateway, String edgeCluster) {
String tier0GatewayPath = TIER_0_GATEWAY_PATH_PREFIX + tier0Gateway;
Tier1 tier1 = getTier1Gateway(name);
if (tier1 != null) {
throw new InvalidParameterValueException(String.format("VPC network with name %s exists in NSX zone", name));
}
Tier1s tier1service = (Tier1s) nsxService.apply(Tier1s.class);
tier1 = new Tier1.Builder()
.setTier0Path(tier0GatewayPath)
.setResourceType(TIER_1_RESOURCE_TYPE)
.setPoolAllocation(PoolAllocation.ROUTING.name())
.setHaMode(HAMode.ACTIVE_STANDBY.name())
.setFailoverMode(FailoverMode.PREEMPTIVE.name())
.setRouteAdvertisementTypes(List.of(RouteAdvertisementType.TIER1_CONNECTED.name(), RouteAdvertisementType.TIER1_IPSEC_LOCAL_ENDPOINT.name()))
.setId(name)
.setDisplayName(name)
.build();
try {
tier1service.patch(name, tier1);
createTier1LocaleServices(name, edgeCluster, tier0Gateway);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
String msg = String.format("Error creating tier 1 gateway %s: %s", name, ae.getErrorMessage());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
}
public void deleteTier1Gateway(String tier1Id) {
com.vmware.nsx_policy.infra.tier_1s.LocaleServices localeService = (com.vmware.nsx_policy.infra.tier_1s.LocaleServices)
nsxService.apply(com.vmware.nsx_policy.infra.tier_1s.LocaleServices.class);
localeService.delete(tier1Id, Tier_1_LOCALE_SERVICE_ID);
Tier1s tier1service = (Tier1s) nsxService.apply(Tier1s.class);
tier1service.delete(tier1Id);
}
public SiteListResult getSites() {
try {
Sites sites = (Sites) nsxService.apply(Sites.class);
return sites.list(null, false, null, null, null, null);
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Failed to fetch service segment list due to %s", e.getMessage()));
}
}
public EnforcementPointListResult getEnforcementPoints(String siteId) {
try {
EnforcementPoints enforcementPoints = (EnforcementPoints) nsxService.apply(EnforcementPoints.class);
return enforcementPoints.list(siteId, null, false, null, null, null, null);
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Failed to fetch service segment list due to %s", e.getMessage()));
}
}
public TransportZoneListResult getTransportZones() {
try {
com.vmware.nsx.TransportZones transportZones = (com.vmware.nsx.TransportZones) nsxService.apply(com.vmware.nsx.TransportZones.class);
return transportZones.list(null, null, true, null, true, null, null, null, TransportType.OVERLAY.name(), null);
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Failed to fetch service segment list due to %s", e.getMessage()));
}
}
public void createSegment(long zoneId, long domainId, long accountId, Long vpcId, String segmentName, String gatewayAddress, String tier0Gateway, String enforcementPointPath, List<TransportZone> transportZones) {
try {
Segments segmentService = (Segments) nsxService.apply(Segments.class);
SegmentSubnet subnet = new SegmentSubnet.Builder()
.setGatewayAddress(gatewayAddress)
.build();
Segment segment = new Segment.Builder()
.setResourceType(SEGMENT_RESOURCE_TYPE)
.setId(segmentName)
.setDisplayName(segmentName)
.setConnectivityPath(isNull(vpcId) ? TIER_0_GATEWAY_PATH_PREFIX + tier0Gateway
: TIER_1_GATEWAY_PATH_PREFIX + NsxControllerUtils.getTier1GatewayName(domainId, accountId, zoneId, vpcId))
.setAdminState(AdminState.UP.name())
.setSubnets(List.of(subnet))
.setTransportZonePath(enforcementPointPath + "/transport-zones/" + transportZones.get(0).getId())
.build();
segmentService.patch(segmentName, segment);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
String msg = String.format("Error creating segment %s: %s", segmentName, ae.getErrorMessage());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
}
public void deleteSegment(long zoneId, long domainId, long accountId, long vpcId, long networkId, String segmentName) {
try {
Segments segmentService = (Segments) nsxService.apply(Segments.class);
LOGGER.debug(String.format("Removing the segment with ID %s", segmentName));
segmentService.delete(segmentName);
DhcpRelayConfigs dhcpRelayConfig = (DhcpRelayConfigs) nsxService.apply(DhcpRelayConfigs.class);
String dhcpRelayConfigId = NsxControllerUtils.getNsxDhcpRelayConfigId(zoneId, domainId, accountId, vpcId, networkId);
LOGGER.debug(String.format("Removing the DHCP relay config with ID %s", dhcpRelayConfigId));
dhcpRelayConfig.delete(dhcpRelayConfigId);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
String msg = String.format("Error deleting segment %s: %s", segmentName, ae.getErrorMessage());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
}
}

View File

@ -27,6 +27,8 @@ import com.cloud.agent.api.StartupCommand;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ConnectionException;
import com.cloud.exception.InsufficientCapacityException;
@ -59,6 +61,7 @@ import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.utils.Pair;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachineProfile;
@ -96,6 +99,8 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS
PhysicalNetworkDao physicalNetworkDao;
@Inject
NetworkModel networkModel;
@Inject
DomainDao domainDao;
private static final Logger LOGGER = Logger.getLogger(NsxElement.class);
@ -112,9 +117,10 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS
dnsCapabilities.put(Network.Capability.AllowDnsSuffixModification, "true");
capabilities.put(Network.Service.Dns, dnsCapabilities);
// capabilities.put(Network.Service.Connectivity, null);
capabilities.put(Network.Service.StaticNat, null);
capabilities.put(Network.Service.Lb, null);
capabilities.put(Network.Service.PortForwarding, null);
capabilities.put(Network.Service.NetworkACL, null);
Map<Network.Capability, String> sourceNatCapabilities = new HashMap<>();
sourceNatCapabilities.put(Network.Capability.RedundantRouter, "true");
sourceNatCapabilities.put(Network.Capability.SupportedSourceNatTypes, "peraccount");
@ -195,7 +201,14 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
Account account = accountMgr.getAccount(network.getAccountId());
NetworkVO networkVO = networkDao.findById(network.getId());
return nsxService.deleteNetwork(account.getAccountName(), networkVO);
DataCenterVO zone = dataCenterDao.findById(network.getDataCenterId());
DomainVO domain = domainDao.findById(account.getDomainId());
if (Objects.isNull(zone)) {
String msg = String.format("Cannot find zone with ID %s", network.getDataCenterId());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
return nsxService.deleteNetwork(zone.getId(), account.getId(), domain.getId(), networkVO);
}
@Override
@ -215,14 +228,14 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS
@Override
public boolean verifyServicesCombination(Set<Network.Service> services) {
return false;
return true;
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
agentManager.registerForHostEvents(this, true, true, true);
resourceManager.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
return false;
return true;
}
@Override
@ -254,6 +267,16 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS
return null;
}
private DomainVO getDomainFromAccount(Account account) {
DomainVO domain = domainDao.findById(account.getDomainId());
if (Objects.isNull(domain)) {
String msg = String.format("Unable to find domain with id: %s", account.getDomainId());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
return domain;
}
@Override
public boolean implementVpc(Vpc vpc, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
DataCenterVO zone = zoneFunction.apply(vpc.getZoneId());
@ -265,7 +288,8 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS
throw new InvalidParameterValueException(String.format("Failed to find account with id %s", vpc.getAccountId()));
}
Account account = isNsxAndAccount.second();
return nsxService.createVpcNetwork(vpc.getZoneId(), zone.getName(), account.getAccountId(), account.getName(), vpc.getName());
DomainVO domain = getDomainFromAccount(account);
return nsxService.createVpcNetwork(vpc.getZoneId(), account.getId(), domain.getId(), vpc.getId(), vpc.getName());
}
@Override
@ -279,8 +303,8 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS
throw new InvalidParameterValueException(String.format("Failed to find account with id %s", vpc.getAccountId()));
}
Account account = isNsxAndAccount.second();
return nsxService.deleteVpcNetwork(vpc.getZoneId(), zone.getName(), account.getAccountId(), account.getName(), vpc.getName());
DomainVO domain = getDomainFromAccount(account);
return nsxService.deleteVpcNetwork(vpc.getZoneId(), account.getId(), domain.getId(), vpc.getId(), vpc.getName());
}
private Pair<Boolean, Account> validateVpcConfigurationAndGetAccount(DataCenterVO zone, Vpc vpc) {

View File

@ -20,9 +20,10 @@ import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import com.cloud.dc.DataCenter;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
import com.cloud.exception.InvalidParameterValueException;
@ -48,6 +49,9 @@ import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.agent.api.CreateNsxDhcpRelayConfigCommand;
import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand;
import org.apache.cloudstack.utils.NsxControllerUtils;
import org.apache.cloudstack.utils.NsxHelper;
import org.apache.log4j.Logger;
import javax.inject.Inject;
@ -62,9 +66,9 @@ public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr
@Inject
NsxControllerUtils nsxControllerUtils;
@Inject
DataCenterDao zoneDao;
@Inject
AccountDao accountDao;
@Inject
DomainDao domainDao;
public NsxGuestNetworkGuru() {
super();
@ -130,17 +134,23 @@ public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr
implemented.setName(name);
}
implemented.setBroadcastUri(Networks.BroadcastDomainType.NSX.toUri("nsx"));
return network;
}
@Override
public void setup(Network network, long networkId) {
try {
NetworkVO designedNetwork = _networkDao.findById(networkId);
long zoneId = network.getDataCenterId();
DataCenter zone = zoneDao.findById(zoneId);
DataCenter zone = _dcDao.findById(zoneId);
if (isNull(zone)) {
throw new CloudRuntimeException(String.format("Failed to find zone with id: %s", zoneId));
}
createNsxSegment(implemented, zone);
createNsxSegment(designedNetwork, zone);
} catch (Exception ex) {
throw new CloudRuntimeException("unable to create NSX network " + network.getUuid() + "due to: " + ex.getMessage());
}
return network;
}
@Override
@ -173,16 +183,6 @@ public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr
implemented.setName(network.getName());
}
implemented.setBroadcastUri(Networks.BroadcastDomainType.NSX.toUri("nsx"));
// try {
// long zoneId = network.getDataCenterId();
// DataCenter zone = zoneDao.findById(zoneId);
// if (isNull(zone)) {
// throw new CloudRuntimeException(String.format("Failed to find zone with id: %s", zoneId));
// }
// createNsxSegment(implemented, zone);
// } catch (Exception ex) {
// throw new CloudRuntimeException("unable to create NSX network " + network.getUuid() + "due to: " + ex.getMessage());
// }
return implemented;
}
@ -211,12 +211,17 @@ public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr
throw new CloudRuntimeException(msg);
}
DomainVO domain = domainDao.findById(account.getDomainId());
if (Objects.isNull(domain)) {
String msg = String.format("Unable to find domain with id: %s", account.getDomainId());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
// Create the DHCP relay config for the segment
String iPv4Address = nicProfile.getIPv4Address();
List<String> addresses = List.of(iPv4Address);
CreateNsxDhcpRelayConfigCommand command = new CreateNsxDhcpRelayConfigCommand(zone.getName(), zone.getId(),
account.getAccountName(), network.getAccountId(),
vpc.getName(), network.getName(), addresses);
CreateNsxDhcpRelayConfigCommand command = NsxHelper.createNsxDhcpRelayConfigCommand(domain, account, zone, vpc, network, addresses);
NsxAnswer answer = nsxControllerUtils.sendNsxCommand(command, zone.getId());
if (!answer.getResult()) {
String msg = String.format("Error creating DHCP relay config for network %s and nic %s: %s", network.getName(), nic.getName(), answer.getDetails());
@ -265,7 +270,7 @@ public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr
}
private void createNsxSegment(NetworkVO networkVO, DataCenter zone) {
String vpcName = null;
String vpcName = null;
if (nonNull(networkVO.getVpcId())) {
VpcVO vpc = _vpcDao.findById(networkVO.getVpcId());
if (isNull(vpc)) {
@ -277,8 +282,13 @@ public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr
if (isNull(account)) {
throw new CloudRuntimeException(String.format("Unable to find account with id: %s", networkVO.getAccountId()));
}
CreateNsxSegmentCommand command = new CreateNsxSegmentCommand(zone.getName(), zone.getId(),
account.getAccountName(), networkVO.getAccountId(), vpcName, networkVO);
DomainVO domain = domainDao.findById(account.getDomainId());
if (Objects.isNull(domain)) {
String msg = String.format("Unable to find domain with id: %s", account.getDomainId());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
CreateNsxSegmentCommand command = NsxHelper.createNsxSegmentCommand(domain, account, zone, vpcName, networkVO);
NsxAnswer answer = nsxControllerUtils.sendNsxCommand(command, zone.getId());
if (!answer.getResult()) {
throw new CloudRuntimeException("can not create NSX network");

View File

@ -53,9 +53,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.UUID;
public class NsxProviderServiceImpl implements NsxProviderService {
@Inject

View File

@ -23,37 +23,39 @@ import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand;
import org.apache.cloudstack.utils.NsxControllerUtils;
import javax.inject.Inject;
import java.util.Objects;
public class NsxServiceImpl implements NsxService {
@Inject
private NsxControllerUtils nsxControllerUtils;
NsxControllerUtils nsxControllerUtils;
@Inject
private VpcDao vpcDao;
VpcDao vpcDao;
public boolean createVpcNetwork(Long zoneId, String zoneName, Long accountId, String accountName, String vpcName) {
public boolean createVpcNetwork(Long zoneId, long accountId, long domainId, long vpcId, String vpcName) {
CreateNsxTier1GatewayCommand createNsxTier1GatewayCommand =
new CreateNsxTier1GatewayCommand(zoneName, zoneId, accountName, accountId, vpcName);
new CreateNsxTier1GatewayCommand(domainId, accountId, zoneId, vpcId, vpcName);
NsxAnswer result = nsxControllerUtils.sendNsxCommand(createNsxTier1GatewayCommand, zoneId);
return result.getResult();
}
public boolean deleteVpcNetwork(Long zoneId, String zoneName, Long accountId, String accountName, String vpcName) {
public boolean deleteVpcNetwork(Long zoneId, long accountId, long domainId, Long vpcId, String vpcName) {
DeleteNsxTier1GatewayCommand deleteNsxTier1GatewayCommand =
new DeleteNsxTier1GatewayCommand(zoneName, zoneId, accountName, accountId, vpcName);
new DeleteNsxTier1GatewayCommand(domainId, accountId, zoneId, vpcId, vpcName);
NsxAnswer result = nsxControllerUtils.sendNsxCommand(deleteNsxTier1GatewayCommand, zoneId);
return result.getResult();
}
public boolean deleteNetwork(String accountName, NetworkVO network) {
public boolean deleteNetwork(long zoneId, long accountId, long domainId, NetworkVO network) {
String vpcName = null;
if (Objects.nonNull(network.getVpcId())) {
VpcVO vpc = vpcDao.findById(network.getVpcId());
vpcName = Objects.nonNull(vpc) ? vpc.getName() : null;
}
DeleteNsxSegmentCommand deleteNsxSegmentCommand = new DeleteNsxSegmentCommand(accountName, vpcName, network);
DeleteNsxSegmentCommand deleteNsxSegmentCommand = new DeleteNsxSegmentCommand(domainId, accountId, zoneId,
network.getVpcId(), vpcName, network.getId(), network.getName());
NsxAnswer result = nsxControllerUtils.sendNsxCommand(deleteNsxSegmentCommand, network.getDataCenterId());
return result.getResult();
}

View File

@ -1,103 +0,0 @@
// 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.
package org.apache.cloudstack.utils;
import com.vmware.vapi.bindings.StubConfiguration;
import com.vmware.vapi.cis.authn.SecurityContextFactory;
import com.vmware.vapi.client.ApiClient;
import com.vmware.vapi.client.ApiClients;
import com.vmware.vapi.client.Configuration;
import com.vmware.vapi.core.ExecutionContext.SecurityContext;
import com.vmware.vapi.internal.protocol.RestProtocol;
import com.vmware.vapi.internal.protocol.client.rest.authn.BasicAuthenticationAppender;
import com.vmware.vapi.protocol.HttpConfiguration;
import org.apache.log4j.Logger;
public class NsxApiClientUtils {
private static final Logger S_LOGGER = Logger.getLogger(NsxApiClientUtils.class);
public static ApiClient apiClient = null;
public static final int RESPONSE_TIMEOUT_SECONDS = 60;
public enum PoolAllocation {
ROUTING,
LB_SMALL,
LB_MEDIUM,
LB_LARGE,
LB_XLARGE
}
public enum TYPE {
ROUTED,
NATTED
}
public enum HAMode {
ACTIVE_STANDBY,
ACTIVE_ACTIVE
}
public enum FailoverMode {
PREEMPTIVE,
NON_PREEMPTIVE
}
public enum AdminState {
UP,
DOWN
}
public enum TransportType {
OVERLAY,
VLAN
}
public enum RouteAdvertisementType {
TIER1_STATIC_ROUTES,
TIER1_CONNECTED,
TIER1_NAT,
TIER1_LB_VIP,
TIER1_LB_SNAT,
TIER1_DNS_FORWARDER_IP,
TIER1_IPSEC_LOCAL_ENDPOINT
}
public static ApiClient createApiClient(String hostname, String port, String username, char[] password) {
String controllerUrl = String.format("https://%s:%s", hostname, port);
HttpConfiguration.SslConfiguration.Builder sslConfigBuilder = new HttpConfiguration.SslConfiguration.Builder();
sslConfigBuilder
.disableCertificateValidation()
.disableHostnameVerification();
HttpConfiguration.SslConfiguration sslConfig = sslConfigBuilder.getConfig();
HttpConfiguration httpConfig = new HttpConfiguration.Builder()
.setSoTimeout(RESPONSE_TIMEOUT_SECONDS * 1000)
.setSslConfiguration(sslConfig).getConfig();
StubConfiguration stubConfig = new StubConfiguration();
SecurityContext securityContext = SecurityContextFactory
.createUserPassSecurityContext(username, password);
stubConfig.setSecurityContext(securityContext);
Configuration.Builder configBuilder = new Configuration.Builder()
.register(Configuration.HTTP_CONFIG_CFG, httpConfig)
.register(Configuration.STUB_CONFIG_CFG, stubConfig)
.register(RestProtocol.REST_REQUEST_AUTHENTICATOR_CFG, new BasicAuthenticationAppender());
Configuration config = configBuilder.build();
apiClient = ApiClients.newRestClient(controllerUrl, config);
return apiClient;
}
}

View File

@ -14,7 +14,7 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.service;
package org.apache.cloudstack.utils;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
@ -28,6 +28,8 @@ import org.springframework.stereotype.Component;
import javax.inject.Inject;
import static java.util.Objects.isNull;
@Component
public class NsxControllerUtils {
private static final Logger s_logger = Logger.getLogger(NsxControllerUtils.class);
@ -53,4 +55,24 @@ public class NsxControllerUtils {
return (NsxAnswer) answer;
}
public static String getTier1GatewayName(long domainId, long accountId, long zoneId, long vpcId) {
return String.format("D%s-A%s-Z%s-V%s", domainId, accountId, zoneId, vpcId);
}
public static String getNsxSegmentId(long domainId, long accountId, long zoneId, Long vpcId, long networkId) {
String segmentName = String.format("D%s-A%s-Z%s", domainId, accountId, zoneId);
if (isNull(vpcId)) {
return String.format("%s-S%s", segmentName, networkId);
}
return String.format("%s-V%s-S%s",segmentName, vpcId, networkId);
}
public static String getNsxDhcpRelayConfigId(long zoneId, long domainId, long accountId, Long vpcId, long networkId) {
String suffix = "Relay";
if (isNull(vpcId)) {
return String.format("D%s-A%s-Z%s-S%s-%s", domainId, accountId, zoneId, networkId, suffix);
}
return String.format("D%s-A%s-Z%s-V%s-S%s-%s", domainId, accountId, zoneId, vpcId, networkId, suffix);
}
}

View File

@ -0,0 +1,41 @@
// 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.
package org.apache.cloudstack.utils;
import com.cloud.dc.DataCenter;
import com.cloud.domain.DomainVO;
import com.cloud.network.Network;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.vpc.VpcVO;
import com.cloud.user.Account;
import org.apache.cloudstack.agent.api.CreateNsxDhcpRelayConfigCommand;
import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand;
import java.util.List;
public class NsxHelper {
public static CreateNsxDhcpRelayConfigCommand createNsxDhcpRelayConfigCommand(DomainVO domain, Account account, DataCenter zone, VpcVO vpc, Network network, List<String> addresses) {
return new CreateNsxDhcpRelayConfigCommand(domain.getId(), account.getId(), zone.getId(),
vpc.getId(), vpc.getName(), network.getId(), network.getName(), addresses);
}
public static CreateNsxSegmentCommand createNsxSegmentCommand(DomainVO domain, Account account, DataCenter zone, String vpcName, NetworkVO networkVO) {
return new CreateNsxSegmentCommand(domain.getId(), account.getId(), zone.getId(),
networkVO.getVpcId(), vpcName, networkVO.getId(), networkVO.getName(), networkVO.getGateway(), networkVO.getCidr());
}
}

View File

@ -33,6 +33,6 @@
</bean>
<bean id="nsxProviderService" class="org.apache.cloudstack.service.NsxProviderServiceImpl"/>
<bean id="nsxService" class="org.apache.cloudstack.service.NsxServiceImpl"/>
<bean id="nsxControllerUtils" class="org.apache.cloudstack.service.NsxControllerUtils" />
<bean id="nsxControllerUtils" class="org.apache.cloudstack.utils.NsxControllerUtils" />
</beans>

View File

@ -0,0 +1,163 @@
// 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.
package org.apache.cloudstack.resource;
import com.cloud.network.dao.NetworkVO;
import com.vmware.nsx.model.TransportZone;
import com.vmware.nsx.model.TransportZoneListResult;
import com.vmware.nsx_policy.model.EnforcementPoint;
import com.vmware.nsx_policy.model.EnforcementPointListResult;
import com.vmware.nsx_policy.model.Site;
import com.vmware.nsx_policy.model.SiteListResult;
import junit.framework.Assert;
import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand;
import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand;
import org.apache.cloudstack.agent.api.NsxCommand;
import org.apache.cloudstack.service.NsxApiClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import javax.naming.ConfigurationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class NsxResourceTest {
@Mock
NsxApiClient nsxApi;
NsxResource nsxResource;
AutoCloseable closeable;
@Mock
EnforcementPointListResult enforcementPointListResult;
@Mock
SiteListResult siteListResult;
@Mock
TransportZoneListResult transportZoneListResult;
@Before
public void setup() {
closeable = MockitoAnnotations.openMocks(this);
nsxResource = new NsxResource();
nsxResource.nsxApiClient = nsxApi;
nsxResource.transportZone = "Overlay";
}
@After
public void tearDown() throws Exception {
closeable.close();
}
@Test
public void testConfigure() throws ConfigurationException {
Map<String, Object> params = new HashMap<>();
params.put("name", "nsxController");
params.put("guid", "5944b356-644f-11ee-b8c2-f37bc1b564ff");
params.put("zoneId", "1");
params.put("hostname", "host1");
params.put("username", "admin");
params.put("password", "password");
params.put("tier0Gateway", "Tier0-GW01");
params.put("edgeCluster", "EdgeCluster");
params.put("transportZone", "Overlay");
params.put("port", "443");
Assert.assertTrue(nsxResource.configure("nsx", params));
}
@Test
public void testConfigure_MissingParameter() throws ConfigurationException {
Map<String, Object> params = new HashMap<>();
assertThrows(ConfigurationException.class, () -> nsxResource.configure("nsx", params));
}
@Test
public void testCreateNsxTier1Gateway() {
NsxCommand command = new CreateNsxTier1GatewayCommand(1L, 2L,
1L, 3L, "VPC01");
NsxAnswer answer = (NsxAnswer) nsxResource.executeRequest(command);
assertTrue(answer.getResult());
}
@Test
public void testDeleteTier1Gateway() {
NsxCommand command = new DeleteNsxTier1GatewayCommand(1L, 1L,
1L, 2L, "VPC01");
NsxAnswer answer = (NsxAnswer) nsxResource.executeRequest(command);
assertTrue(answer.getResult());
}
@Test
public void testCreateNsxSegment() {
NetworkVO tierNetwork = new NetworkVO();
tierNetwork.setName("tier1");
tierNetwork.setCidr("10.0.0.0/8");
tierNetwork.setGateway("10.0.0.1");
Site site = mock(Site.class);
List<Site> siteList = List.of(site);
EnforcementPoint enforcementPoint = mock(EnforcementPoint.class);
List<EnforcementPoint> enforcementPointList = List.of(enforcementPoint);
List<TransportZone> transportZoneList = List.of(new TransportZone.Builder().setDisplayName("Overlay").build());
NsxCommand command = new CreateNsxSegmentCommand(1L, 1L,
1L, 2L, "VPC01", 3L, "Web", "10.10.10.1", "10.10.10.0/24");
when(nsxApi.getSites()).thenReturn(siteListResult);
when(siteListResult.getResults()).thenReturn(siteList);
when(siteList.get(0).getId()).thenReturn("site1");
when(nsxApi.getEnforcementPoints(anyString())).thenReturn(enforcementPointListResult);
when(enforcementPointListResult.getResults()).thenReturn(enforcementPointList);
when(enforcementPointList.get(0).getPath()).thenReturn("enforcementPointPath");
when(nsxApi.getTransportZones()).thenReturn(transportZoneListResult);
when(transportZoneListResult.getResults()).thenReturn(transportZoneList);
NsxAnswer answer = (NsxAnswer) nsxResource.executeRequest(command);
assertTrue(answer.getResult());
}
@Test
public void testDeleteNsxSegment() {
NetworkVO tierNetwork = new NetworkVO();
tierNetwork.setName("tier1");
DeleteNsxSegmentCommand command = new DeleteNsxSegmentCommand(1L, 1L, 1L, 3L, "VPC01", 2L, "Web");
NsxAnswer answer = (NsxAnswer) nsxResource.executeRequest(command);
assertTrue(answer.getResult());
}
}

View File

@ -0,0 +1,132 @@
// 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.
package org.apache.cloudstack.service;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.NetworkModel;
import com.cloud.network.Networks;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.vpc.Vpc;
import com.cloud.resource.ResourceManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.vm.ReservationContext;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.List;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class NsxElementTest {
@Mock
DataCenterDao dataCenterDao;
@Mock
NsxServiceImpl nsxService;
@Mock
AccountManager accountManager;
@Mock
NetworkDao networkDao;
@Mock
ResourceManager resourceManager;
@Mock
PhysicalNetworkDao physicalNetworkDao;
@Mock
NetworkModel networkModel;
@Mock
Vpc vpc;
@Mock
DataCenterVO zone;
@Mock
DataCenterVO dataCenterVO;
@Mock
Account account;
@Mock
DomainVO domain;
NsxElement nsxElement;
ReservationContext reservationContext;
DeployDestination deployDestination;
@Mock
DomainDao domainDao;
@Before
public void setup() {
nsxElement = new NsxElement();
nsxElement.dataCenterDao = dataCenterDao;
nsxElement.nsxService = nsxService;
nsxElement.accountMgr = accountManager;
nsxElement.networkDao = networkDao;
nsxElement.resourceManager = resourceManager;
nsxElement.physicalNetworkDao = physicalNetworkDao;
nsxElement.domainDao = domainDao;
nsxElement.networkModel = networkModel;
reservationContext = mock(ReservationContext.class);
deployDestination = mock(DeployDestination.class);
when(vpc.getZoneId()).thenReturn(1L);
when(vpc.getAccountId()).thenReturn(2L);
when(dataCenterVO.getId()).thenReturn(1L);
when(vpc.getName()).thenReturn("VPC01");
when(accountManager.getAccount(2L)).thenReturn(account);
when(dataCenterDao.findById(anyLong())).thenReturn(dataCenterVO);
when(domainDao.findById(anyLong())).thenReturn(domain);
when(vpc.getZoneId()).thenReturn(1L);
when(vpc.getName()).thenReturn("testVPC");
PhysicalNetworkVO physicalNetworkVO = new PhysicalNetworkVO();
physicalNetworkVO.setIsolationMethods(List.of("NSX"));
List<PhysicalNetworkVO> physicalNetworkVOList = List.of(physicalNetworkVO);
when(physicalNetworkDao.listByZoneAndTrafficType(1L, Networks.TrafficType.Guest)).thenReturn(physicalNetworkVOList);
}
@Test
public void testImplementVpc() throws ResourceUnavailableException, InsufficientCapacityException {
when(nsxService.createVpcNetwork(anyLong(), anyLong(), anyLong(), anyLong(), anyString())).thenReturn(true);
assertTrue(nsxElement.implementVpc(vpc, deployDestination, reservationContext));
}
@Test
public void testShutdownVpc() {
when(nsxService.deleteVpcNetwork(anyLong(), anyLong(), anyLong(), anyLong(), anyString())).thenReturn(true);
assertTrue(nsxElement.shutdownVpc(vpc, reservationContext));
}
}

View File

@ -0,0 +1,217 @@
// 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.
package org.apache.cloudstack.service;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.Networks;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.user.Account;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.vm.ReservationContext;
import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand;
import org.apache.cloudstack.agent.api.NsxCommand;
import org.apache.cloudstack.utils.NsxControllerUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.List;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.lenient;
@RunWith(MockitoJUnitRunner.class)
public class NsxGuestNetworkGuruTest {
@Mock
PhysicalNetworkDao physicalNetworkDao;
@Mock
DataCenterDao dcDao;
@Mock
VpcDao vpcDao;
@Mock
NetworkOfferingServiceMapDao networkOfferingServiceMapDao;
@Mock
NsxControllerUtils nsxControllerUtils;
@Mock
AccountDao accountDao;
@Mock
PhysicalNetworkVO physicalNetwork;
@Mock
DataCenterVO dataCenterVO;
@Mock
NetworkOffering offering;
@Mock
DeploymentPlan plan;
@Mock
Network network;
@Mock
Account account;
@Mock
VpcVO vpcVO;
@Mock
NetworkModel networkModel;
@Mock
DomainDao domainDao;
@Mock
NetworkDao networkDao;
NsxGuestNetworkGuru guru;
AutoCloseable closeable;
@Before
public void setUp() {
closeable = MockitoAnnotations.openMocks(this);
guru = new NsxGuestNetworkGuru();
ReflectionTestUtils.setField(guru, "_physicalNetworkDao", physicalNetworkDao);
ReflectionTestUtils.setField(guru, "_dcDao", dcDao);
ReflectionTestUtils.setField(guru, "_networkDao", networkDao);
ReflectionTestUtils.setField(guru, "_networkModel", networkModel);
ReflectionTestUtils.setField(guru, "_vpcDao", vpcDao);
guru.networkOfferingServiceMapDao = networkOfferingServiceMapDao;
guru.nsxControllerUtils = nsxControllerUtils;
guru.accountDao = accountDao;
guru.domainDao = domainDao;
Mockito.when(dataCenterVO.getNetworkType()).thenReturn(DataCenter.NetworkType.Advanced);
when(physicalNetwork.getIsolationMethods()).thenReturn(List.of("NSX"));
when(offering.getTrafficType()).thenReturn(Networks.TrafficType.Guest);
when(offering.getGuestType()).thenReturn(Network.GuestType.Isolated);
when(offering.getId()).thenReturn(1L);
when(plan.getDataCenterId()).thenReturn(1L);
when(plan.getPhysicalNetworkId()).thenReturn(1L);
when(vpcDao.findById(anyLong())).thenReturn(vpcVO);
when(vpcVO.getName()).thenReturn("VPC01");
when(account.getAccountId()).thenReturn(1L);
when(accountDao.findById(anyLong())).thenReturn(mock(AccountVO.class));
when(domainDao.findById(anyLong())).thenReturn(mock(DomainVO.class));
Mockito.when(networkOfferingServiceMapDao.isProviderForNetworkOffering(offering.getId(), Network.Provider.Nsx)).thenReturn(
true);
}
@After
public void tearDown() throws Exception {
closeable.close();
}
@Test
public void testIsMyIsolationMethod() {
assertTrue(guru.isMyIsolationMethod(physicalNetwork));
}
@Test
public void testCanHandle() {
assertTrue(guru.canHandle(offering, dataCenterVO.getNetworkType(), physicalNetwork));
}
@Test
public void testNsxNetworkDesign() {
when(physicalNetworkDao.findById(ArgumentMatchers.anyLong())).thenReturn(physicalNetwork);
when(dcDao.findById(ArgumentMatchers.anyLong())).thenReturn(dataCenterVO);
Network designedNetwork = guru.design(offering, plan, network, "", 1L, account);
assertNotNull(designedNetwork);
assertSame(Networks.BroadcastDomainType.NSX, designedNetwork.getBroadcastDomainType());
assertSame(Network.State.Allocated, designedNetwork.getState());
}
@Test
public void testNsxNetworkSetup() {
when(dcDao.findById(ArgumentMatchers.anyLong())).thenReturn(dataCenterVO);
when(networkDao.findById(ArgumentMatchers.anyLong())).thenReturn(mock(NetworkVO.class));
when(nsxControllerUtils.sendNsxCommand(any(CreateNsxSegmentCommand.class), anyLong())).thenReturn(
new NsxAnswer(new NsxCommand(), true, ""));
guru.setup(network, 1L);
verify(nsxControllerUtils, times(1)).sendNsxCommand(any(CreateNsxSegmentCommand.class), anyLong());
}
@Test
public void testNsxNetworkImplementation() {
final DeployDestination deployDestination = mock(DeployDestination.class);
final ReservationContext reservationContext = mock(ReservationContext.class);
when(network.getTrafficType()).thenReturn(Networks.TrafficType.Guest);
when(network.getMode()).thenReturn(Networks.Mode.Dhcp);
when(network.getGateway()).thenReturn("192.168.1.1");
when(network.getCidr()).thenReturn("192.168.1.0/24");
when(network.getBroadcastDomainType()).thenReturn(Networks.BroadcastDomainType.NSX);
when(network.getNetworkOfferingId()).thenReturn(1L);
lenient().when(network.getState()).thenReturn(Network.State.Implementing);
when(network.getDataCenterId()).thenReturn(2L);
when(network.getPhysicalNetworkId()).thenReturn(3L);
when(network.getVpcId()).thenReturn(4L);
when(offering.isRedundantRouter()).thenReturn(false);
lenient().when(offering.getGuestType()).thenReturn(Network.GuestType.Isolated);
final Network implemented = guru.implement(network, offering, deployDestination, reservationContext);
assertEquals(Networks.BroadcastDomainType.NSX.toUri("nsx"), implemented.getBroadcastUri());
assertEquals("192.168.1.1", implemented.getGateway());
assertEquals("192.168.1.0/24", implemented.getCidr());
assertEquals(Networks.Mode.Dhcp, implemented.getMode());
assertEquals(Networks.BroadcastDomainType.NSX, implemented.getBroadcastDomainType());
assertEquals(1L, implemented.getNetworkOfferingId());
assertEquals(Network.State.Implemented, implemented.getState());
assertEquals(2L, implemented.getDataCenterId());
assertEquals(3L, implemented.getPhysicalNetworkId().longValue());
assertEquals(4L, implemented.getVpcId().longValue());
assertFalse(implemented.isRedundant());
}
}

View File

@ -0,0 +1,158 @@
// 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.
package org.apache.cloudstack.service;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.host.Host;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.network.NsxProvider;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.NsxProviderDao;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.element.NsxProviderVO;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ServerResource;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.command.AddNsxControllerCmd;
import org.apache.cloudstack.api.response.NsxControllerResponse;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.List;
import java.util.UUID;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class NsxProviderServiceImplTest {
@Mock
NsxProviderDao nsxProviderDao;
@Mock
DataCenterDao dataCenterDao;
@Mock
PhysicalNetworkDao physicalNetworkDao;
@Mock
NetworkDao networkDao;
@Mock
ResourceManager resourceManager;
@Mock
HostDetailsDao hostDetailsDao;
NsxProviderServiceImpl nsxProviderService;
@Before
public void setup() {
nsxProviderService = new NsxProviderServiceImpl();
nsxProviderService.resourceManager = resourceManager;
nsxProviderService.nsxProviderDao = nsxProviderDao;
nsxProviderService.hostDetailsDao = hostDetailsDao;
nsxProviderService.dataCenterDao = dataCenterDao;
nsxProviderService.networkDao = networkDao;
nsxProviderService.physicalNetworkDao = physicalNetworkDao;
}
@Test
public void testAddProvider() {
AddNsxControllerCmd cmd = mock(AddNsxControllerCmd.class);
when(cmd.getZoneId()).thenReturn(1L);
when(cmd.getName()).thenReturn("NsxController");
when(cmd.getHostname()).thenReturn("192.168.0.100");
when(cmd.getPort()).thenReturn("443");
when(cmd.getUsername()).thenReturn("admin");
when(cmd.getPassword()).thenReturn("password");
when(cmd.getEdgeCluster()).thenReturn("EdgeCluster");
when(cmd.getTier0Gateway()).thenReturn("Tier0-GW01");
when(cmd.getTransportZone()).thenReturn("Overlay");
when(resourceManager.addHost(anyLong(), any(ServerResource.class), any(Host.Type.class), anyMap())).thenReturn(mock(Host.class));
try {
NsxProvider provider = nsxProviderService.addProvider(cmd);
Assert.assertNotNull(provider);
} catch (CloudRuntimeException e) {
e.printStackTrace();
fail("Failed to add NSX controller due to internal error.");
}
}
@Test
public void testCreateNsxControllerResponse() {
NsxProvider nsxProvider = mock(NsxProvider.class);
DataCenterVO zone = mock(DataCenterVO.class);
String uuid = UUID.randomUUID().toString();
when(dataCenterDao.findById(anyLong())).thenReturn(zone);
when(zone.getUuid()).thenReturn(UUID.randomUUID().toString());
when(zone.getName()).thenReturn("ZoneNSX");
when(nsxProvider.getProviderName()).thenReturn("NSXController");
when(nsxProvider.getUuid()).thenReturn(uuid);
when(nsxProvider.getHostname()).thenReturn("hostname");
when(nsxProvider.getPort()).thenReturn("443");
when(nsxProvider.getTier0Gateway()).thenReturn("Tier0Gw");
when(nsxProvider.getEdgeCluster()).thenReturn("EdgeCluster");
when(nsxProvider.getTransportZone()).thenReturn("Overlay");
NsxControllerResponse response = nsxProviderService.createNsxControllerResponse(nsxProvider);
assertEquals(response.getEdgeCluster(), "EdgeCluster");
assertEquals(response.getTier0Gateway(), "Tier0Gw");
assertEquals(response.getTransportZone(), "Overlay");
assertEquals(response.getZoneName(), "ZoneNSX");
}
@Test
public void testListNsxControllers() {
NsxProviderVO nsxProviderVO = Mockito.mock(NsxProviderVO.class);
when(nsxProviderVO.getZoneId()).thenReturn(1L);
when(dataCenterDao.findById(1L)).thenReturn(mock(DataCenterVO.class));
when(nsxProviderDao.findByZoneId(anyLong())).thenReturn(nsxProviderVO);
List<BaseResponse> baseResponseList = nsxProviderService.listNsxProviders(1L);
assertEquals(1, baseResponseList.size());
}
@Test
public void testDeleteNsxController() {
NsxProviderVO nsxProviderVO = Mockito.mock(NsxProviderVO.class);
PhysicalNetworkVO physicalNetworkVO = mock(PhysicalNetworkVO.class);
List<PhysicalNetworkVO> physicalNetworkVOList = List.of(physicalNetworkVO);
NetworkVO networkVO = mock(NetworkVO.class);
List<NetworkVO> networkVOList = List.of(networkVO);
when(nsxProviderVO.getZoneId()).thenReturn(1L);
when(physicalNetworkVO.getId()).thenReturn(2L);
when(physicalNetworkDao.listByZone(1L)).thenReturn(physicalNetworkVOList);
when(nsxProviderDao.findById(anyLong())).thenReturn(nsxProviderVO);
when(networkDao.listByPhysicalNetwork(anyLong())).thenReturn(networkVOList);
assertTrue(nsxProviderService.deleteNsxController(1L));
}
}

View File

@ -0,0 +1,94 @@
// 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.
package org.apache.cloudstack.service;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand;
import org.apache.cloudstack.utils.NsxControllerUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class NsxServiceImplTest {
@Mock
private NsxControllerUtils nsxControllerUtils;
@Mock
private VpcDao vpcDao;
NsxServiceImpl nsxService;
AutoCloseable closeable;
@Before
public void setup() {
closeable = MockitoAnnotations.openMocks(this);
nsxService = new NsxServiceImpl();
nsxService.nsxControllerUtils = nsxControllerUtils;
nsxService.vpcDao = vpcDao;
}
@After
public void teardown() throws Exception {
closeable.close();
}
@Test
public void testCreateVpcNetwork() {
NsxAnswer createNsxTier1GatewayAnswer = mock(NsxAnswer.class);
when(nsxControllerUtils.sendNsxCommand(any(CreateNsxTier1GatewayCommand.class), anyLong())).thenReturn(createNsxTier1GatewayAnswer);
when(createNsxTier1GatewayAnswer.getResult()).thenReturn(true);
assertTrue(nsxService.createVpcNetwork(1L, 3L, 2L, 5L, "VPC01"));
}
@Test
public void testDeleteVpcNetwork() {
NsxAnswer deleteNsxTier1GatewayAnswer = mock(NsxAnswer.class);
when(nsxControllerUtils.sendNsxCommand(any(DeleteNsxTier1GatewayCommand.class), anyLong())).thenReturn(deleteNsxTier1GatewayAnswer);
when(deleteNsxTier1GatewayAnswer.getResult()).thenReturn(true);
assertTrue(nsxService.deleteVpcNetwork(1L, 2L, 3L, 10L, "VPC01"));
}
@Test
public void testDelete() {
NetworkVO network = new NetworkVO();
network.setVpcId(1L);
VpcVO vpc = mock(VpcVO.class);
when(vpcDao.findById(1L)).thenReturn(mock(VpcVO.class));
NsxAnswer deleteNsxSegmentAnswer = mock(NsxAnswer.class);
when(nsxControllerUtils.sendNsxCommand(any(DeleteNsxSegmentCommand.class), anyLong())).thenReturn(deleteNsxSegmentAnswer);
when(deleteNsxSegmentAnswer.getResult()).thenReturn(true);
assertTrue(nsxService.deleteNetwork(1L, 3L, 5L, network));
}
}

View File

@ -2332,6 +2332,7 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setForVpc(_configMgr.isOfferingForVpc(offering));
response.setForTungsten(offering.isForTungsten());
response.setForNsx(offering.isForNsx());
response.setNsxMode(offering.getNsxMode());
response.setServices(serviceResponses);
//set network offering details
Map<Detail, String> details = _ntwkModel.getNtwkOffDetails(offering.getId());

View File

@ -72,6 +72,8 @@ public class VpcOfferingJoinDaoImpl extends GenericDaoBase<VpcOfferingJoinVO, Lo
offeringResponse.setDomain(offeringJoinVO.getDomainPath());
offeringResponse.setZoneId(offeringJoinVO.getZoneUuid());
offeringResponse.setZone(offeringJoinVO.getZoneName());
offeringResponse.setForNsx(offeringJoinVO.isForNsx());
offeringResponse.setNsxMode(offeringJoinVO.getNsxMode());
String protocol = offeringJoinVO.getInternetProtocol();
if (StringUtils.isEmpty(protocol)) {
protocol = NetUtils.InternetProtocol.IPv4.toString();

View File

@ -159,6 +159,10 @@ public class NetworkOfferingJoinVO extends BaseViewVO implements NetworkOffering
@Column(name = "for_nsx")
boolean forNsx;
@Column(name = "nsx_mode")
String nsxMode;
@Column(name = "service_package_id")
private String servicePackageUuid = null;
@ -360,6 +364,15 @@ public class NetworkOfferingJoinVO extends BaseViewVO implements NetworkOffering
this.forNsx = forNsx;
}
@Override
public String getNsxMode() {
return nsxMode;
}
public void setNsxMode(String nsxMode) {
this.nsxMode = nsxMode;
}
public String getServicePackage() {
return servicePackageUuid;
}

View File

@ -77,6 +77,12 @@ public class VpcOfferingJoinVO implements VpcOffering {
@Column(name = "sort_key")
int sortKey;
@Column(name = "for_nsx")
boolean forNsx = false;
@Column(name = "nsx_mode")
String nsxMode;
@Column(name = "domain_id")
private String domainId;
@ -138,6 +144,16 @@ public class VpcOfferingJoinVO implements VpcOffering {
return isDefault;
}
@Override
public boolean isForNsx() {
return forNsx;
}
@Override
public String getNsxMode() {
return nsxMode;
}
@Override
public Date getRemoved() {
return removed;

View File

@ -132,6 +132,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
@ -5926,7 +5927,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
final Map<String, String> detailsStr = cmd.getDetails();
final Boolean egressDefaultPolicy = cmd.getEgressDefaultPolicy();
Boolean forVpc = cmd.getForVpc();
Boolean forNsx = cmd.isForNsx();
Boolean forTungsten = cmd.getForTungsten();
String nsxMode = cmd.getNsxMode();
Integer maxconn = null;
boolean enableKeepAlive = false;
String servicePackageuuid = cmd.getServicePackageId();
@ -5960,6 +5963,26 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
}
if (Boolean.TRUE.equals(forNsx) && Boolean.TRUE.equals(forTungsten)) {
throw new InvalidParameterValueException("Network Offering cannot be for both Tungsten-Fabric and NSX");
}
if (Boolean.TRUE.equals(forNsx)) {
if (Objects.isNull(nsxMode)) {
throw new InvalidParameterValueException("Mode for an NSX offering needs to be specified. Valid values: " + Arrays.toString(NetworkOffering.NsxMode.values()));
}
if (!EnumUtils.isValidEnum(NetworkOffering.NsxMode.class, nsxMode)) {
throw new InvalidParameterValueException("Invalid mode passed. Valid values: " + Arrays.toString(NetworkOffering.NsxMode.values()));
}
} else {
if (Objects.nonNull(nsxMode)) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("nsxMode has is ignored for non-NSX enabled zones");
}
nsxMode = null;
}
}
// Verify traffic type
for (final TrafficType tType : TrafficType.values()) {
if (tType.name().equalsIgnoreCase(trafficTypeString)) {
@ -6224,7 +6247,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
final NetworkOfferingVO offering = createNetworkOffering(name, displayText, trafficType, tags, specifyVlan, availability, networkRate, serviceProviderMap, false, guestType, false,
serviceOfferingId, conserveMode, serviceCapabilityMap, specifyIpRanges, isPersistent, details, egressDefaultPolicy, maxconn, enableKeepAlive, forVpc, forTungsten, false, domainIds, zoneIds, enable, internetProtocol);
serviceOfferingId, conserveMode, serviceCapabilityMap, specifyIpRanges, isPersistent, details, egressDefaultPolicy, maxconn, enableKeepAlive, forVpc, forTungsten, forNsx, nsxMode, domainIds, zoneIds, enable, internetProtocol);
CallContext.current().setEventDetails(" Id: " + offering.getId() + " Name: " + name);
CallContext.current().putContextParameter(NetworkOffering.class, offering.getId());
return offering;
@ -6369,7 +6392,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
final Long serviceOfferingId,
final boolean conserveMode, final Map<Service, Map<Capability, String>> serviceCapabilityMap, final boolean specifyIpRanges, final boolean isPersistent,
final Map<Detail, String> details, final boolean egressDefaultPolicy, final Integer maxconn, final boolean enableKeepAlive, Boolean forVpc,
Boolean forTungsten, Boolean forNsx, final List<Long> domainIds, final List<Long> zoneIds, final boolean enableOffering, final NetUtils.InternetProtocol internetProtocol) {
Boolean forTungsten, Boolean forNsx, String mode, final List<Long> domainIds, final List<Long> zoneIds, final boolean enableOffering, final NetUtils.InternetProtocol internetProtocol) {
String servicePackageUuid;
String spDescription = null;
@ -6595,7 +6618,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
s_logger.trace("Added service for the network offering: " + offService + " with provider " + provider.getName());
}
if (vpcOff) {
if (vpcOff && !forNsx) {
final List<Service> supportedSvcs = new ArrayList<Service>();
supportedSvcs.addAll(serviceProviderMap.keySet());
_vpcMgr.validateNtwkOffForVpc(offering, supportedSvcs);

View File

@ -23,10 +23,15 @@ import java.util.UUID;
import javax.inject.Inject;
import com.cloud.dc.DataCenter;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.backup.Backup;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
@ -86,6 +91,10 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
@Inject
protected AccountManager accountManager;
@Inject
private DomainDao domainDao;
@Inject
private DataCenterDao dcDao;
@Inject
private NetworkOfferingDetailsDao networkOfferingDetailsDao;
@Inject
protected
@ -160,11 +169,22 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
NetworkVO network = networkDao.findById(profile.getNetworkId());
to.setNetworkUuid(network.getUuid());
Account account = accountManager.getAccount(network.getAccountId());
Domain domain = domainDao.findById(network.getDomainId());
DataCenter zone = dcDao.findById(network.getDataCenterId());
if (Objects.isNull(zone)) {
throw new CloudRuntimeException(String.format("Failed to find zone with ID: %s", network.getDataCenterId()));
}
if (Objects.isNull(account)) {
throw new CloudRuntimeException(String.format("Failed to find account with ID: %s", network.getAccountId()));
}
if (Objects.isNull(domain)) {
throw new CloudRuntimeException(String.format("Failed to find domain with ID: %s", network.getDomainId()));
}
VpcVO vpc = null;
if (Objects.nonNull(network) && Objects.nonNull(network.getVpcId())) {
vpc = vpcDao.findById(network.getVpcId());
}
to.setNetworkSegmentName(getNetworkName(account.getAccountName(), vpc, network.getName()));
to.setNetworkSegmentName(getNetworkName(zone.getId(), domain.getId(), account.getId(), vpc, network.getId()));
// Workaround to make sure the TO has the UUID we need for Nicira integration
NicVO nicVO = nicDao.findById(profile.getId());
@ -193,11 +213,12 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
return to;
}
private String getNetworkName(String accountName, VpcVO vpc, String networkName) {
private String getNetworkName(long zoneId, long domainId, long accountId, VpcVO vpc, long networkId) {
String prefix = String.format("D%s-A%s-Z%s", domainId, accountId, zoneId);
if (Objects.isNull(vpc)) {
return accountName + "-" + networkName;
return prefix + "-S" + networkId;
}
return accountName + "-" + vpc.getName() + "-" + networkName;
return prefix + "-V" + vpc.getId() + "-S" + networkId;
}

View File

@ -104,6 +104,11 @@ public class ControlNetworkGuru extends PodBasedNetworkGuru implements NetworkGu
return config;
}
@Override
public void setup(Network network, long networkId) {
// do nothing
}
protected ControlNetworkGuru() {
super();
}

View File

@ -251,6 +251,11 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
return config;
}
@Override
public void setup(Network network, long networkId) {
// do nothing
}
protected DirectNetworkGuru() {
super();
_isolationMethods = new IsolationMethod[] { new IsolationMethod("VLAN"), new IsolationMethod("VXLAN") };

View File

@ -148,6 +148,11 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur
_isolationMethods = null;
}
@Override
public void setup(Network network, long networkId) {
// do nothing
}
private void updateNicIpv6(Network network, NicProfile nic, VirtualMachineProfile vm, DataCenter dc, boolean isGateway) throws InsufficientAddressCapacityException {
boolean isIpv6Supported = networkOfferingDao.isIpv6Supported(network.getNetworkOfferingId());
if (!isIpv6Supported || nic.getIPv6Address() != null || network.getIp6Cidr() == null || network.getIp6Gateway() == null) {

View File

@ -89,6 +89,11 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru {
return config;
}
@Override
public void setup(Network network, long networkId) {
// do nothing
}
protected PodBasedNetworkGuru() {
super();
}

View File

@ -137,6 +137,11 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
return network;
}
@Override
public void setup(Network network, long networkId) {
// do nothing
}
@Override
public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) {
if (s_logger.isDebugEnabled()) {

View File

@ -115,6 +115,11 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru {
}
}
@Override
public void setup(Network network, long networkId) {
// do nothing
}
protected PublicNetworkGuru() {
super();
}

View File

@ -62,6 +62,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.query.QueryService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.Nullable;
@ -325,7 +326,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
svcProviderMap.put(svc, defaultProviders);
}
}
createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap, true, State.Enabled, null, false, false, false);
createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap,
true, State.Enabled, null, false,
false, false, false, null);
}
// configure default vpc offering with Netscaler as LB Provider
@ -344,7 +347,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
svcProviderMap.put(svc, defaultProviders);
}
}
createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, svcProviderMap, false, State.Enabled, null, false, false, false);
createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, svcProviderMap, false, State.Enabled, null, false, false, false, false, null);
}
@ -364,12 +367,13 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
svcProviderMap.put(svc, defaultProviders);
}
}
createVpcOffering(VpcOffering.redundantVPCOfferingName, VpcOffering.redundantVPCOfferingName, svcProviderMap, true, State.Enabled, null, false, false, true);
createVpcOffering(VpcOffering.redundantVPCOfferingName, VpcOffering.redundantVPCOfferingName, svcProviderMap, true, State.Enabled,
null, false, false, true, false, null);
}
// configure default vpc offering with NSX as network service provider
if (_vpcOffDao.findByUniqueName(VpcOffering.DEFAULT_VPC_NSX_OFFERING_NAME) == null) {
s_logger.debug("Creating default VPC offering with NSX as network service provider" + VpcOffering.DEFAULT_VPC_NSX_OFFERING_NAME);
// configure default vpc offering with NSX as network service provider in NAT mode
if (_vpcOffDao.findByUniqueName(VpcOffering.DEFAULT_VPC_NAT_NSX_OFFERING_NAME) == null) {
s_logger.debug("Creating default VPC offering with NSX as network service provider" + VpcOffering.DEFAULT_VPC_NAT_NSX_OFFERING_NAME);
final Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
final Set<Provider> defaultProviders = Set.of(Provider.Nsx);
for (final Service svc : getSupportedServices()) {
@ -380,7 +384,26 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
svcProviderMap.put(svc, defaultProviders);
}
}
createVpcOffering(VpcOffering.DEFAULT_VPC_NSX_OFFERING_NAME, VpcOffering.DEFAULT_VPC_NSX_OFFERING_NAME, svcProviderMap, false, State.Enabled, null, false, false, false);
createVpcOffering(VpcOffering.DEFAULT_VPC_NAT_NSX_OFFERING_NAME, VpcOffering.DEFAULT_VPC_NAT_NSX_OFFERING_NAME, svcProviderMap, false,
State.Enabled, null, false, false, false, true, NetworkOffering.NsxMode.NATTED.name());
}
// configure default vpc offering with NSX as network service provider in Route mode
if (_vpcOffDao.findByUniqueName(VpcOffering.DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME) == null) {
s_logger.debug("Creating default VPC offering with NSX as network service provider" + VpcOffering.DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME);
final Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
final Set<Provider> defaultProviders = Set.of(Provider.Nsx);
for (final Service svc : getSupportedServices()) {
if (List.of(Service.UserData, Service.Dhcp, Service.Dns).contains(svc)) {
final Set<Provider> userDataProvider = Set.of(Provider.VPCVirtualRouter);
svcProviderMap.put(svc, userDataProvider);
} else {
svcProviderMap.put(svc, defaultProviders);
}
}
createVpcOffering(VpcOffering.DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME, VpcOffering.DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME, svcProviderMap, false,
State.Enabled, null, false, false, false, true, NetworkOffering.NsxMode.ROUTED.name());
}
}
@ -440,7 +463,25 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
final Long serviceOfferingId = cmd.getServiceOfferingId();
final List<Long> domainIds = cmd.getDomainIds();
final List<Long> zoneIds = cmd.getZoneIds();
final Boolean forNsx = cmd.isForNsx();
String nsxMode = cmd.getNsxMode();
final boolean enable = cmd.getEnable();
if (Boolean.TRUE.equals(forNsx)) {
if (Objects.isNull(nsxMode)) {
throw new InvalidParameterValueException("Mode for an NSX offering needs to be specified.Valid values: " + Arrays.toString(NetworkOffering.NsxMode.values()));
}
if (!EnumUtils.isValidEnum(NetworkOffering.NsxMode.class, nsxMode)) {
throw new InvalidParameterValueException("Invalid mode passed. Valid values: " + Arrays.toString(NetworkOffering.NsxMode.values()));
}
} else {
if (Objects.nonNull(nsxMode)) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("nsxMode has is ignored for non-NSX enabled zones");
}
nsxMode = null;
}
}
// check if valid domain
if (CollectionUtils.isNotEmpty(cmd.getDomainIds())) {
for (final Long domainId: cmd.getDomainIds()) {
@ -463,14 +504,15 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
}
return createVpcOffering(vpcOfferingName, displayText, supportedServices,
serviceProviderList, serviceCapabilityList, internetProtocol, serviceOfferingId,
serviceProviderList, serviceCapabilityList, internetProtocol, serviceOfferingId, forNsx, nsxMode,
domainIds, zoneIds, (enable ? State.Enabled : State.Disabled));
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_VPC_OFFERING_CREATE, eventDescription = "creating vpc offering", create = true)
public VpcOffering createVpcOffering(final String name, final String displayText, final List<String> supportedServices, final Map<String, List<String>> serviceProviders,
final Map serviceCapabilityList, final NetUtils.InternetProtocol internetProtocol, final Long serviceOfferingId, List<Long> domainIds, List<Long> zoneIds, State state) {
final Map serviceCapabilityList, final NetUtils.InternetProtocol internetProtocol, final Long serviceOfferingId,
final Boolean forNsx, final String mode, List<Long> domainIds, List<Long> zoneIds, State state) {
if (!Ipv6Service.Ipv6OfferingCreationEnabled.value() && !(internetProtocol == null || NetUtils.InternetProtocol.IPv4.equals(internetProtocol))) {
throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for creating IPv6 supported VPC offering", Ipv6Service.Ipv6OfferingCreationEnabled.key()));
@ -555,7 +597,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
final boolean offersRegionLevelVPC = isVpcOfferingForRegionLevelVpc(serviceCapabilityList);
final boolean redundantRouter = isVpcOfferingRedundantRouter(serviceCapabilityList);
final VpcOfferingVO offering = createVpcOffering(name, displayText, svcProviderMap, false, state, serviceOfferingId, supportsDistributedRouter, offersRegionLevelVPC,
redundantRouter);
redundantRouter, forNsx, mode);
if (offering != null) {
List<VpcOfferingDetailsVO> detailsVO = new ArrayList<>();
@ -583,7 +625,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
@DB
protected VpcOfferingVO createVpcOffering(final String name, final String displayText, final Map<Network.Service, Set<Network.Provider>> svcProviderMap,
final boolean isDefault, final State state, final Long serviceOfferingId, final boolean supportsDistributedRouter, final boolean offersRegionLevelVPC,
final boolean redundantRouter) {
final boolean redundantRouter, Boolean forNsx, String mode) {
return Transaction.execute(new TransactionCallback<VpcOfferingVO>() {
@Override
@ -594,6 +636,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
if (state != null) {
offering.setState(state);
}
offering.setForNsx(forNsx);
offering.setMode(mode);
s_logger.debug("Adding vpc offering " + offering);
offering = _vpcOffDao.persist(offering);
// populate services and providers

View File

@ -1206,17 +1206,34 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
}
_networkOfferingDao.persistDefaultL2NetworkOfferings();
// Offering #9 - network offering for nsx provider
NetworkOfferingVO defaultNSXNetworkOffering =
new NetworkOfferingVO(NetworkOffering.DEFAULT_NSX_OFFERING, "Offering for NSX enabled networks",
// Offering #9 - network offering for nsx provider - NATTED mode
NetworkOfferingVO defaultNatNSXNetworkOffering =
new NetworkOfferingVO(NetworkOffering.DEFAULT_NAT_NSX_OFFERING, "Offering for NSX enabled networks - NAT mode",
TrafficType.Guest, false, false, null, null, true, Availability.Optional, null, GuestType.Isolated, false, false, false, false, false, true);
defaultNSXNetworkOffering.setForNsx(true);
defaultNSXNetworkOffering.setState(NetworkOffering.State.Enabled);
defaultNSXNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNSXNetworkOffering);
defaultNatNSXNetworkOffering.setForNsx(true);
defaultNatNSXNetworkOffering.setNsxMode(NetworkOffering.NsxMode.NATTED.name());
defaultNatNSXNetworkOffering.setState(NetworkOffering.State.Enabled);
defaultNatNSXNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNatNSXNetworkOffering);
for (Map.Entry<Network.Service, Network.Provider> service : defaultNSXNetworkOfferingProviders.entrySet()) {
NetworkOfferingServiceMapVO offService =
new NetworkOfferingServiceMapVO(defaultNSXNetworkOffering.getId(), service.getKey(), service.getValue());
new NetworkOfferingServiceMapVO(defaultNatNSXNetworkOffering.getId(), service.getKey(), service.getValue());
_ntwkOfferingServiceMapDao.persist(offService);
s_logger.trace("Added service for the network offering: " + offService);
}
// Offering #10 - network offering for nsx provider - ROUTED mode
NetworkOfferingVO defaultRouteNSXNetworkOffering =
new NetworkOfferingVO(NetworkOffering.DEFAULT_NAT_NSX_OFFERING, "Offering for NSX enabled networks - NAT mode",
TrafficType.Guest, false, false, null, null, true, Availability.Optional, null, GuestType.Isolated, false, false, false, false, false, true);
defaultRouteNSXNetworkOffering.setForNsx(true);
defaultRouteNSXNetworkOffering.setNsxMode(NetworkOffering.NsxMode.ROUTED.name());
defaultRouteNSXNetworkOffering.setState(NetworkOffering.State.Enabled);
defaultRouteNSXNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultRouteNSXNetworkOffering);
for (Map.Entry<Network.Service, Network.Provider> service : defaultNSXNetworkOfferingProviders.entrySet()) {
NetworkOfferingServiceMapVO offService =
new NetworkOfferingServiceMapVO(defaultRouteNSXNetworkOffering.getId(), service.getKey(), service.getValue());
_ntwkOfferingServiceMapDao.persist(offService);
s_logger.trace("Added service for the network offering: " + offService);
}

View File

@ -546,7 +546,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
Integer networkRate, Map<Service, Set<Provider>> serviceProviderMap, boolean isDefault, GuestType type, boolean systemOnly, Long serviceOfferingId,
boolean conserveMode, Map<Service, Map<Capability, String>> serviceCapabilityMap, boolean specifyIpRanges, boolean isPersistent,
Map<NetworkOffering.Detail, String> details, boolean egressDefaultPolicy, Integer maxconn, boolean enableKeepAlive, Boolean forVpc,
Boolean forTungsten, Boolean forNsx, List<Long> domainIds, List<Long> zoneIds, boolean enableOffering, NetUtils.InternetProtocol internetProtocol) {
Boolean forTungsten, Boolean forNsx, String mode, List<Long> domainIds, List<Long> zoneIds, boolean enableOffering, NetUtils.InternetProtocol internetProtocol) {
// TODO Auto-generated method stub
return null;
}

View File

@ -129,7 +129,7 @@ public class CreateNetworkOfferingTest extends TestCase {
public void createSharedNtwkOffWithVlan() {
NetworkOfferingVO off =
configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest, null, true, Availability.Optional, 200, null, false, Network.GuestType.Shared, false,
null, false, null, true, false, null, false, null, true, false, false, false, null, null, false, null);
null, false, null, true, false, null, false, null, true, false, false, false, null,null, null, false, null);
assertNotNull("Shared network offering with specifyVlan=true failed to create ", off);
}
@ -137,7 +137,7 @@ public class CreateNetworkOfferingTest extends TestCase {
public void createSharedNtwkOffWithNoVlan() {
NetworkOfferingVO off =
configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest, null, false, Availability.Optional, 200, null, false, Network.GuestType.Shared,
false, null, false, null, true, false, null, false, null, true, false, false, false, null, null, false, null);
false, null, false, null, true, false, null, false, null, true, false, false, false, null, null,null, false, null);
assertNotNull("Shared network offering with specifyVlan=false was created", off);
}
@ -145,7 +145,7 @@ public class CreateNetworkOfferingTest extends TestCase {
public void createSharedNtwkOffWithSpecifyIpRanges() {
NetworkOfferingVO off =
configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest, null, true, Availability.Optional, 200, null, false, Network.GuestType.Shared, false,
null, false, null, true, false, null, false, null, true, false, false, false, null, null, false, null);
null, false, null, true, false, null, false, null, true, false, false, false, null,null, null, false, null);
assertNotNull("Shared network offering with specifyIpRanges=true failed to create ", off);
}
@ -154,7 +154,7 @@ public class CreateNetworkOfferingTest extends TestCase {
public void createSharedNtwkOffWithoutSpecifyIpRanges() {
NetworkOfferingVO off =
configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest, null, true, Availability.Optional, 200, null, false, Network.GuestType.Shared,
false, null, false, null, false, false, null, false, null, true, false, false, false, null, null, false, null);
false, null, false, null, false, false, null, false, null, true, false, false, false, null,null, null, false, null);
assertNull("Shared network offering with specifyIpRanges=false was created", off);
}
@ -167,7 +167,7 @@ public class CreateNetworkOfferingTest extends TestCase {
serviceProviderMap.put(Network.Service.SourceNat, vrProvider);
NetworkOfferingVO off =
configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, false, Availability.Optional, 200, serviceProviderMap, false,
Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, false, false, false, null, null, false, null);
Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, false, false, false, null, null, null, false, null);
assertNotNull("Isolated network offering with specifyIpRanges=false failed to create ", off);
}
@ -180,7 +180,7 @@ public class CreateNetworkOfferingTest extends TestCase {
serviceProviderMap.put(Network.Service.SourceNat, vrProvider);
NetworkOfferingVO off =
configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, true, Availability.Optional, 200, serviceProviderMap, false,
Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, false, false, false, null, null, false, null);
Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, false, false, false, null,null, null, false, null);
assertNotNull("Isolated network offering with specifyVlan=true wasn't created", off);
}
@ -193,7 +193,7 @@ public class CreateNetworkOfferingTest extends TestCase {
serviceProviderMap.put(Network.Service.SourceNat, vrProvider);
NetworkOfferingVO off =
configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, false, Availability.Optional, 200, serviceProviderMap, false,
Network.GuestType.Isolated, false, null, false, null, true, false, null, false, null, true, false, false, false, null, null, false, null);
Network.GuestType.Isolated, false, null, false, null, true, false, null, false, null, true, false, false, false, null,null, null, false, null);
assertNull("Isolated network offering with specifyIpRanges=true and source nat service enabled, was created", off);
}
@ -204,7 +204,7 @@ public class CreateNetworkOfferingTest extends TestCase {
Set<Network.Provider> vrProvider = new HashSet<Network.Provider>();
NetworkOfferingVO off =
configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, false, Availability.Optional, 200, serviceProviderMap, false,
Network.GuestType.Isolated, false, null, false, null, true, false, null, false, null, true, false, false, false, null, null, false, null);
Network.GuestType.Isolated, false, null, false, null, true, false, null, false, null, true, false, false, false, null,null, null, false, null);
assertNotNull("Isolated network offering with specifyIpRanges=true and with no sourceNatService, failed to create", off);
}
@ -222,7 +222,7 @@ public class CreateNetworkOfferingTest extends TestCase {
serviceProviderMap.put(Network.Service.Lb, vrProvider);
NetworkOfferingVO off =
configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, true, Availability.Optional, 200, serviceProviderMap, false,
Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, false, null);
Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, null, false, null);
// System.out.println("Creating Vpc Network Offering");
assertNotNull("Vpc Isolated network offering with Vpc provider ", off);
}
@ -242,7 +242,7 @@ public class CreateNetworkOfferingTest extends TestCase {
serviceProviderMap.put(Network.Service.Lb, lbProvider);
NetworkOfferingVO off =
configMgr.createNetworkOffering("isolated", "isolated", TrafficType.Guest, null, true, Availability.Optional, 200, serviceProviderMap, false,
Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, false, null);
Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true, true, false, false, null, null, null, false, null);
// System.out.println("Creating Vpc Network Offering");
assertNotNull("Vpc Isolated network offering with Vpc and Netscaler provider ", off);
}

View File

@ -876,6 +876,7 @@
"label.forceencap": "Force UDP encapsulation of ESP packets",
"label.forgedtransmits": "Forged transmits",
"label.format": "Format",
"label.fornsx": "NSX",
"label.free": "Free",
"label.french.azerty.keyboard": "French AZERTY keyboard",
"label.friday": "Friday",
@ -1289,6 +1290,7 @@
"label.minorsequence": "Minor Sequence",
"label.minsize": "Minimum size",
"label.minute.past.hour": "minute(s) past the hour",
"label.mode": "Mode",
"label.monday": "Monday",
"label.monitor": "Monitor",
"label.monitor.expected.code": "Expected HTTP Status Code",
@ -1383,6 +1385,8 @@
"label.not.found": "Not found",
"label.not.suitable": "Not suitable",
"label.notifications": "Notifications",
"label.nsx": "NSX",
"label.nsx.mode": "NSX Mode",
"label.nsx.provider": "NSX Provider",
"label.nsx.provider.name": "NSX provider name",
"label.nsx.provider.hostname": "NSX provider hostname",
@ -1561,6 +1565,7 @@
"label.public.ips": "Public IP addresses",
"label.public.lb": "Public LB",
"label.public.traffic": "Public traffic",
"label.public.traffic.nsx": "NSX Public traffic",
"label.publicinterface": "Public interface",
"label.publicip": "IP address",
"label.publicipid": "IP address ID",

View File

@ -21,6 +21,7 @@
<a-col :md="24" :lg="layout === 'horizontal' ? 10 : 24">
<a-checkbox
:checked="checked"
:disabled="forNsx"
@change="handleCheckChange">
{{ checkBoxLabel }}
</a-checkbox>
@ -30,7 +31,8 @@
v-if="reversed !== checked"
:label="selectLabel">
<a-select
v-model:value="selectedOption"
v-model:value="selected"
:disabled="forNsx"
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
@ -83,6 +85,10 @@ export default {
reversed: {
type: Boolean,
default: false
},
forNsx: {
type: Boolean,
default: false
}
},
data () {
@ -112,6 +118,15 @@ export default {
}
return option
})
},
selected () {
return this.option || this.selectedOption
},
option () {
if (this.forNsx) {
return this.selectOptions[0]?.name || null
}
return null
}
},
methods: {

View File

@ -38,7 +38,7 @@
<br/>
<div v-if="Array.isArray(dataResource[item]) && item === 'service'">
<div v-for="(service, idx) in dataResource[item]" :key="idx">
{{ service.name }} : {{ service.provider[0].name }}
{{ service.name }} : {{ service.provider?.[0]?.name }}
</div>
</div>
<div v-else-if="$route.meta.name === 'backup' && item === 'volumes'">

View File

@ -262,7 +262,7 @@ export default {
docHelp: 'adminguide/networking.html#network-offerings',
permission: ['listNetworkOfferings'],
columns: ['name', 'state', 'guestiptype', 'traffictype', 'networkrate', 'domain', 'zone', 'order'],
details: ['name', 'id', 'displaytext', 'guestiptype', 'traffictype', 'internetprotocol', 'networkrate', 'ispersistent', 'egressdefaultpolicy', 'availability', 'conservemode', 'specifyvlan', 'specifyipranges', 'supportspublicaccess', 'supportsstrechedl2subnet', 'service', 'tags', 'domain', 'zone'],
details: ['name', 'id', 'displaytext', 'guestiptype', 'traffictype', 'internetprotocol', 'networkrate', 'ispersistent', 'egressdefaultpolicy', 'availability', 'conservemode', 'specifyvlan', 'specifyipranges', 'supportspublicaccess', 'supportsstrechedl2subnet', 'forvpc', 'fornsx', 'nsxmode', 'service', 'tags', 'domain', 'zone'],
resourceType: 'NetworkOffering',
tabs: [
{
@ -355,7 +355,7 @@ export default {
permission: ['listVPCOfferings'],
resourceType: 'VpcOffering',
columns: ['name', 'state', 'displaytext', 'domain', 'zone', 'order'],
details: ['name', 'id', 'displaytext', 'internetprotocol', 'distributedvpcrouter', 'tags', 'service', 'domain', 'zone', 'created'],
details: ['name', 'id', 'displaytext', 'internetprotocol', 'distributedvpcrouter', 'tags', 'service', 'fornsx', 'nsxmode', 'domain', 'zone', 'created'],
related: [{
name: 'vpc',
title: 'label.vpc',

View File

@ -41,7 +41,7 @@
v-model:value="form.displaytext"
:placeholder="apiParams.displaytext.description"/>
</a-form-item>
<a-form-item name="networkrate" ref="networkrate">
<a-form-item name="networkrate" ref="networkrate" v-if="!forNsx">
<template #label>
<tooltip-label :title="$t('label.networkrate')" :tooltip="apiParams.networkrate.description"/>
</template>
@ -60,10 +60,10 @@
<a-radio-button value="isolated">
{{ $t('label.isolated') }}
</a-radio-button>
<a-radio-button value="l2">
<a-radio-button value="l2" v-if="!forNsx">
{{ $t('label.l2') }}
</a-radio-button>
<a-radio-button value="shared">
<a-radio-button value="shared" v-if="!forNsx">
{{ $t('label.shared') }}
</a-radio-button>
</a-radio-group>
@ -93,7 +93,7 @@
</a-radio-button>
</a-radio-group>
</a-form-item>
<a-row :gutter="12">
<a-row :gutter="12" v-if="!forNsx">
<a-col :md="12" :lg="12">
<a-form-item name="specifyvlan" ref="specifyvlan">
<template #label>
@ -111,18 +111,47 @@
</a-form-item>
</a-col>
</a-row>
<a-form-item name="forvpc" ref="forvpc" v-if="guestType === 'isolated'">
<a-row :gutter="12">
<a-col :md="12" :lg="12">
<a-form-item name="forvpc" ref="forvpc" v-if="guestType === 'isolated'">
<template #label>
<tooltip-label :title="$t('label.vpc')" :tooltip="apiParams.forvpc.description"/>
</template>
<a-switch v-model:checked="form.forvpc" @change="val => { handleForVpcChange(val) }" />
</a-form-item>
</a-col>
<a-col :md="12" :lg="12">
<a-form-item name="fornsx" ref="fornsx" v-if="guestType === 'isolated'">
<template #label>
<tooltip-label :title="$t('label.nsx')" :tooltip="apiParams.fornsx.description"/>
</template>
<a-switch v-model:checked="form.fornsx" @change="val => { handleForNsxChange(val) }" />
</a-form-item>
</a-col>
</a-row>
<a-form-item name="nsxmode" ref="nsxmode" v-if="forNsx">
<template #label>
<tooltip-label :title="$t('label.vpc')" :tooltip="apiParams.forvpc.description"/>
<tooltip-label :title="$t('label.nsx.mode')" :tooltip="apiParams.nsxmode.description"/>
</template>
<a-switch v-model:checked="form.forvpc" @change="val => { handleForVpcChange(val) }" />
<a-select
v-if="showMode"
optionFilterProp="label"
v-model:value="form.nsxmode"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:placeholder="apiParams.nsxmode.description">
<a-select-option v-for="(opt) in modes" :key="opt.name" :label="opt.name">
{{ opt.name }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item name="userdatal2" ref="userdatal2" :label="$t('label.userdatal2')" v-if="guestType === 'l2'">
<a-switch v-model:checked="form.userdatal2" />
</a-form-item>
<a-row :gutter="12">
<a-col :md="12" :lg="12">
<a-form-item name="promiscuousmode" ref="promiscuousmode">
<a-form-item name="promiscuousmode" ref="promiscuousmode" v-if="!forNsx">
<template #label>
<tooltip-label :title="$t('label.promiscuousmode')" :tooltip="$t('message.network.offering.promiscuous.mode')"/>
</template>
@ -140,7 +169,7 @@
</a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item name="macaddresschanges" ref="macaddresschanges">
<a-form-item name="macaddresschanges" ref="macaddresschanges" v-if="!forNsx">
<template #label>
<tooltip-label :title="$t('label.macaddresschanges')" :tooltip="$t('message.network.offering.mac.address.changes')"/>
</template>
@ -160,7 +189,7 @@
</a-form-item>
</a-col>
<a-col :md="12" :lg="12">
<a-form-item name="forgedtransmits" ref="forgedtransmits">
<a-form-item name="forgedtransmits" ref="forgedtransmits" v-if="!forNsx">
<template #label>
<tooltip-label :title="$t('label.forgedtransmits')" :tooltip="$t('message.network.offering.forged.transmits')"/>
</template>
@ -178,7 +207,7 @@
</a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item name="maclearning" ref="maclearning">
<a-form-item name="maclearning" ref="maclearning" v-if="!forNsx">
<template #label>
<tooltip-label :title="$t('label.maclearning')" :tooltip="$t('message.network.offering.mac.learning')"/>
</template>
@ -217,6 +246,8 @@
<CheckBoxSelectPair
:resourceKey="item.name"
:checkBoxLabel="item.description"
:forNsx="forNsx"
:defaultCheckBoxValue="forNsx"
:selectOptions="!supportedServiceLoading ? item.provider: []"
@handle-checkselectpair-change="handleSupportedServiceChange"/>
</a-list-item>
@ -377,7 +408,7 @@
<a-form-item
name="conservemode"
ref="conservemode"
v-if="(guestType === 'shared' || guestType === 'isolated') && !isVpcVirtualRouterForAtLeastOneService">
v-if="(guestType === 'shared' || guestType === 'isolated') && !isVpcVirtualRouterForAtLeastOneService && !forNsx">
<template #label>
<tooltip-label :title="$t('label.conservemode')" :tooltip="apiParams.conservemode.description"/>
</template>
@ -512,6 +543,8 @@ export default {
selectedDomains: [],
selectedZones: [],
forVpc: false,
forNsx: false,
showMode: false,
lbType: 'publicLb',
macLearningValue: '',
supportedServices: [],
@ -538,7 +571,33 @@ export default {
zones: [],
zoneLoading: false,
ipv6NetworkOfferingEnabled: false,
loading: false
loading: false,
modes: [
{
id: 0,
name: 'NATTED'
},
{
id: 1,
name: 'ROUTED'
}
],
VPCVR: {
name: 'VPCVirtualRouter',
description: 'VPCVirtualRouter',
enabled: true
},
VR: {
name: 'VirtualRouter',
description: 'VirtualRouter',
enabled: true
},
NSX: {
name: 'Nsx',
description: 'Nsx',
enabled: true
},
nsxSupportedServicesMap: {}
}
},
beforeCreate () {
@ -761,34 +820,65 @@ export default {
this.supportedServiceLoading = true
var supportedServices = this.supportedServices
var self = this
supportedServices.forEach(function (svc, index) {
if (svc.name !== 'Connectivity') {
var providers = svc.provider
providers.forEach(function (provider, providerIndex) {
if (self.forVpc) { // *** vpc ***
var enabledProviders = ['VpcVirtualRouter', 'Netscaler', 'BigSwitchBcf', 'ConfigDrive']
if (self.lbType === 'internalLb') {
enabledProviders.push('InternalLbVm')
if (!this.forNsx) {
supportedServices.forEach(function (svc, index) {
if (svc.name !== 'Connectivity') {
var providers = svc.provider
providers.forEach(function (provider, providerIndex) {
if (self.forVpc) { // *** vpc ***
var enabledProviders = ['VpcVirtualRouter', 'Netscaler', 'BigSwitchBcf', 'ConfigDrive']
if (self.lbType === 'internalLb') {
enabledProviders.push('InternalLbVm')
}
provider.enabled = enabledProviders.includes(provider.name)
} else { // *** non-vpc ***
provider.enabled = !['InternalLbVm', 'VpcVirtualRouter', 'Nsx'].includes(provider.name)
}
provider.enabled = enabledProviders.includes(provider.name)
} else { // *** non-vpc ***
provider.enabled = !['InternalLbVm', 'VpcVirtualRouter'].includes(provider.name)
}
providers[providerIndex] = provider
})
svc.provider = providers
providers[providerIndex] = provider
})
svc.provider = providers
supportedServices[index] = svc
}
})
setTimeout(() => {
self.supportedServices = supportedServices
self.supportedServiceLoading = false
}, 50)
} else {
supportedServices = supportedServices.filter(svc => {
return Object.keys(this.nsxSupportedServicesMap).includes(svc.name)
})
supportedServices.forEach(function (svc, index) {
svc.provider = [self.nsxSupportedServicesMap[svc.name]]
supportedServices[index] = svc
}
})
setTimeout(() => {
})
self.supportedServices = supportedServices
self.supportedServiceLoading = false
}, 50)
}
},
handleForVpcChange (forVpc) {
this.forVpc = forVpc
if (this.forNsx) {
this.nsxSupportedServicesMap = {
Dhcp: this.forVpc ? this.VPCVR : this.VR,
Dns: this.forVpc ? this.VPCVR : this.VR,
UserData: this.forVpc ? this.VPCVR : this.VR,
SourceNat: this.NSX
}
}
this.updateSupportedServices()
},
async handleForNsxChange (forNsx) {
this.forNsx = forNsx
this.showMode = forNsx
this.nsxSupportedServicesMap = {
Dhcp: this.forVpc ? this.VPCVR : this.VR,
Dns: this.forVpc ? this.VPCVR : this.VR,
UserData: this.forVpc ? this.VPCVR : this.VR,
SourceNat: this.NSX
}
this.fetchSupportedServiceData()
},
handleLbTypeChange (lbType) {
this.lbType = lbType
this.updateSupportedServices()
@ -895,6 +985,10 @@ export default {
if (values.forvpc === true) {
params.forvpc = true
}
if (values.fornsx === true) {
params.fornsx = true
params.nsxmode = values.nsxmode
}
if (values.guestiptype === 'shared' || values.guestiptype === 'isolated') {
if (values.conservemode !== true) {
params.conservemode = false

View File

@ -67,6 +67,33 @@
</a-radio-button>
</a-radio-group>
</a-form-item>
<a-row :gutter="12">
<a-col :md="12" :lg="12">
<a-form-item name="fornsx" ref="fornsx">
<template #label>
<tooltip-label :title="$t('label.nsx')" :tooltip="apiParams.fornsx.description"/>
</template>
<a-switch v-model:checked="form.fornsx" @change="val => { handleForNsxChange(val) }" />
</a-form-item>
</a-col>
</a-row>
<a-form-item name="nsxmode" ref="nsxmode" v-if="forNsx">
<template #label>
<tooltip-label :title="$t('label.nsx.mode')" :tooltip="apiParams.nsxmode.description"/>
</template>
<a-select
v-if="showMode"
optionFilterProp="label"
v-model:value="form.nsxmode"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:placeholder="apiParams.nsxmode.description">
<a-select-option v-for="(opt) in modes" :key="opt.name" :label="opt.name">
{{ opt.name }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item>
<template #label>
<tooltip-label :title="$t('label.supportedservices')" :tooltip="apiParams.supportedservices.description"/>
@ -78,6 +105,8 @@
<CheckBoxSelectPair
:resourceKey="item.name"
:checkBoxLabel="item.description"
:forNsx="forNsx"
:defaultCheckBoxValue="forNsx"
:selectOptions="item.provider"
@handle-checkselectpair-change="handleSupportedServiceChange"/>
</a-list-item>
@ -209,6 +238,8 @@ export default {
domainLoading: false,
zones: [],
zoneLoading: false,
forNsx: false,
showMode: false,
loading: false,
supportedServices: [],
supportedServiceLoading: false,
@ -218,7 +249,28 @@ export default {
connectivityServiceChecked: false,
sourceNatServiceChecked: false,
selectedServiceProviderMap: {},
ipv6NetworkOfferingEnabled: false
ipv6NetworkOfferingEnabled: false,
modes: [
{
id: 0,
name: 'NATTED'
},
{
id: 1,
name: 'ROUTED'
}
],
VPCVR: {
name: 'VPCVirtualRouter',
description: 'VPCVirtualRouter',
enabled: true
},
NSX: {
name: 'Nsx',
description: 'Nsx',
enabled: true
},
nsxSupportedServicesMap: {}
}
},
beforeCreate () {
@ -299,85 +351,138 @@ export default {
})
},
fetchSupportedServiceData () {
this.supportedServices = []
this.supportedServices.push({
name: 'Dhcp',
provider: [
{ name: 'VpcVirtualRouter' }
]
})
this.supportedServices.push({
name: 'Dns',
provider: [{ name: 'VpcVirtualRouter' }]
})
this.supportedServices.push({
name: 'Lb',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'InternalLbVm' }
]
})
this.supportedServices.push({
name: 'Gateway',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'BigSwitchBcf' }
]
})
this.supportedServices.push({
name: 'StaticNat',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'BigSwitchBcf' }
]
})
this.supportedServices.push({
name: 'SourceNat',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'BigSwitchBcf' }
]
})
this.supportedServices.push({
name: 'NetworkACL',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'BigSwitchBcf' }
]
})
this.supportedServices.push({
name: 'PortForwarding',
provider: [{ name: 'VpcVirtualRouter' }]
})
this.supportedServices.push({
name: 'UserData',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'ConfigDrive' }
]
})
this.supportedServices.push({
name: 'Vpn',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'BigSwitchBcf' }
]
})
this.supportedServices.push({
name: 'Connectivity',
provider: [
{ name: 'BigSwitchBcf' },
{ name: 'NiciraNvp' },
{ name: 'Ovs' },
{ name: 'JuniperContrailVpcRouter' }
]
})
for (var i in this.supportedServices) {
var serviceName = this.supportedServices[i].name
var serviceDisplayName = serviceName
// Sanitize names
this.supportedServices[i].description = serviceDisplayName
var services = []
if (this.forNsx) {
services.push({
name: 'Dhcp',
enabled: true,
provider: [
{ name: 'VpcVirtualRouter' }
]
})
services.push({
name: 'Dns',
enabled: true,
provider: [{ name: 'VpcVirtualRouter' }]
})
services.push({
name: 'Lb',
enabled: true,
provider: [{ name: 'Nsx' }]
})
services.push({
name: 'StaticNat',
enabled: true,
provider: [{ name: 'Nsx' }]
})
services.push({
name: 'SourceNat',
enabled: true,
provider: [{ name: 'Nsx' }]
})
services.push({
name: 'NetworkACL',
enabled: true,
provider: [{ name: 'Nsx' }]
})
services.push({
name: 'PortForwarding',
enabled: true,
provider: [{ name: 'Nsx' }]
})
services.push({
name: 'UserData',
enabled: true,
provider: [{ name: 'VpcVirtualRouter' }]
})
} else {
services.push({
name: 'Dhcp',
provider: [
{ name: 'VpcVirtualRouter' }
]
})
services.push({
name: 'Dns',
provider: [{ name: 'VpcVirtualRouter' }]
})
services.push({
name: 'Lb',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'InternalLbVm' }
]
})
services.push({
name: 'Gateway',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'BigSwitchBcf' }
]
})
services.push({
name: 'StaticNat',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'BigSwitchBcf' }
]
})
services.push({
name: 'SourceNat',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'BigSwitchBcf' }
]
})
services.push({
name: 'NetworkACL',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'BigSwitchBcf' }
]
})
services.push({
name: 'PortForwarding',
provider: [{ name: 'VpcVirtualRouter' }]
})
services.push({
name: 'UserData',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'ConfigDrive' }
]
})
services.push({
name: 'Vpn',
provider: [
{ name: 'VpcVirtualRouter' },
{ name: 'BigSwitchBcf' }
]
})
services.push({
name: 'Connectivity',
provider: [
{ name: 'BigSwitchBcf' },
{ name: 'NiciraNvp' },
{ name: 'Ovs' },
{ name: 'JuniperContrailVpcRouter' }
]
})
}
this.supportedServices = []
for (var i in services) {
services[i].description = services[i].name
}
var self = this
setTimeout(() => {
self.supportedServices = services
self.supportedServiceLoading = false
}, 50)
},
async handleForNsxChange (forNsx) {
this.forNsx = forNsx
this.showMode = forNsx
this.fetchSupportedServiceData()
},
handleSupportedServiceChange (service, checked, provider) {
if (service === 'Connectivity') {
@ -453,9 +558,16 @@ export default {
if (values.internetprotocol) {
params.internetprotocol = values.internetprotocol
}
if (values.fornsx === true) {
params.fornsx = true
params.nsxmode = values.nsxmode
}
if (this.selectedServiceProviderMap != null) {
var supportedServices = Object.keys(this.selectedServiceProviderMap)
params.supportedservices = supportedServices.join(',')
params.supportedservices = []
if (!this.forNsx) {
params.supportedservices = supportedServices.join(',')
}
for (var k in supportedServices) {
params['serviceProviderList[' + k + '].service'] = supportedServices[k]
params['serviceProviderList[' + k + '].provider'] = this.selectedServiceProviderMap[supportedServices[k]]
@ -485,7 +597,7 @@ export default {
params.serviceofferingid = values.serviceofferingid
}
} else {
params.supportedservices = ''
params.supportedservices = []
}
if (values.enable) {
params.enable = values.enable

View File

@ -21,14 +21,24 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cloud.hypervisor.vmware.util.VmwareClient;
import com.cloud.network.Networks;
import com.cloud.utils.Pair;
import com.vmware.vim25.DynamicProperty;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.ObjectContent;
import com.vmware.vim25.VimPortType;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@ -61,6 +71,10 @@ public class HypervisorHostHelperTest {
@Mock
VmwareContext context;
@Mock
ManagedObjectReference mor;
@Mock
VmwareClient vmwareClient;
@Mock
DVPortgroupConfigInfo currentDvPortgroupInfo;
@Mock
DVPortgroupConfigSpec dvPortgroupConfigSpec;
@ -78,6 +92,12 @@ public class HypervisorHostHelperTest {
private ClusterConfigInfoEx clusterConfigInfo;
@Mock
private DatacenterConfigInfo datacenterConfigInfo;
@Mock
HostMO hostMO;
@Mock
VimPortType vimService;
@Mock
ObjectContent ocs;
String vSwitchName;
Integer networkRateMbps;
@ -90,6 +110,10 @@ public class HypervisorHostHelperTest {
@Before
public void setup() throws Exception {
closeable = MockitoAnnotations.openMocks(this);
ObjectContent oc = new ObjectContent();
when(hostMO.getContext()).thenReturn(context);
when(context.getService()).thenReturn(vimService);
when(context.getVimClient()).thenReturn(vmwareClient);
when(context.getServiceContent()).thenReturn(serviceContent);
when(serviceContent.getAbout()).thenReturn(aboutInfo);
when(clusterMO.getClusterConfigInfo()).thenReturn(clusterConfigInfo);
@ -947,4 +971,24 @@ public class HypervisorHostHelperTest {
HypervisorHostHelper.setVMHardwareVersion(vmSpec, clusterMO, datacenterMO);
verify(vmSpec, never()).setVersion(any());
}
@Test
public void testPrepareNetwork() throws Exception {
String networkName = "D1-A2-Z2-V8-S3";
DynamicProperty property = new DynamicProperty();
property.setVal(networkName);
when(hostMO.getHyperHostDatacenter()).thenReturn(mor);
when(datacenterMO.getDvSwitchMor(any(String.class))).thenReturn(mor);
when(vmwareClient.getDecendentMoRef(nullable(ManagedObjectReference.class), any(String.class), any(String.class))).thenReturn(mor);
when(vimService.retrieveProperties(any(), anyList())).thenReturn(List.of(ocs));
when(ocs.getPropSet()).thenReturn(List.of(property));
when(ocs.getObj()).thenReturn(mor);
Pair<ManagedObjectReference, String> morNet = HypervisorHostHelper.prepareNetwork("NSX-VDS", "cloud.guest", hostMO, null, null,
200, null, 900000, VirtualSwitchType.VMwareDistributedVirtualSwitch, 1, null,
false, Networks.BroadcastDomainType.NSX, null,
null, networkName);
assertEquals(morNet.second(), networkName);
}
}