mirror of https://github.com/apache/cloudstack.git
Support adding netris provider to CloudStack and Netris VPC Creation (#6)
* Support adding netris provider to CloudStack * revert marvin change * add license and perform session check when provider is added * add license and remove unused import * fix build failure - uunused imports * address comments * fix provider name * add Netris network element * add license * Add netris management APIs and netris service provider * add license * revert change * remove other network elements from Netris element * fix api name in doc generator * remove logs * move session alive check to CheckHealthCommand exec * Fix zone creation wizard to configure netris provider * Upgrade GSON version - from PR 8756 * Add additional parametes to the add Netris provider API * add netris as a host * add additional params to the resoponse and update UI * Rename site to site_name * Create Netris VPC (#8) * Delegate API classes creation to the SDK and simply invoke the desired API class through CloudStack (#7) * Delegate API classes creation to the SDK and simply invoke the desired API class through CloudStack * Pass default auth scheme for now * Drop for_nsx and for_tungten columns in favour of checking the provider on the ntwserviceprovider map table * Remove missing setForTungsten occurrence * Remove forNsx from VPC offerings * Create Netris VPC * Fix VPC offerings listing and remove unused dao * Create VPC fixes * Upgrade GSON version - from PR 8756 * Fix VPC creation response by using the latest SDK code * Fix unit test * Remove unused import * Fix NSX unit tests after refactoring * Add Netris key to the VLAN Details table (#10) * Add Netris key to the VLAN Details table * update for_<provider> column to be generic * Fix VPC and add IPAM allocation for the VPC CIDR (#9) * Fix VPC and add IPAM allocation for the VPC CIDR * Remove VPC logic * Use zoneId accountId and domainId on resources creation * Fix naming * Fix VR public nic issue * Fix Netris Public IP for VPC source NAT allocation * Add Netris VPC Subnets and vNets (#11) * Add Netris VPC Subnets and vNets * fix compilation errors * Add netris subnet * refactor naming convention to differentiate between VPC tiers and Isolated networks * revert marvin change * fix constructor - build failure * Add support to filter netris offerings, delete netris provider when zone is being deleted * Fix build * Fix VPC creation * Fix vnet creation * unnecesary log --------- Co-authored-by: nvazquez <nicovazquez90@gmail.com> --------- Co-authored-by: Pearl Dsilva <pearl1594@gmail.com> --------- Co-authored-by: nvazquez <nicovazquez90@gmail.com>
This commit is contained in:
parent
9f76e377d4
commit
bfb017426d
|
|
@ -17,7 +17,11 @@
|
|||
package com.cloud.configuration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.cloud.network.Network;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd;
|
||||
import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.CreateGuestNetworkIpv6PrefixCmd;
|
||||
|
|
@ -372,4 +376,16 @@ public interface ConfigurationService {
|
|||
List<? extends PortableIp> listPortableIps(long id);
|
||||
|
||||
Boolean isAccountAllowedToCreateOfferingsWithTags(IsAccountAllowedToCreateOfferingsWithTagsCmd cmd);
|
||||
|
||||
public static final Map<String, String> ProviderDetailKeyMap = Map.of(
|
||||
Network.Provider.Nsx.getName(), ApiConstants.NSX_DETAIL_KEY,
|
||||
Network.Provider.Netris.getName(), ApiConstants.NETRIS_DETAIL_KEY
|
||||
);
|
||||
|
||||
public static boolean IsIpRangeForProvider(Network.Provider provider) {
|
||||
if (Objects.isNull(provider)) {
|
||||
return false;
|
||||
}
|
||||
return ProviderDetailKeyMap.containsKey(provider.getName());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,7 +129,8 @@ public class Networks {
|
|||
UnDecided(null, null),
|
||||
OpenDaylight("opendaylight", String.class),
|
||||
TUNGSTEN("tf", String.class),
|
||||
NSX("nsx", String.class);
|
||||
NSX("nsx", String.class),
|
||||
Netris("netris", String.class);
|
||||
|
||||
private final String scheme;
|
||||
private final Class<?> type;
|
||||
|
|
|
|||
|
|
@ -25,4 +25,6 @@ public interface NetrisProvider extends InternalIdentity, Identity {
|
|||
String getHostname();
|
||||
String getPort();
|
||||
String getUsername();
|
||||
String getSiteName();
|
||||
String getTenantName();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
// 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 com.cloud.network.netris;
|
||||
|
||||
import com.cloud.network.vpc.Vpc;
|
||||
|
||||
public interface NetrisService {
|
||||
boolean createVpcResource(long zoneId, long accountId, long domainId, Long vpcId, String vpcName, boolean sourceNatEnabled, String cidr, boolean isVpcNetwork);
|
||||
boolean deleteVpcResource(long zoneId, long accountId, long domainId, Vpc vpc);
|
||||
boolean createVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr);
|
||||
}
|
||||
|
|
@ -57,8 +57,6 @@ public interface VpcOffering extends InternalIdentity, Identity {
|
|||
*/
|
||||
boolean isDefault();
|
||||
|
||||
boolean isForNsx();
|
||||
|
||||
NetworkOffering.NetworkMode getNetworkMode();
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -103,10 +103,6 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
|
|||
|
||||
boolean isForVpc();
|
||||
|
||||
boolean isForTungsten();
|
||||
|
||||
boolean isForNsx();
|
||||
|
||||
NetworkMode getNetworkMode();
|
||||
|
||||
TrafficType getTrafficType();
|
||||
|
|
|
|||
|
|
@ -325,6 +325,8 @@ public class ApiConstants {
|
|||
public static final String MIN_CPU_NUMBER = "mincpunumber";
|
||||
public static final String MIN_MEMORY = "minmemory";
|
||||
public static final String MIGRATION_TYPE = "migrationtype";
|
||||
public static final String MIGRATION_JOB_ID = "migrationjobid";
|
||||
public static final String MIGRATION_JOB_STATUS = "migrationjobstatus";
|
||||
public static final String MIGRATIONS = "migrations";
|
||||
public static final String MEMORY = "memory";
|
||||
public static final String MODE = "mode";
|
||||
|
|
@ -448,6 +450,7 @@ public class ApiConstants {
|
|||
public static final String SIGNATURE = "signature";
|
||||
public static final String SIGNATURE_VERSION = "signatureversion";
|
||||
public static final String SINCE = "since";
|
||||
public static final String SITE_NAME = "sitename";
|
||||
public static final String SIZE = "size";
|
||||
public static final String SIZEGB = "sizegb";
|
||||
public static final String SNAPSHOT = "snapshot";
|
||||
|
|
@ -490,6 +493,7 @@ public class ApiConstants {
|
|||
public static final String TIMEOUT = "timeout";
|
||||
public static final String TIMEZONE = "timezone";
|
||||
public static final String TIMEZONEOFFSET = "timezoneoffset";
|
||||
public static final String TENANT_NAME = "tenantname";
|
||||
public static final String TOTAL = "total";
|
||||
public static final String TOTAL_SUBNETS = "totalsubnets";
|
||||
public static final String TYPE = "type";
|
||||
|
|
@ -1143,6 +1147,7 @@ public class ApiConstants {
|
|||
public static final String SOURCE_NAT_IP_ID = "sourcenatipaddressid";
|
||||
public static final String HAS_RULES = "hasrules";
|
||||
public static final String NSX_DETAIL_KEY = "forNsx";
|
||||
public static final String NETRIS_DETAIL_KEY = "forNetris";
|
||||
public static final String DISK_PATH = "diskpath";
|
||||
public static final String IMPORT_SOURCE = "importsource";
|
||||
public static final String TEMP_PATH = "temppath";
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.admin.vlan;
|
||||
|
||||
import com.cloud.configuration.ConfigurationService;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
|
|
@ -39,7 +41,6 @@ import com.cloud.exception.ResourceAllocationException;
|
|||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@APICommand(name = "createVlanIpRange", description = "Creates a VLAN IP range.", responseObject = VlanIpRangeResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
|
|
@ -114,8 +115,8 @@ public class CreateVlanIpRangeCmd extends BaseCmd {
|
|||
@Parameter(name = ApiConstants.FOR_SYSTEM_VMS, type = CommandType.BOOLEAN, description = "true if IP range is set to system vms, false if not")
|
||||
private Boolean forSystemVms;
|
||||
|
||||
@Parameter(name = ApiConstants.FOR_NSX, type = CommandType.BOOLEAN, description = "true if the IP range is used for NSX resource", since = "4.20.0")
|
||||
private boolean forNsx;
|
||||
@Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, description = "Provider name for which the IP range is reserved for", since = "4.20.0")
|
||||
private String provider;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
|
|
@ -157,12 +158,12 @@ public class CreateVlanIpRangeCmd extends BaseCmd {
|
|||
return startIp;
|
||||
}
|
||||
|
||||
public boolean isForNsx() {
|
||||
return !Objects.isNull(forNsx) && forNsx;
|
||||
public Network.Provider getProvider() {
|
||||
return Network.Provider.getProvider(provider);
|
||||
}
|
||||
|
||||
public String getVlan() {
|
||||
if ((vlan == null || vlan.isEmpty()) && !isForNsx()) {
|
||||
if ((vlan == null || vlan.isEmpty()) && !ConfigurationService.IsIpRangeForProvider(getProvider())) {
|
||||
vlan = "untagged";
|
||||
}
|
||||
return vlan;
|
||||
|
|
|
|||
|
|
@ -55,10 +55,6 @@ public class AsyncJobResponse extends BaseResponse {
|
|||
@Param(description = "the async command executed")
|
||||
private String cmd;
|
||||
|
||||
@SerializedName("jobstatus")
|
||||
@Param(description = "the current job status-should be 0 for PENDING")
|
||||
private Integer jobStatus;
|
||||
|
||||
@SerializedName("jobprocstatus")
|
||||
@Param(description = "the progress information of the PENDING job")
|
||||
private Integer jobProcStatus;
|
||||
|
|
@ -119,11 +115,6 @@ public class AsyncJobResponse extends BaseResponse {
|
|||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJobStatus(Integer jobStatus) {
|
||||
this.jobStatus = jobStatus;
|
||||
}
|
||||
|
||||
public void setJobProcStatus(Integer jobProcStatus) {
|
||||
this.jobProcStatus = jobProcStatus;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,13 +50,13 @@ public class ClusterDrsPlanMigrationResponse extends BaseResponse {
|
|||
@Param(description = "Destination host for VM migration")
|
||||
String destHostName;
|
||||
|
||||
@SerializedName(ApiConstants.JOB_ID)
|
||||
@SerializedName(ApiConstants.MIGRATION_JOB_ID)
|
||||
@Param(description = "id of VM migration async job")
|
||||
private Long jobId;
|
||||
private Long migrationJobId;
|
||||
|
||||
@SerializedName(ApiConstants.JOB_STATUS)
|
||||
@SerializedName(ApiConstants.MIGRATION_JOB_STATUS)
|
||||
@Param(description = "Job status of VM migration async job")
|
||||
private JobInfo.Status jobStatus;
|
||||
private JobInfo.Status migrationJobStatus;
|
||||
|
||||
|
||||
public ClusterDrsPlanMigrationResponse(String vmId, String vmName, String srcHostId, String srcHostName,
|
||||
|
|
@ -68,8 +68,8 @@ public class ClusterDrsPlanMigrationResponse extends BaseResponse {
|
|||
this.srcHostName = srcHostName;
|
||||
this.destHostId = destHostId;
|
||||
this.destHostName = destHostName;
|
||||
this.jobId = jobId;
|
||||
this.jobStatus = jobStatus;
|
||||
this.migrationJobId = jobId;
|
||||
this.migrationJobStatus = jobStatus;
|
||||
this.setObjectName(ApiConstants.MIGRATIONS);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,14 +208,6 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement
|
|||
@Param(description = "Name of the VPC to which this network belongs", since = "4.15")
|
||||
private String vpcName;
|
||||
|
||||
@SerializedName(ApiConstants.ASSOCIATED_NETWORK_ID)
|
||||
@Param(description = "the ID of the Network associated with this network")
|
||||
private String associatedNetworkId;
|
||||
|
||||
@SerializedName(ApiConstants.ASSOCIATED_NETWORK)
|
||||
@Param(description = "the name of the Network associated with this network")
|
||||
private String associatedNetworkName;
|
||||
|
||||
@SerializedName(ApiConstants.TUNGSTEN_VIRTUAL_ROUTER_UUID)
|
||||
@Param(description = "Tungsten-Fabric virtual router the network belongs to")
|
||||
private String tungstenVirtualRouterUuid;
|
||||
|
|
@ -612,14 +604,6 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement
|
|||
this.vpcName = vpcName;
|
||||
}
|
||||
|
||||
public void setAssociatedNetworkId(String associatedNetworkId) {
|
||||
this.associatedNetworkId = associatedNetworkId;
|
||||
}
|
||||
|
||||
public void setAssociatedNetworkName(String associatedNetworkName) {
|
||||
this.associatedNetworkName = associatedNetworkName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceIconResponse(ResourceIconResponse icon) {
|
||||
this.icon = icon;
|
||||
|
|
|
|||
|
|
@ -38,14 +38,6 @@ public class SystemVmResponse extends BaseResponseWithAnnotations {
|
|||
@Param(description = "the system VM type")
|
||||
private String systemVmType;
|
||||
|
||||
@SerializedName("jobid")
|
||||
@Param(description = "the job ID associated with the system VM. This is only displayed if the router listed is part of a currently running asynchronous job.")
|
||||
private String jobId;
|
||||
|
||||
@SerializedName("jobstatus")
|
||||
@Param(description = "the job status associated with the system VM. This is only displayed if the router listed is part of a currently running asynchronous job.")
|
||||
private Integer jobStatus;
|
||||
|
||||
@SerializedName("zoneid")
|
||||
@Param(description = "the Zone ID for the system VM")
|
||||
private String zoneId;
|
||||
|
|
|
|||
|
|
@ -127,9 +127,9 @@ public class VlanIpRangeResponse extends BaseResponse implements ControlledEntit
|
|||
@Param(description = "indicates whether VLAN IP range is dedicated to system vms or not")
|
||||
private Boolean forSystemVms;
|
||||
|
||||
@SerializedName(ApiConstants.FOR_NSX)
|
||||
@Param(description = "indicates whether IP range is dedicated to NSX resources or not")
|
||||
private Boolean forNsx;
|
||||
@SerializedName(ApiConstants.PROVIDER)
|
||||
@Param(description = "indicates whether IP range is dedicated to NSX resources or not", since = "4.20.0")
|
||||
private String provider;
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
|
|
@ -249,7 +249,7 @@ public class VlanIpRangeResponse extends BaseResponse implements ControlledEntit
|
|||
this.ip6Cidr = ip6Cidr;
|
||||
}
|
||||
|
||||
public void setForNsx(Boolean forNsx) {
|
||||
this.forNsx = forNsx;
|
||||
public void setProvider(String provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,10 +145,15 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso
|
|||
@Param(description = "the type of the zone - core or edge", since = "4.18.0")
|
||||
String type;
|
||||
|
||||
@Deprecated(since = "4.20")
|
||||
@SerializedName(ApiConstants.NSX_ENABLED)
|
||||
@Param(description = "true, if zone is NSX enabled", since = "4.20.0")
|
||||
private boolean nsxEnabled = false;
|
||||
|
||||
@SerializedName(ApiConstants.PROVIDER)
|
||||
@Param(description = "External network provider if any", since = "4.20.0")
|
||||
private String provider = null;
|
||||
|
||||
@SerializedName(ApiConstants.MULTI_ARCH)
|
||||
@Param(description = "true, if zone contains clusters and hosts from different CPU architectures", since = "4.20")
|
||||
private boolean multiArch;
|
||||
|
|
@ -368,6 +373,14 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso
|
|||
return nsxEnabled;
|
||||
}
|
||||
|
||||
public String getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
public void setProvider(String provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceIconResponse(ResourceIconResponse resourceIconResponse) {
|
||||
this.resourceIconResponse = resourceIconResponse;
|
||||
|
|
|
|||
|
|
@ -1097,6 +1097,11 @@
|
|||
<artifactId>cloud-plugin-network-nsx</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-network-netris</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-network-tungsten</artifactId>
|
||||
|
|
|
|||
|
|
@ -75,13 +75,17 @@ public class ArrayTypeAdaptor<T> implements JsonDeserializer<T[]>, JsonSerialize
|
|||
try {
|
||||
clazz = Class.forName(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new CloudRuntimeException("can't find " + name);
|
||||
throw new JsonParseException("can't find " + name);
|
||||
}
|
||||
T cmd = (T)_gson.fromJson(entry.getValue(), clazz);
|
||||
cmds.add(cmd);
|
||||
}
|
||||
Class<?> type = ((Class<?>)typeOfT).getComponentType();
|
||||
T[] ts = (T[])Array.newInstance(type, cmds.size());
|
||||
return cmds.toArray(ts);
|
||||
try {
|
||||
Class<?> type = Class.forName(typeOfT.getTypeName().replace("[]", ""));
|
||||
T[] ts = (T[])Array.newInstance(type, cmds.size());
|
||||
return cmds.toArray(ts);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new CloudRuntimeException("can't find " + typeOfT.getTypeName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ public interface ConfigurationManager {
|
|||
NetworkOffering.RoutingMode routingMode, boolean specifyAsNumber);
|
||||
|
||||
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, boolean forNsx)
|
||||
String vlanGateway, String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr, Provider provider)
|
||||
throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException;
|
||||
|
||||
void createDefaultSystemNetworks(long zoneId) throws ConcurrentOperationException;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import com.cloud.bgp.BGPService;
|
|||
import com.cloud.dc.VlanDetailsVO;
|
||||
import com.cloud.dc.dao.ASNumberDao;
|
||||
import com.cloud.dc.dao.VlanDetailsDao;
|
||||
import com.cloud.network.dao.NetrisProviderDao;
|
||||
import com.cloud.network.dao.NsxProviderDao;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
|
|
@ -355,6 +356,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
@Inject
|
||||
private NsxProviderDao nsxProviderDao;
|
||||
@Inject
|
||||
private NetrisProviderDao netrisProviderDao;
|
||||
@Inject
|
||||
private ASNumberDao asNumberDao;
|
||||
@Inject
|
||||
private BGPService bgpService;
|
||||
|
|
@ -1082,10 +1085,14 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
return null;
|
||||
}
|
||||
|
||||
if (isNicAllocatedForNsxPublicNetworkOnVR(network, profile, vm)) {
|
||||
if (isNicAllocatedForProviderPublicNetworkOnVR(network, profile, vm, Provider.Nsx)) {
|
||||
String guruName = "NsxPublicNetworkGuru";
|
||||
NetworkGuru nsxGuru = AdapterBase.getAdapterByName(networkGurus, guruName);
|
||||
nsxGuru.allocate(network, profile, vm);
|
||||
} else if (isNicAllocatedForProviderPublicNetworkOnVR(network, profile, vm, Provider.Netris)) {
|
||||
String guruName = "NetrisPublicNetworkGuru";
|
||||
NetworkGuru nsxGuru = AdapterBase.getAdapterByName(networkGurus, guruName);
|
||||
nsxGuru.allocate(network, profile, vm);
|
||||
}
|
||||
|
||||
if (isDefaultNic != null) {
|
||||
|
|
@ -1148,7 +1155,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
return new Pair<NicProfile, Integer>(vmNic, Integer.valueOf(deviceId));
|
||||
}
|
||||
|
||||
private boolean isNicAllocatedForNsxPublicNetworkOnVR(Network network, NicProfile requested, VirtualMachineProfile vm) {
|
||||
private boolean isNicAllocatedForProviderPublicNetworkOnVR(Network network, NicProfile requested, VirtualMachineProfile vm, Provider provider) {
|
||||
if (ObjectUtils.anyNull(network, requested, vm)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1158,7 +1165,9 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
return false;
|
||||
}
|
||||
long dataCenterId = vm.getVirtualMachine().getDataCenterId();
|
||||
if (nsxProviderDao.findByZoneId(dataCenterId) == null) {
|
||||
if (Provider.Nsx == provider && nsxProviderDao.findByZoneId(dataCenterId) == null) {
|
||||
return false;
|
||||
} else if (Provider.Netris == provider && netrisProviderDao.findByZoneId(dataCenterId) == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1168,14 +1177,16 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
if (CollectionUtils.isEmpty(ips)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ips = ips.stream().filter(x -> !x.getAddress().addr().equals(requested.getIPv4Address())).collect(Collectors.toList());
|
||||
IPAddressVO ip = ips.get(0);
|
||||
VlanDetailsVO vlanDetail = vlanDetailsDao.findDetail(ip.getVlanId(), ApiConstants.NSX_DETAIL_KEY);
|
||||
String detailKey = Provider.Nsx == provider ? ApiConstants.NSX_DETAIL_KEY : ApiConstants.NETRIS_DETAIL_KEY;
|
||||
VlanDetailsVO vlanDetail = vlanDetailsDao.findDetail(ip.getVlanId(), detailKey);
|
||||
if (vlanDetail == null) {
|
||||
return false;
|
||||
}
|
||||
boolean isForNsx = vlanDetail.getValue().equalsIgnoreCase("true");
|
||||
return isForNsx && !ip.isForSystemVms();
|
||||
boolean isForProvider = vlanDetail.getValue().equalsIgnoreCase("true");
|
||||
return isForProvider && !ip.isForSystemVms();
|
||||
}
|
||||
|
||||
private void setMtuDetailsInVRNic(final Pair<NetworkVO, VpcVO> networks, Network network, NicVO vo) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
// 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 com.cloud.network.dao;
|
||||
|
||||
import com.cloud.network.element.NetrisProviderVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface NetrisProviderDao extends GenericDao<NetrisProviderVO, Long> {
|
||||
NetrisProviderVO findByZoneId(long zoneId);
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// 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 com.cloud.network.dao;
|
||||
|
||||
import com.cloud.network.element.NetrisProviderVO;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@DB()
|
||||
public class NetrisProviderDaoImpl extends GenericDaoBase<NetrisProviderVO, Long> implements NetrisProviderDao {
|
||||
|
||||
final SearchBuilder<NetrisProviderVO> allFieldsSearch;
|
||||
|
||||
public NetrisProviderDaoImpl() {
|
||||
super();
|
||||
allFieldsSearch = createSearchBuilder();
|
||||
allFieldsSearch.and("id", allFieldsSearch.entity().getId(),
|
||||
SearchCriteria.Op.EQ);
|
||||
allFieldsSearch.and("uuid", allFieldsSearch.entity().getUuid(),
|
||||
SearchCriteria.Op.EQ);
|
||||
allFieldsSearch.and("hostname", allFieldsSearch.entity().getHostname(),
|
||||
SearchCriteria.Op.EQ);
|
||||
allFieldsSearch.and("zone_id", allFieldsSearch.entity().getZoneId(),
|
||||
SearchCriteria.Op.EQ);
|
||||
allFieldsSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetrisProviderVO findByZoneId(long zoneId) {
|
||||
SearchCriteria<NetrisProviderVO> sc = allFieldsSearch.create();
|
||||
sc.setParameters("zone_id", zoneId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import javax.persistence.GeneratedValue;
|
|||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
|
|
@ -59,6 +60,18 @@ public class NetrisProviderVO implements NetrisProvider {
|
|||
@Column(name = "password")
|
||||
private String password;
|
||||
|
||||
@Column(name = "site_name")
|
||||
private String siteName;
|
||||
|
||||
@Column(name = "tenant_name")
|
||||
private String tenantName;
|
||||
|
||||
@Column(name = "created")
|
||||
private Date created;
|
||||
|
||||
@Column(name = "removed")
|
||||
private Date removed;
|
||||
|
||||
public NetrisProviderVO() {
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
|
@ -141,4 +154,112 @@ public class NetrisProviderVO implements NetrisProvider {
|
|||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getSiteName() {
|
||||
return siteName;
|
||||
}
|
||||
|
||||
public void setSiteName(String siteName) {
|
||||
this.siteName = siteName;
|
||||
}
|
||||
|
||||
public String getTenantName() {
|
||||
return tenantName;
|
||||
}
|
||||
|
||||
public void setTenantName(String tenantName) {
|
||||
this.tenantName = tenantName;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public Date getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void setRemoved(Date removed) {
|
||||
this.removed = removed;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private long zoneId;
|
||||
private long hostId;
|
||||
private String name;
|
||||
private String hostname;
|
||||
private String port;
|
||||
private String username;
|
||||
private String password;
|
||||
private String siteName;
|
||||
private String tenantName;
|
||||
|
||||
public Builder() {
|
||||
// Default constructor
|
||||
}
|
||||
|
||||
public Builder setZoneId(long zoneId) {
|
||||
this.zoneId = zoneId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setHostId(long hostId) {
|
||||
this.hostId = hostId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setHostname(String hostname) {
|
||||
this.hostname = hostname;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPort(String port) {
|
||||
this.port = port;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUsername(String username) {
|
||||
this.username = username;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPassword(String password) {
|
||||
this.password = password;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSiteName(String siteName) {
|
||||
this.siteName = siteName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTenantName(String tenantName) {
|
||||
this.tenantName = tenantName;
|
||||
return this;
|
||||
}
|
||||
public NetrisProviderVO build() {
|
||||
NetrisProviderVO provider = new NetrisProviderVO();
|
||||
provider.setZoneId(this.zoneId);
|
||||
provider.setHostId(this.hostId);
|
||||
provider.setUuid(UUID.randomUUID().toString());
|
||||
provider.setName(this.name);
|
||||
provider.setHostname(this.hostname);
|
||||
provider.setPort(this.port);
|
||||
provider.setUsername(this.username);
|
||||
provider.setPassword(this.password);
|
||||
provider.setSiteName(this.siteName);
|
||||
provider.setTenantName(this.tenantName);
|
||||
provider.setCreated(new Date());
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,9 +59,6 @@ public class VpcOfferingVO implements VpcOffering {
|
|||
@Column(name = "default")
|
||||
boolean isDefault = false;
|
||||
|
||||
@Column(name = "for_nsx")
|
||||
boolean forNsx = false;
|
||||
|
||||
@Column(name = "network_mode")
|
||||
NetworkOffering.NetworkMode networkMode;
|
||||
|
||||
|
|
@ -158,14 +155,6 @@ public class VpcOfferingVO implements VpcOffering {
|
|||
return isDefault;
|
||||
}
|
||||
|
||||
public boolean isForNsx() {
|
||||
return forNsx;
|
||||
}
|
||||
|
||||
public void setForNsx(boolean forNsx) {
|
||||
this.forNsx = forNsx;
|
||||
}
|
||||
|
||||
public NetworkOffering.NetworkMode getNetworkMode() {
|
||||
return networkMode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package com.cloud.network.vpc.dao;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Network.Service;
|
||||
import com.cloud.network.vpc.VpcOfferingServiceMapVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
|
@ -37,4 +38,6 @@ public interface VpcOfferingServiceMapDao extends GenericDao<VpcOfferingServiceM
|
|||
|
||||
VpcOfferingServiceMapVO findByServiceProviderAndOfferingId(String service, String provider, long vpcOfferingId);
|
||||
|
||||
boolean isProviderForVpcOffering(Network.Provider provider, long vpcOfferingId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package com.cloud.network.vpc.dao;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
import com.cloud.network.Network;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.network.Network.Service;
|
||||
|
|
@ -110,4 +111,12 @@ public class VpcOfferingServiceMapDaoImpl extends GenericDaoBase<VpcOfferingServ
|
|||
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProviderForVpcOffering(Network.Provider provider, long vpcOfferingId) {
|
||||
SearchCriteria<VpcOfferingServiceMapVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("vpcOffId", vpcOfferingId);
|
||||
sc.setParameters("provider", provider.getName());
|
||||
return findOneBy(sc) != null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,12 +133,6 @@ public class NetworkOfferingVO implements NetworkOffering {
|
|||
@Column(name = "for_vpc")
|
||||
boolean forVpc;
|
||||
|
||||
@Column(name = "for_tungsten")
|
||||
boolean forTungsten = false;
|
||||
|
||||
@Column(name = "for_nsx")
|
||||
boolean forNsx = false;
|
||||
|
||||
@Column(name = "network_mode")
|
||||
NetworkMode networkMode;
|
||||
|
||||
|
|
@ -199,24 +193,6 @@ public class NetworkOfferingVO implements NetworkOffering {
|
|||
this.forVpc = isForVpc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForTungsten() {
|
||||
return forTungsten;
|
||||
}
|
||||
|
||||
public void setForTungsten(boolean forTungsten) {
|
||||
this.forTungsten = forTungsten;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForNsx() {
|
||||
return forNsx;
|
||||
}
|
||||
|
||||
public void setForNsx(boolean forNsx) {
|
||||
this.forNsx = forNsx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkMode getNetworkMode() {
|
||||
return networkMode;
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@
|
|||
<bean id="objectInDataStoreDaoImpl" class="org.apache.cloudstack.storage.db.ObjectInDataStoreDaoImpl" />
|
||||
<bean id="ovsProviderDaoImpl" class="com.cloud.network.dao.OvsProviderDaoImpl" />
|
||||
<bean id="nsxControllerDaoImpl" class="com.cloud.network.dao.NsxProviderDaoImpl" />
|
||||
<bean id="netrisProviderDaoImpl" class="com.cloud.network.dao.NetrisProviderDaoImpl" />
|
||||
<bean id="tungstenControllerDaoImpl" class="com.cloud.network.dao.TungstenProviderDaoImpl"/>
|
||||
<bean id="physicalNetworkDaoImpl" class="com.cloud.network.dao.PhysicalNetworkDaoImpl" />
|
||||
<bean id="physicalNetworkIsolationMethodDaoImpl" class="com.cloud.network.dao.PhysicalNetworkIsolationMethodDaoImpl" />
|
||||
|
|
|
|||
|
|
@ -437,9 +437,18 @@ CREATE TABLE `cloud`.`netris_providers` (
|
|||
`port` varchar(255),
|
||||
`username` varchar(255) NOT NULL,
|
||||
`password` varchar(255) NOT NULL,
|
||||
`created` datetime NOT NULL COMMENT 'date created',
|
||||
`removed` datetime COMMENT 'date removed if not null',
|
||||
`site_name` varchar(255) NOT NULL,
|
||||
`tenant_name` varchar(255) NOT NULL,
|
||||
`created` datetime NOT NULL COMMENT 'created date',
|
||||
`removed` datetime COMMENT 'removed date if not null',
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `fk_netris_providers__zone_id` FOREIGN KEY `fk_netris_providers__zone_id` (`zone_id`) REFERENCES `data_center`(`id`) ON DELETE CASCADE,
|
||||
INDEX `i_netris_providers__zone_id`(`zone_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- Drop the Tungsten and NSX columns from the network offerings (replaced by checking the provider on the ntwk_offering_service_map table)
|
||||
ALTER TABLE `cloud`.`network_offerings` DROP COLUMN `for_tungsten`;
|
||||
ALTER TABLE `cloud`.`network_offerings` DROP COLUMN `for_nsx`;
|
||||
|
||||
-- Drop the Tungsten and NSX columns from the VPC offerings (replaced by checking the provider on the vpc_offering_service_map table)
|
||||
ALTER TABLE `cloud`.`vpc_offerings` DROP COLUMN `for_nsx`;
|
||||
|
|
|
|||
|
|
@ -59,8 +59,6 @@ SELECT
|
|||
`network_offerings`.`supports_public_access` AS `supports_public_access`,
|
||||
`network_offerings`.`supports_vm_autoscaling` AS `supports_vm_autoscaling`,
|
||||
`network_offerings`.`for_vpc` AS `for_vpc`,
|
||||
`network_offerings`.`for_tungsten` AS `for_tungsten`,
|
||||
`network_offerings`.`for_nsx` AS `for_nsx`,
|
||||
`network_offerings`.`network_mode` AS `network_mode`,
|
||||
`network_offerings`.`service_package_id` AS `service_package_id`,
|
||||
`network_offerings`.`routing_mode` AS `routing_mode`,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ select
|
|||
`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`.`network_mode` AS `network_mode`,
|
||||
`vpc_offerings`.`created` AS `created`,
|
||||
`vpc_offerings`.`removed` AS `removed`,
|
||||
|
|
|
|||
|
|
@ -2008,7 +2008,6 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
|
|||
forVpc, true, false, false);
|
||||
if (forNsx) {
|
||||
defaultKubernetesServiceNetworkOffering.setNetworkMode(NetworkOffering.NetworkMode.NATTED);
|
||||
defaultKubernetesServiceNetworkOffering.setForNsx(true);
|
||||
}
|
||||
defaultKubernetesServiceNetworkOffering.setSupportsVmAutoScaling(true);
|
||||
defaultKubernetesServiceNetworkOffering.setState(NetworkOffering.State.Enabled);
|
||||
|
|
|
|||
|
|
@ -712,7 +712,7 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements
|
|||
metricsResponse.setCpuTotal(hostResponse.getCpuNumber(), hostResponse.getCpuSpeed());
|
||||
metricsResponse.setCpuUsed(hostResponse.getCpuUsed(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed());
|
||||
metricsResponse.setCpuAllocated(hostResponse.getCpuAllocated(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed());
|
||||
metricsResponse.setLoadAverage(hostResponse.getAverageLoad());
|
||||
metricsResponse.setCpuAverageLoad(hostResponse.getAverageLoad());
|
||||
metricsResponse.setMemTotal(hostResponse.getMemoryTotal());
|
||||
metricsResponse.setMemAllocated(hostResponse.getMemoryAllocated());
|
||||
metricsResponse.setMemUsed(hostResponse.getMemoryUsed());
|
||||
|
|
|
|||
|
|
@ -52,10 +52,6 @@ public class HostMetricsResponse extends HostResponse {
|
|||
@Param(description = "the total cpu allocated in Ghz")
|
||||
private String cpuAllocated;
|
||||
|
||||
@SerializedName("cpuloadaverage")
|
||||
@Param(description = "the average cpu load the last minute")
|
||||
private Double loadAverage;
|
||||
|
||||
@SerializedName("memorytotalgb")
|
||||
@Param(description = "the total memory capacity in GiB")
|
||||
private String memTotal;
|
||||
|
|
@ -132,12 +128,6 @@ public class HostMetricsResponse extends HostResponse {
|
|||
}
|
||||
}
|
||||
|
||||
public void setLoadAverage(final Double loadAverage) {
|
||||
if (loadAverage != null) {
|
||||
this.loadAverage = loadAverage;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCpuAllocated(final String cpuAllocated, final Integer cpuNumber, final Long cpuSpeed) {
|
||||
if (cpuAllocated != null && cpuNumber != null && cpuSpeed != null) {
|
||||
this.cpuAllocated = String.format("%.2f Ghz", parseCPU(cpuAllocated) * cpuNumber * cpuSpeed / (100.0 * 1000.0));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
// 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;
|
||||
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.host.Host;
|
||||
|
||||
public class StartupNetrisCommand extends StartupCommand {
|
||||
public StartupNetrisCommand() {
|
||||
super(Host.Type.L2Networking);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// 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.agent.api;
|
||||
|
||||
public class CreateNetrisVnetCommand extends NetrisCommand {
|
||||
private String vpcName;
|
||||
private Long vpcId;
|
||||
private String cidr;
|
||||
private Integer vxlanId;
|
||||
|
||||
public CreateNetrisVnetCommand(Long zoneId, Long accountId, Long domainId, String vpcName, Long vpcId, String vNetName, Long networkId, String cidr, boolean isVpc) {
|
||||
super(zoneId, accountId, domainId, vNetName, networkId, isVpc);
|
||||
this.vpcId = vpcId;
|
||||
this.vpcName = vpcName;
|
||||
this.cidr = cidr;
|
||||
}
|
||||
|
||||
|
||||
public Long getVpcId() {
|
||||
return vpcId;
|
||||
}
|
||||
|
||||
public String getVpcName() {
|
||||
return vpcName;
|
||||
}
|
||||
|
||||
public String getCidr() {
|
||||
return cidr;
|
||||
}
|
||||
|
||||
public Integer getVxlanId() {
|
||||
return vxlanId;
|
||||
}
|
||||
|
||||
public void setVxlanId(Integer vxlanId) {
|
||||
this.vxlanId = vxlanId;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// 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.agent.api;
|
||||
|
||||
public class CreateNetrisVpcCommand extends NetrisCommand {
|
||||
|
||||
private final String cidr;
|
||||
|
||||
public CreateNetrisVpcCommand(long zoneId, long accountId, long domainId, String name, String cidr, long vpcId, boolean isVpc) {
|
||||
super(zoneId, accountId, domainId, name, vpcId, isVpc);
|
||||
this.cidr = cidr;
|
||||
}
|
||||
|
||||
public String getCidr() {
|
||||
return cidr;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// 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.agent.api;
|
||||
|
||||
public class DeleteNetrisVpcCommand extends NetrisCommand {
|
||||
private final String cidr;
|
||||
|
||||
public DeleteNetrisVpcCommand(long zoneId, long accountId, long domainId, String name, String cidr, long vpcId, boolean isVpc) {
|
||||
super(zoneId, accountId, domainId, name, vpcId, isVpc);
|
||||
this.cidr = cidr;
|
||||
}
|
||||
|
||||
public String getCidr() {
|
||||
return cidr;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// 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.agent.api;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public class NetrisAnswer extends Answer {
|
||||
public NetrisAnswer(final Command command, final boolean success, final String details) {
|
||||
super(command, success, details);
|
||||
}
|
||||
|
||||
public NetrisAnswer(final Command command, final Exception e) {
|
||||
super(command, e);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// 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.agent.api;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public class NetrisCommand extends Command {
|
||||
private final long zoneId;
|
||||
private final long accountId;
|
||||
private final long domainId;
|
||||
private final String name;
|
||||
private final long id;
|
||||
private final boolean isVpc;
|
||||
|
||||
public NetrisCommand(long zoneId, long accountId, long domainId, String name, long id, boolean isVpc) {
|
||||
this.zoneId = zoneId;
|
||||
this.accountId = accountId;
|
||||
this.domainId = domainId;
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.isVpc = isVpc;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public boolean isVpc() {
|
||||
return isVpc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,25 +17,103 @@
|
|||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.NetworkRuleConflictException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.netris.NetrisProvider;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.NetrisProviderResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.service.NetrisProviderService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@APICommand(name = AddNetrisProviderCmd.APINAME, description = "Add Netris Provider to CloudStack",
|
||||
responseObject = NetrisProviderResponse.class, requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = false, since = "4.20")
|
||||
public class AddNetrisProviderCmd extends BaseCmd {
|
||||
public static final String APINAME = "addNetrisProvider";
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(AddNetrisProviderCmd.class.getName());
|
||||
|
||||
@Inject
|
||||
NetrisProviderService netrisProviderService;
|
||||
|
||||
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true,
|
||||
description = "the ID of zone")
|
||||
private Long zoneId;
|
||||
|
||||
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Netris provider name")
|
||||
private String name;
|
||||
|
||||
@Parameter(name = ApiConstants.HOST_NAME, type = CommandType.STRING, required = true, description = "Netris provider hostname / IP address")
|
||||
private String hostname;
|
||||
|
||||
@Parameter(name = ApiConstants.PORT, type = CommandType.STRING, description = "Netris provider port")
|
||||
private String port;
|
||||
|
||||
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, required = true, description = "Username to log into Netris")
|
||||
private String username;
|
||||
|
||||
@Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, required = true, description = "Password to login into Netris")
|
||||
private String password;
|
||||
|
||||
@Parameter(name = ApiConstants.SITE_NAME, type = CommandType.STRING, required = true, description = "Netris Site name")
|
||||
private String siteName;
|
||||
|
||||
@Parameter(name = ApiConstants.TENANT_NAME, type = CommandType.STRING, required = true, description = "Password to login into Netris")
|
||||
private String tenantName;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public String getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getSiteName() {
|
||||
return siteName;
|
||||
}
|
||||
|
||||
public String getTenantName() {
|
||||
return tenantName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
|
||||
|
||||
public void execute() throws ServerApiException, ConcurrentOperationException {
|
||||
NetrisProvider provider = netrisProviderService.addProvider(this);
|
||||
NetrisProviderResponse response = netrisProviderService.createNetrisProviderResponse(provider);
|
||||
if (response == null)
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Netris provider");
|
||||
else {
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
// 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.api.command;
|
||||
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.NetrisProviderResponse;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import org.apache.cloudstack.service.NetrisProviderService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.apache.cloudstack.api.command.DeleteNetrisProviderCmd.APINAME;
|
||||
|
||||
@APICommand(name = APINAME, description = "delete Netris Provider to CloudStack",
|
||||
responseObject = NetrisProviderResponse.class, requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = false, since = "4.20.0")
|
||||
public class DeleteNetrisProviderCmd extends BaseCmd {
|
||||
public static final String APINAME = "deleteNetrisProvider";
|
||||
|
||||
@Inject
|
||||
private NetrisProviderService netrisProviderService;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = NetrisProviderResponse.class,
|
||||
required = true, description = "Netris Provider ID")
|
||||
private Long id;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getId() { return id; }
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() throws ServerApiException, ConcurrentOperationException {
|
||||
try {
|
||||
boolean deleted = netrisProviderService.deleteNetrisProvider(getId());
|
||||
if (deleted) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to Netris provider from zone");
|
||||
}
|
||||
} catch (InvalidParameterValueException e) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, e.getMessage());
|
||||
} catch (CloudRuntimeException e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// 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.api.command;
|
||||
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.NetrisProviderResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
import org.apache.cloudstack.service.NetrisProviderService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
@APICommand(name = ListNetrisProvidersCmd.APINAME, description = "list all Netris providers added to CloudStack",
|
||||
responseObject = NetrisProviderResponse.class, requestHasSensitiveInfo = false,
|
||||
responseHasSensitiveInfo = false, since = "4.20.0")
|
||||
public class ListNetrisProvidersCmd extends BaseListCmd {
|
||||
public static final String APINAME = "listNetrisProviders";
|
||||
|
||||
@Inject
|
||||
NetrisProviderService netrisProviderService;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
///
|
||||
@Parameter(name = ApiConstants.ZONE_ID, description = "Netris provider added to the specific zone",
|
||||
type = CommandType.UUID, entityType = ZoneResponse.class)
|
||||
Long zoneId;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() throws ServerApiException, ConcurrentOperationException {
|
||||
List<BaseResponse> baseResponseList = netrisProviderService.listNetrisProviders(zoneId);
|
||||
List<BaseResponse> pagingList = StringUtils.applyPagination(baseResponseList, this.getStartIndex(), this.getPageSizeVal());
|
||||
ListResponse<BaseResponse> listResponse = new ListResponse<>();
|
||||
listResponse.setResponses(pagingList);
|
||||
listResponse.setResponseName(getCommandName());
|
||||
setResponseObject(listResponse);
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,10 @@ public class NetrisProviderResponse extends BaseResponse {
|
|||
@Param(description = "Netris Provider name")
|
||||
private String name;
|
||||
|
||||
@SerializedName(ApiConstants.UUID)
|
||||
@Param(description = "Netris provider uuid")
|
||||
private String uuid;
|
||||
|
||||
@SerializedName(ApiConstants.ZONE_ID)
|
||||
@Param(description = "Zone ID to which the Netris Provider is associated with")
|
||||
private String zoneId;
|
||||
|
|
@ -45,9 +49,13 @@ public class NetrisProviderResponse extends BaseResponse {
|
|||
@Param(description = "Netris Provider port")
|
||||
private String port;
|
||||
|
||||
@SerializedName(ApiConstants.USERNAME)
|
||||
@Param(description = "Netris Provider username")
|
||||
private String username;
|
||||
@SerializedName(ApiConstants.SITE_NAME)
|
||||
@Param(description = "Netris Provider site")
|
||||
private String siteName;
|
||||
|
||||
@SerializedName(ApiConstants.TENANT_NAME)
|
||||
@Param(description = "Netris Admin tenant name")
|
||||
private String tenantName;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
|
|
@ -57,6 +65,14 @@ public class NetrisProviderResponse extends BaseResponse {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public String getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
|
@ -89,11 +105,19 @@ public class NetrisProviderResponse extends BaseResponse {
|
|||
this.port = port;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
public String getSiteName() {
|
||||
return siteName;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
public void setSiteName(String siteName) {
|
||||
this.siteName = siteName;
|
||||
}
|
||||
|
||||
public String getTenantName() {
|
||||
return tenantName;
|
||||
}
|
||||
|
||||
public void setTenantName(String tenantName) {
|
||||
this.tenantName = tenantName;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,244 @@
|
|||
// 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.agent.IAgentControl;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.CheckHealthAnswer;
|
||||
import com.cloud.agent.api.CheckHealthCommand;
|
||||
import com.cloud.agent.api.Command;
|
||||
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.host.Host;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
|
||||
import org.apache.cloudstack.agent.api.NetrisAnswer;
|
||||
import org.apache.cloudstack.StartupNetrisCommand;
|
||||
import org.apache.cloudstack.service.NetrisApiClient;
|
||||
import org.apache.cloudstack.service.NetrisApiClientImpl;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class NetrisResource implements ServerResource {
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
||||
private String name;
|
||||
protected String hostname;
|
||||
protected String username;
|
||||
protected String password;
|
||||
protected String guid;
|
||||
protected String zoneId;
|
||||
protected String siteName;
|
||||
protected String adminTenantName;
|
||||
|
||||
protected NetrisApiClient netrisApiClient;
|
||||
|
||||
@Override
|
||||
public Host.Type getType() {
|
||||
return Host.Type.Routing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartupCommand[] initialize() {
|
||||
StartupNetrisCommand sc = new StartupNetrisCommand();
|
||||
sc.setGuid(guid);
|
||||
sc.setName(name);
|
||||
sc.setDataCenter(zoneId);
|
||||
sc.setPod("");
|
||||
sc.setPrivateIpAddress("");
|
||||
sc.setStorageIpAddress("");
|
||||
sc.setVersion("");
|
||||
return new StartupCommand[] {sc};
|
||||
}
|
||||
|
||||
@Override
|
||||
public PingCommand getCurrentStatus(long id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
if (cmd instanceof ReadyCommand) {
|
||||
return executeRequest((ReadyCommand) cmd);
|
||||
} else if (cmd instanceof CheckHealthCommand) {
|
||||
return executeRequest((CheckHealthCommand) cmd);
|
||||
} else if (cmd instanceof CreateNetrisVpcCommand) {
|
||||
return executeRequest((CreateNetrisVpcCommand) cmd);
|
||||
} else if (cmd instanceof DeleteNetrisVpcCommand) {
|
||||
return executeRequest((DeleteNetrisVpcCommand) cmd);
|
||||
} else if (cmd instanceof CreateNetrisVnetCommand) {
|
||||
return executeRequest((CreateNetrisVnetCommand) cmd);
|
||||
} else {
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAgentControl getAgentControl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAgentControl(IAgentControl agentControl) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfigParams(Map<String, Object> params) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getConfigParams() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRunLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRunLevel(int level) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
hostname = (String) params.get("hostname");
|
||||
if (hostname == null) {
|
||||
throw new ConfigurationException("Missing Netris hostname from params: " + params);
|
||||
}
|
||||
|
||||
username = (String) params.get("username");
|
||||
if (username == null) {
|
||||
throw new ConfigurationException("Missing Netris username from params: " + params);
|
||||
}
|
||||
|
||||
password = (String) params.get("password");
|
||||
if (password == null) {
|
||||
throw new ConfigurationException("Missing Netris password from params: " + params);
|
||||
}
|
||||
|
||||
this.name = (String) params.get("name");
|
||||
if (this.name == null) {
|
||||
throw new ConfigurationException("Unable to find name");
|
||||
}
|
||||
|
||||
guid = (String) params.get("guid");
|
||||
if (guid == null) {
|
||||
throw new ConfigurationException("Unable to find the guid");
|
||||
}
|
||||
|
||||
zoneId = (String) params.get("zoneId");
|
||||
if (zoneId == null) {
|
||||
throw new ConfigurationException("Unable to find zone");
|
||||
}
|
||||
|
||||
siteName = (String) params.get("siteName");
|
||||
if (siteName == null) {
|
||||
throw new ConfigurationException("Unable to find the Netris site name");
|
||||
}
|
||||
|
||||
adminTenantName = (String) params.get("tenantName");
|
||||
if (adminTenantName == null) {
|
||||
throw new ConfigurationException("Unable to find the Netris admin tenant name");
|
||||
}
|
||||
|
||||
netrisApiClient = new NetrisApiClientImpl(hostname, username, password, siteName, adminTenantName);
|
||||
return netrisApiClient.isSessionAlive();
|
||||
}
|
||||
|
||||
private Answer executeRequest(ReadyCommand cmd) {
|
||||
return new ReadyAnswer(cmd);
|
||||
}
|
||||
|
||||
private Answer executeRequest(CheckHealthCommand cmd) {
|
||||
return new CheckHealthAnswer(cmd, netrisApiClient.isSessionAlive());
|
||||
}
|
||||
|
||||
private Answer executeRequest(CreateNetrisVpcCommand cmd) {
|
||||
try {
|
||||
boolean result = netrisApiClient.createVpc(cmd);
|
||||
if (!result) {
|
||||
return new NetrisAnswer(cmd, false, String.format("Netris VPC %s creation failed", cmd.getName()));
|
||||
}
|
||||
return new NetrisAnswer(cmd, true, "OK");
|
||||
} catch (CloudRuntimeException e) {
|
||||
String msg = String.format("Error creating Netris VPC: %s", e.getMessage());
|
||||
logger.error(msg, e);
|
||||
return new NetrisAnswer(cmd, new CloudRuntimeException(msg));
|
||||
}
|
||||
}
|
||||
|
||||
private Answer executeRequest(CreateNetrisVnetCommand cmd) {
|
||||
try {
|
||||
String vpcName = cmd.getVpcName();
|
||||
boolean result = netrisApiClient.createVnet(cmd);
|
||||
if (!result) {
|
||||
return new NetrisAnswer(cmd, false, String.format("Netris VPC %s creation failed", vpcName));
|
||||
}
|
||||
return new NetrisAnswer(cmd, true, "OK");
|
||||
} catch (CloudRuntimeException e) {
|
||||
String msg = String.format("Error creating Netris VPC: %s", e.getMessage());
|
||||
logger.error(msg, e);
|
||||
return new NetrisAnswer(cmd, new CloudRuntimeException(msg));
|
||||
}
|
||||
}
|
||||
|
||||
private Answer executeRequest(DeleteNetrisVpcCommand cmd) {
|
||||
boolean result = netrisApiClient.deleteVpc(cmd);
|
||||
if (!result) {
|
||||
return new NetrisAnswer(cmd, false, String.format("Netris VPC %s deletion failed", cmd.getName()));
|
||||
}
|
||||
return new NetrisAnswer(cmd, true, "OK");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
// 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 org.apache.cloudstack.agent.api.NetrisCommand;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
public class NetrisResourceObjectUtils {
|
||||
|
||||
public enum NetrisObjectType {
|
||||
VPC, IPAM_ALLOCATION, IPAM_SUBNET, VNET
|
||||
}
|
||||
|
||||
public static String retrieveNetrisResourceObjectName(NetrisCommand cmd, NetrisObjectType netrisObjectType, String... suffixes) {
|
||||
long zoneId = cmd.getZoneId();
|
||||
long accountId = cmd.getAccountId();
|
||||
long domainId = cmd.getDomainId();
|
||||
long objectId = cmd.getId();
|
||||
String objectName = cmd.getName();
|
||||
boolean isVpc = cmd.isVpc();
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append(String.format("D%s-A%s-Z%s", domainId, accountId, zoneId));
|
||||
String prefix = isVpc ? "-V" : "-N";
|
||||
switch (netrisObjectType) {
|
||||
case VPC:
|
||||
if (ArrayUtils.isEmpty(suffixes)) {
|
||||
stringBuilder.append(String.format("%s%s-%s", prefix, objectId, objectName));
|
||||
} else {
|
||||
stringBuilder.append(String.format("%s%s", prefix, suffixes[0]));
|
||||
suffixes = new String[0];
|
||||
}
|
||||
break;
|
||||
case IPAM_ALLOCATION:
|
||||
case IPAM_SUBNET:
|
||||
stringBuilder.append(String.format("%s%s", prefix, objectId));
|
||||
break;
|
||||
case VNET:
|
||||
break;
|
||||
default:
|
||||
stringBuilder.append(String.format("-%s", objectName));
|
||||
break;
|
||||
}
|
||||
if (ArrayUtils.isNotEmpty(suffixes)) {
|
||||
for (String suffix : suffixes) {
|
||||
stringBuilder.append(String.format("-%s", suffix));
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,9 @@ import io.netris.ApiException;
|
|||
import io.netris.model.GetSiteBody;
|
||||
import io.netris.model.VPCListing;
|
||||
import io.netris.model.response.TenantResponse;
|
||||
import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -28,4 +31,20 @@ public interface NetrisApiClient {
|
|||
List<GetSiteBody> listSites();
|
||||
List<VPCListing> listVPCs();
|
||||
List<TenantResponse> listTenants() throws ApiException;
|
||||
|
||||
/**
|
||||
* Create a VPC on CloudStack creates the following Netris resources:
|
||||
* - Create a Netris VPC with the VPC name
|
||||
* - Create an IPAM Allocation for the created Netris VPC using the Prefix = VPC CIDR
|
||||
*/
|
||||
boolean createVpc(CreateNetrisVpcCommand cmd);
|
||||
|
||||
/**
|
||||
* Delete a VPC on CloudStack removes the following Netris resources:
|
||||
* - Delete the IPAM Allocation for the VPC using the Prefix = VPC CIDR
|
||||
* - Delete a Netris VPC with the VPC name
|
||||
*/
|
||||
boolean deleteVpc(DeleteNetrisVpcCommand cmd);
|
||||
|
||||
boolean createVnet(CreateNetrisVnetCommand cmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.service;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import io.netris.ApiClient;
|
||||
import io.netris.ApiException;
|
||||
|
|
@ -23,18 +24,46 @@ import io.netris.ApiResponse;
|
|||
import io.netris.api.v1.AuthenticationApi;
|
||||
import io.netris.api.v1.SitesApi;
|
||||
import io.netris.api.v1.TenantsApi;
|
||||
import io.netris.api.v2.IpamApi;
|
||||
import io.netris.api.v2.VNetApi;
|
||||
import io.netris.api.v2.VpcApi;
|
||||
import io.netris.model.AllocationBody;
|
||||
import io.netris.model.AllocationBodyVpc;
|
||||
import io.netris.model.GetSiteBody;
|
||||
import io.netris.model.InlineResponse2004;
|
||||
import io.netris.model.IpTreeAllocationTenant;
|
||||
import io.netris.model.IpTreeSubnetSites;
|
||||
import io.netris.model.SitesResponseOK;
|
||||
import io.netris.model.SubnetBody;
|
||||
import io.netris.model.VPCAdminTenant;
|
||||
import io.netris.model.VPCCreate;
|
||||
import io.netris.model.VPCListing;
|
||||
import io.netris.model.VPCResource;
|
||||
import io.netris.model.VPCResourceIpam;
|
||||
import io.netris.model.VPCResponseOK;
|
||||
import io.netris.model.VPCResponseObjectOK;
|
||||
import io.netris.model.VPCResponseResourceOK;
|
||||
import io.netris.model.VnetAddBody;
|
||||
import io.netris.model.VnetAddBodyDhcp;
|
||||
import io.netris.model.VnetAddBodyDhcpOptionSet;
|
||||
import io.netris.model.VnetAddBodyGateways;
|
||||
import io.netris.model.VnetAddBodyVpc;
|
||||
import io.netris.model.VnetResAddBody;
|
||||
import io.netris.model.response.AuthResponse;
|
||||
import io.netris.model.response.TenantResponse;
|
||||
import io.netris.model.response.TenantsResponse;
|
||||
import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
|
||||
import org.apache.cloudstack.resource.NetrisResourceObjectUtils;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class NetrisApiClientImpl implements NetrisApiClient {
|
||||
|
||||
|
|
@ -42,17 +71,52 @@ public class NetrisApiClientImpl implements NetrisApiClient {
|
|||
|
||||
private static ApiClient apiClient;
|
||||
|
||||
public NetrisApiClientImpl(String endpointBaseUrl, String username, String password) {
|
||||
private final int siteId;
|
||||
private final String siteName;
|
||||
private final int tenantId;
|
||||
private final String tenantName;
|
||||
|
||||
public NetrisApiClientImpl(String endpointBaseUrl, String username, String password, String siteName, String adminTenantName) {
|
||||
try {
|
||||
apiClient = new ApiClient(endpointBaseUrl, username, password, 1L);
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException(String.format("Error creating the Netris API Client for %s", endpointBaseUrl), e);
|
||||
}
|
||||
Pair<Integer, String> sitePair = getNetrisSitePair(siteName);
|
||||
Pair<Integer, String> tenantPair = getNetrisTenantPair(adminTenantName);
|
||||
this.siteId = sitePair.first();
|
||||
this.siteName = sitePair.second();
|
||||
this.tenantId = tenantPair.first();
|
||||
this.tenantName = tenantPair.second();
|
||||
}
|
||||
|
||||
private Pair<Integer, String> getNetrisSitePair(String siteName) {
|
||||
List<GetSiteBody> sites = listSites();
|
||||
if (CollectionUtils.isEmpty(sites)) {
|
||||
throw new CloudRuntimeException("There are no Netris sites, please check the Netris endpoint");
|
||||
}
|
||||
List<GetSiteBody> filteredSites = sites.stream().filter(x -> x.getName().equals(siteName)).collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(filteredSites)) {
|
||||
throw new CloudRuntimeException(String.format("Cannot find a site matching name %s on Netris, please check the Netris endpoint", siteName));
|
||||
}
|
||||
return new Pair<>(filteredSites.get(0).getId(), siteName);
|
||||
}
|
||||
|
||||
private Pair<Integer, String> getNetrisTenantPair(String adminTenantName) {
|
||||
List<TenantResponse> tenants = listTenants();
|
||||
if (CollectionUtils.isEmpty(tenants)) {
|
||||
throw new CloudRuntimeException("There are no Netris tenants, please check the Netris endpoint");
|
||||
}
|
||||
List<TenantResponse> filteredTenants = tenants.stream().filter(x -> x.getName().equals(adminTenantName)).collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(filteredTenants)) {
|
||||
throw new CloudRuntimeException(String.format("Cannot find a site matching name %s on Netris, please check the Netris endpoint", adminTenantName));
|
||||
}
|
||||
return new Pair<>(filteredTenants.get(0).getId().intValue(), adminTenantName);
|
||||
}
|
||||
|
||||
protected void logAndThrowException(String prefix, ApiException e) throws CloudRuntimeException {
|
||||
String msg = String.format("%s: (%s, %s, %s)", prefix, e.getCode(), e.getMessage(), e.getResponseBody());
|
||||
logger.error(msg);
|
||||
logger.error(msg, e);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
|
||||
|
|
@ -103,4 +167,264 @@ public class NetrisApiClientImpl implements NetrisApiClient {
|
|||
}
|
||||
return (response != null && response.getData() != null) ? response.getData().getData() : null;
|
||||
}
|
||||
|
||||
private VPCResponseObjectOK createVpcInternal(String vpcName, int adminTenantId, String adminTenantName) {
|
||||
VPCResponseObjectOK response;
|
||||
logger.debug(String.format("Creating Netris VPC %s", vpcName));
|
||||
try {
|
||||
VpcApi vpcApi = apiClient.getApiStubForMethod(VpcApi.class);
|
||||
VPCCreate body = new VPCCreate();
|
||||
body.setName(vpcName);
|
||||
VPCAdminTenant vpcAdminTenant = new VPCAdminTenant();
|
||||
vpcAdminTenant.setId(adminTenantId);
|
||||
vpcAdminTenant.name(adminTenantName);
|
||||
body.setAdminTenant(vpcAdminTenant);
|
||||
response = vpcApi.apiV2VpcPost(body);
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException("Error creating Netris VPC", e);
|
||||
return null;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private InlineResponse2004 createVpcAllocationInternal(VPCResponseObjectOK createdVpc, String cidr, int adminTenantId,
|
||||
String adminTenantName, String netrisIpamAllocationName) {
|
||||
logger.debug(String.format("Creating Netris VPC Allocation %s for VPC %s", cidr, createdVpc.getData().getName()));
|
||||
try {
|
||||
IpamApi ipamApi = apiClient.getApiStubForMethod(IpamApi.class);
|
||||
AllocationBody body = new AllocationBody();
|
||||
AllocationBodyVpc allocationBodyVpc = new AllocationBodyVpc();
|
||||
allocationBodyVpc.setId(createdVpc.getData().getId());
|
||||
allocationBodyVpc.setName(createdVpc.getData().getName());
|
||||
body.setVpc(allocationBodyVpc);
|
||||
body.setName(netrisIpamAllocationName);
|
||||
body.setPrefix(cidr);
|
||||
IpTreeAllocationTenant allocationTenant = new IpTreeAllocationTenant();
|
||||
allocationTenant.setId(new BigDecimal(adminTenantId));
|
||||
allocationTenant.setName(adminTenantName);
|
||||
body.setTenant(allocationTenant);
|
||||
return ipamApi.apiV2IpamAllocationPost(body);
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException(String.format("Error creating Netris Allocation %s for VPC %s", cidr, createdVpc.getData().getName()), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createVpc(CreateNetrisVpcCommand cmd) {
|
||||
String netrisVpcName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VPC);
|
||||
VPCResponseObjectOK createdVpc = createVpcInternal(netrisVpcName, tenantId, tenantName);
|
||||
if (createdVpc == null || !createdVpc.isIsSuccess()) {
|
||||
String reason = createdVpc == null ? "Empty response" : "Operation failed on Netris";
|
||||
logger.debug("The Netris VPC {} creation failed: {}", cmd.getName(), reason);
|
||||
return false;
|
||||
}
|
||||
|
||||
String netrisIpamAllocationName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.IPAM_ALLOCATION, cmd.getCidr());
|
||||
String vpcCidr = cmd.getCidr();
|
||||
InlineResponse2004 ipamResponse = createVpcAllocationInternal(createdVpc, vpcCidr, tenantId, tenantName, netrisIpamAllocationName);
|
||||
if (ipamResponse == null || !ipamResponse.isIsSuccess()) {
|
||||
String reason = ipamResponse == null ? "Empty response" : "Operation failed on Netris";
|
||||
logger.debug("The Netris Allocation {} for VPC {} creation failed: {}", vpcCidr, cmd.getName(), reason);
|
||||
return false;
|
||||
}
|
||||
logger.debug(String.format("Successfully created VPC %s and its IPAM Allocation %s on Netris", cmd.getName(), vpcCidr));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void deleteVpcIpamAllocationInternal(VPCListing vpcResource, String vpcCidr) {
|
||||
logger.debug(String.format("Deleting Netris VPC IPAM Allocation %s for VPC %s", vpcCidr, vpcResource.getName()));
|
||||
try {
|
||||
VpcApi vpcApi = apiClient.getApiStubForMethod(VpcApi.class);
|
||||
VPCResponseResourceOK vpcResourcesResponse = vpcApi.apiV2VpcVpcIdResourcesGet(vpcResource.getId());
|
||||
VPCResourceIpam vpcAllocationResource = getVpcAllocationResource(vpcResourcesResponse);
|
||||
IpamApi ipamApi = apiClient.getApiStubForMethod(IpamApi.class);
|
||||
logger.debug("Removing the IPAM allocation {} with ID {}", vpcAllocationResource.getName(), vpcAllocationResource.getId());
|
||||
ipamApi.apiV2IpamTypeIdDelete("allocation", vpcAllocationResource.getId());
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException(String.format("Error removing IPAM Allocation %s for VPC %s", vpcCidr, vpcResource.getName()), e);
|
||||
}
|
||||
}
|
||||
|
||||
private VPCResourceIpam getVpcAllocationResource(VPCResponseResourceOK vpcResourcesResponse) {
|
||||
VPCResource resource = vpcResourcesResponse.getData().get(0);
|
||||
List<VPCResourceIpam> vpcAllocations = resource.getAllocation();
|
||||
if (CollectionUtils.isNotEmpty(vpcAllocations)) {
|
||||
if (vpcAllocations.size() > 1) {
|
||||
logger.warn("Unexpected VPC allocations size {}, one expected", vpcAllocations.size());
|
||||
}
|
||||
return vpcAllocations.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private VPCListing getVpcByNameAndTenant(String vpcName) {
|
||||
try {
|
||||
List<VPCListing> vpcListings = listVPCs();
|
||||
List<VPCListing> vpcs = vpcListings.stream()
|
||||
.filter(x -> x.getName().equals(vpcName) && x.getAdminTenant().getId().equals(tenantId))
|
||||
.collect(Collectors.toList());
|
||||
return vpcs.get(0);
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException(String.format("Error getting VPC %s information: %s", vpcName, e.getMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
private VPCResponseObjectOK deleteVpcInternal(VPCListing vpcResource) {
|
||||
try {
|
||||
VpcApi vpcApi = apiClient.getApiStubForMethod(VpcApi.class);
|
||||
logger.debug("Removing the VPC {} with ID {}", vpcResource.getName(), vpcResource.getId());
|
||||
return vpcApi.apiV2VpcVpcIdDelete(vpcResource.getId());
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException(String.format("Error deleting VPC %s: %s", vpcResource.getName(), e.getResponseBody()), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteVpc(DeleteNetrisVpcCommand cmd) {
|
||||
String vpcName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VPC);
|
||||
VPCListing vpcResource = getVpcByNameAndTenant(vpcName);
|
||||
if (vpcResource == null) {
|
||||
logger.error(String.format("Could not find the Netris VPC resource with name %s and tenant ID %s", vpcName, tenantId));
|
||||
return false;
|
||||
}
|
||||
String vpcCidr = cmd.getCidr();
|
||||
deleteVpcIpamAllocationInternal(vpcResource, vpcCidr);
|
||||
VPCResponseObjectOK response = deleteVpcInternal(vpcResource);
|
||||
return response != null && response.isIsSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createVnet(CreateNetrisVnetCommand cmd) {
|
||||
String vpcName = cmd.getVpcName();
|
||||
Long vpcId = cmd.getVpcId();
|
||||
String networkName = cmd.getName();
|
||||
Long networkId = cmd.getId();
|
||||
String vnetCidr = cmd.getCidr();
|
||||
boolean isVpc = cmd.isVpc();
|
||||
|
||||
String suffix = String.format("%s-%s", vpcId, vpcName);
|
||||
String netrisVpcName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VPC, suffix);
|
||||
VPCListing associatedVpc = getVpcByNameAndTenant(netrisVpcName);
|
||||
if (associatedVpc == null) {
|
||||
logger.error(String.format("Failed to find Netris VPC with name: %s, to create the corresponding vNet for network %s", vpcName, networkName));
|
||||
return false;
|
||||
}
|
||||
|
||||
String vNetName;
|
||||
if (isVpc) {
|
||||
vNetName = String.format("V%s-N%s-%s", vpcId, networkId, networkName);
|
||||
} else {
|
||||
vNetName = String.format("N%s-%s", networkId, networkName);
|
||||
}
|
||||
String netrisVnetName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VNET, vNetName) ;
|
||||
String netrisSubnetName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.IPAM_SUBNET, vnetCidr) ;
|
||||
|
||||
InlineResponse2004 subnetResponse = createVpcSubnetInternal(associatedVpc, vNetName, vnetCidr, netrisSubnetName);
|
||||
if (subnetResponse == null || !subnetResponse.isIsSuccess()) {
|
||||
String reason = subnetResponse == null ? "Empty response" : "Operation failed on Netris";
|
||||
logger.debug("The Netris Subnet {} for VPC {} for network {} creation failed: {}", vnetCidr, vpcName, networkName, reason);
|
||||
return false;
|
||||
}
|
||||
logger.debug("Successfully created VPC {} and its IPAM Subnet {} on Netris", vpcName, vnetCidr);
|
||||
|
||||
VnetResAddBody vnetResponse = createVnetInternal(associatedVpc, netrisVnetName, vnetCidr);
|
||||
if (vnetResponse == null || !vnetResponse.isIsSuccess()) {
|
||||
String reason = vnetResponse == null ? "Empty response" : "Operation failed on Netris";
|
||||
logger.debug("The Netris vNet creation {} for VPC {} failed: {}", vNetName, vpcName, reason);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private InlineResponse2004 createVpcSubnetInternal(VPCListing associatedVpc, String vNetName, String vNetCidr, String netrisSubnetName) {
|
||||
logger.debug("Creating Netris VPC Subnet {} for VPC {} for vNet {}", vNetCidr, associatedVpc.getName(), vNetName);
|
||||
try {
|
||||
|
||||
SubnetBody subnetBody = new SubnetBody();
|
||||
subnetBody.setName(netrisSubnetName);
|
||||
|
||||
AllocationBodyVpc vpcAllocationBody = new AllocationBodyVpc();
|
||||
vpcAllocationBody.setName(associatedVpc.getName());
|
||||
vpcAllocationBody.setId(associatedVpc.getId());
|
||||
subnetBody.setVpc(vpcAllocationBody);
|
||||
|
||||
IpTreeAllocationTenant allocationTenant = new IpTreeAllocationTenant();
|
||||
allocationTenant.setId(new BigDecimal(tenantId));
|
||||
allocationTenant.setName(tenantName);
|
||||
subnetBody.setTenant(allocationTenant);
|
||||
|
||||
IpTreeSubnetSites subnetSites = new IpTreeSubnetSites();
|
||||
subnetSites.setId(new BigDecimal(siteId));
|
||||
subnetSites.setName(siteName);
|
||||
subnetBody.setSites(List.of(subnetSites));
|
||||
|
||||
subnetBody.setPurpose(SubnetBody.PurposeEnum.COMMON);
|
||||
subnetBody.setPrefix(vNetCidr);
|
||||
IpamApi ipamApi = apiClient.getApiStubForMethod(IpamApi.class);
|
||||
return ipamApi.apiV2IpamSubnetPost(subnetBody);
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException(String.format("Error creating Netris Subnet %s for VPC %s", vNetCidr, associatedVpc.getName()), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
VnetResAddBody createVnetInternal(VPCListing associatedVpc, String netrisVnetName, String vNetCidr) {
|
||||
logger.debug("Creating Netris VPC vNet {} for CIDR {}", netrisVnetName, vNetCidr);
|
||||
try {
|
||||
VnetAddBody vnetBody = new VnetAddBody();
|
||||
|
||||
vnetBody.setCustomAnycastMac("");
|
||||
|
||||
VnetAddBodyGateways gateways = new VnetAddBodyGateways();
|
||||
gateways.prefix(vNetCidr);
|
||||
gateways.setDhcpEnabled(false);
|
||||
VnetAddBodyDhcp dhcp = new VnetAddBodyDhcp();
|
||||
dhcp.setEnd("");
|
||||
dhcp.setStart("");
|
||||
dhcp.setOptionSet(new VnetAddBodyDhcpOptionSet());
|
||||
gateways.setDhcp(dhcp);
|
||||
List<VnetAddBodyGateways> gatewaysList = new ArrayList<>();
|
||||
gatewaysList.add(gateways);
|
||||
vnetBody.setGateways(gatewaysList);
|
||||
|
||||
vnetBody.setGuestTenants(new ArrayList<>());
|
||||
vnetBody.setL3vpn(false);
|
||||
vnetBody.setName(netrisVnetName);
|
||||
vnetBody.setNativeVlan(0);
|
||||
vnetBody.setPorts(new ArrayList<>());
|
||||
|
||||
IpTreeSubnetSites subnetSites = new IpTreeSubnetSites();
|
||||
subnetSites.setId(new BigDecimal(siteId));
|
||||
subnetSites.setName(siteName);
|
||||
List<IpTreeSubnetSites> subnetSitesList = new ArrayList<>();
|
||||
subnetSitesList.add(subnetSites);
|
||||
vnetBody.setSites(subnetSitesList);
|
||||
|
||||
vnetBody.setState(VnetAddBody.StateEnum.ACTIVE);
|
||||
|
||||
vnetBody.setTags(new ArrayList<>());
|
||||
|
||||
IpTreeAllocationTenant allocationTenant = new IpTreeAllocationTenant();
|
||||
allocationTenant.setId(new BigDecimal(tenantId));
|
||||
allocationTenant.setName(tenantName);
|
||||
vnetBody.setTenant(allocationTenant);
|
||||
|
||||
vnetBody.setVlan(0);
|
||||
vnetBody.setVlanAware(false);
|
||||
vnetBody.setVlans("");
|
||||
|
||||
VnetAddBodyVpc vpc = new VnetAddBodyVpc();
|
||||
vpc.setName(associatedVpc.getName());
|
||||
vpc.setId(associatedVpc.getId());
|
||||
vnetBody.setVpc(vpc);
|
||||
|
||||
VNetApi vnetApi = apiClient.getApiStubForMethod(VNetApi.class);
|
||||
return vnetApi.apiV2VnetPost(vnetBody);
|
||||
} catch (ApiException e) {
|
||||
logAndThrowException(String.format("Error creating Netris vNet %s for VPC %s", netrisVnetName, associatedVpc.getName()), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,350 @@
|
|||
// 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.agent.AgentManager;
|
||||
import com.cloud.agent.Listener;
|
||||
import com.cloud.agent.api.AgentControlAnswer;
|
||||
import com.cloud.agent.api.AgentControlCommand;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.ConnectionException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.network.IpAddress;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.PhysicalNetworkServiceProvider;
|
||||
import com.cloud.network.element.DhcpServiceProvider;
|
||||
import com.cloud.network.element.DnsServiceProvider;
|
||||
import com.cloud.network.element.VirtualRouterElement;
|
||||
import com.cloud.network.element.VpcProvider;
|
||||
import com.cloud.network.netris.NetrisService;
|
||||
import com.cloud.network.rules.LoadBalancerContainer;
|
||||
import com.cloud.network.vpc.NetworkACLItem;
|
||||
import com.cloud.network.vpc.PrivateGateway;
|
||||
import com.cloud.network.vpc.StaticRouteProfile;
|
||||
import com.cloud.network.vpc.Vpc;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resource.ResourceStateAdapter;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.resource.UnableDeleteHostException;
|
||||
import com.cloud.utils.component.AdapterBase;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.ReservationContext;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import org.apache.cloudstack.StartupNetrisCommand;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
public class NetrisElement extends AdapterBase implements DhcpServiceProvider, DnsServiceProvider, ResourceStateAdapter,
|
||||
Listener, VpcProvider {
|
||||
|
||||
@Inject
|
||||
NetworkModel networkModel;
|
||||
@Inject
|
||||
AgentManager agentManager;
|
||||
@Inject
|
||||
ResourceManager resourceManager;
|
||||
@Inject
|
||||
private NetrisService netrisService;
|
||||
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
||||
private final Map<Network.Service, Map<Network.Capability, String>> capabilities = initCapabilities();
|
||||
|
||||
private static Map<Network.Service, Map<Network.Capability, String>> initCapabilities() {
|
||||
Map<Network.Service, Map<Network.Capability, String>> capabilities = new HashMap<>();
|
||||
|
||||
Map<Network.Capability, String> dhcpCapabilities = Map.of(Network.Capability.DhcpAccrossMultipleSubnets, "true");
|
||||
capabilities.put(Network.Service.Dhcp, dhcpCapabilities);
|
||||
|
||||
Map<Network.Capability, String> dnsCapabilities = new HashMap<>();
|
||||
dnsCapabilities.put(Network.Capability.AllowDnsSuffixModification, "true");
|
||||
capabilities.put(Network.Service.Dns, dnsCapabilities);
|
||||
|
||||
capabilities.put(Network.Service.StaticNat, null);
|
||||
|
||||
// Set capabilities for LB service
|
||||
Map<Network.Capability, String> lbCapabilities = new HashMap<Network.Capability, String>();
|
||||
lbCapabilities.put(Network.Capability.SupportedLBAlgorithms, "roundrobin,leastconn");
|
||||
lbCapabilities.put(Network.Capability.SupportedLBIsolation, "dedicated");
|
||||
lbCapabilities.put(Network.Capability.SupportedProtocols, "tcp, udp");
|
||||
lbCapabilities.put(Network.Capability.SupportedStickinessMethods, VirtualRouterElement.getHAProxyStickinessCapability());
|
||||
lbCapabilities.put(Network.Capability.LbSchemes, String.join(",", LoadBalancerContainer.Scheme.Internal.name(), LoadBalancerContainer.Scheme.Public.name()));
|
||||
|
||||
capabilities.put(Network.Service.Lb, lbCapabilities);
|
||||
capabilities.put(Network.Service.PortForwarding, null);
|
||||
capabilities.put(Network.Service.NetworkACL, null);
|
||||
|
||||
Map<Network.Capability, String> firewallCapabilities = new HashMap<>();
|
||||
firewallCapabilities.put(Network.Capability.SupportedProtocols, "tcp,udp,icmp");
|
||||
firewallCapabilities.put(Network.Capability.SupportedEgressProtocols, "tcp,udp,icmp,all");
|
||||
firewallCapabilities.put(Network.Capability.MultipleIps, "true");
|
||||
firewallCapabilities.put(Network.Capability.TrafficStatistics, "per public ip");
|
||||
firewallCapabilities.put(Network.Capability.SupportedTrafficDirection, "ingress, egress");
|
||||
capabilities.put(Network.Service.Firewall, firewallCapabilities);
|
||||
|
||||
Map<Network.Capability, String> sourceNatCapabilities = new HashMap<>();
|
||||
sourceNatCapabilities.put(Network.Capability.RedundantRouter, "true");
|
||||
sourceNatCapabilities.put(Network.Capability.SupportedSourceNatTypes, "peraccount");
|
||||
capabilities.put(Network.Service.SourceNat, sourceNatCapabilities);
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processAnswers(long agentId, long seq, Answer[] answers) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processCommands(long agentId, long seq, Command[] commands) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processHostAdded(long hostId) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processDisconnect(long agentId, Status state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processHostAboutToBeRemoved(long hostId) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processHostRemoved(long hostId, long clusterId) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecurring() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeout() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processTimeout(long agentId, long seq) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean canHandle(Network network, Network.Service service) {
|
||||
logger.debug("Checking if Netris Element can handle service " + service.getName() + " on network "
|
||||
+ network.getDisplayText());
|
||||
|
||||
if (!networkModel.isProviderForNetwork(getProvider(), network.getId())) {
|
||||
logger.debug("Netris Element is not a provider for network " + network.getDisplayText());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configDhcpSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeDhcpSupportForSubnet(Network network) throws ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setExtraDhcpOptions(Network network, long nicId, Map<Integer, String> dhcpOptions) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile vmProfile) throws ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addDnsEntry(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configDnsSupportForSubnet(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeDnsSupportForSubnet(Network network) throws ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Network.Service, Map<Network.Capability, String>> getCapabilities() {
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Network.Provider getProvider() {
|
||||
return Network.Provider.Netris;
|
||||
}
|
||||
|
||||
@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 true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||
return canHandle(network, Network.Service.Connectivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady(PhysicalNetworkServiceProvider provider) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEnableIndividualServices() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyServicesCombination(Set<Network.Service> services) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details, List<String> hostTags) {
|
||||
if (!(startup[0] instanceof StartupNetrisCommand)) {
|
||||
return null;
|
||||
}
|
||||
host.setType(Host.Type.L2Networking);
|
||||
return host;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean implementVpc(Vpc vpc, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shutdownVpc(Vpc vpc, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||
long zoneId = vpc.getZoneId();
|
||||
long accountId = vpc.getAccountId();
|
||||
long domainId = vpc.getDomainId();
|
||||
return netrisService.deleteVpcResource(zoneId, accountId, domainId, vpc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createPrivateGateway(PrivateGateway gateway) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deletePrivateGateway(PrivateGateway privateGateway) throws ConcurrentOperationException, ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyStaticRoutes(Vpc vpc, List<StaticRouteProfile> routes) throws ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyACLItemsToPrivateGw(PrivateGateway gateway, List<? extends NetworkACLItem> rules) throws ResourceUnavailableException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
// 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.deploy.DeployDestination;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.NetworkMigrationResponder;
|
||||
import com.cloud.network.Networks;
|
||||
import com.cloud.network.PhysicalNetwork;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.network.dao.PhysicalNetworkVO;
|
||||
import com.cloud.network.guru.GuestNetworkGuru;
|
||||
import com.cloud.network.netris.NetrisService;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.ReservationContext;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
public class NetrisGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigrationResponder {
|
||||
|
||||
@Inject
|
||||
private NetrisService netrisService;
|
||||
|
||||
public NetrisGuestNetworkGuru() {
|
||||
super();
|
||||
_isolationMethods = new PhysicalNetwork.IsolationMethod[] {new PhysicalNetwork.IsolationMethod("Netris")};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(NetworkOffering offering, DataCenter.NetworkType networkType,
|
||||
PhysicalNetwork physicalNetwork) {
|
||||
return networkType == DataCenter.NetworkType.Advanced && isMyTrafficType(offering.getTrafficType())
|
||||
&& isMyIsolationMethod(physicalNetwork) && (NetworkOffering.NetworkMode.ROUTED.equals(offering.getNetworkMode())
|
||||
|| (networkOfferingServiceMapDao.isProviderForNetworkOffering(
|
||||
offering.getId(), Network.Provider.Netris) && NetworkOffering.NetworkMode.NATTED.equals(offering.getNetworkMode())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, String name, Long vpcId, Account owner) {
|
||||
PhysicalNetworkVO physnet = _physicalNetworkDao.findById(plan.getPhysicalNetworkId());
|
||||
DataCenter dc = _dcDao.findById(plan.getDataCenterId());
|
||||
|
||||
if (!canHandle(offering, dc.getNetworkType(), physnet)) {
|
||||
logger.debug("Refusing to design this network");
|
||||
return null;
|
||||
}
|
||||
|
||||
NetworkVO network = (NetworkVO) super.design(offering, plan, userSpecified, name, vpcId, owner);
|
||||
if (network == null) {
|
||||
return null;
|
||||
}
|
||||
network.setBroadcastDomainType(Networks.BroadcastDomainType.Netris);
|
||||
|
||||
if (userSpecified != null) {
|
||||
if ((userSpecified.getIp6Cidr() == null && userSpecified.getIp6Gateway() != null) || (
|
||||
userSpecified.getIp6Cidr() != null && userSpecified.getIp6Gateway() == null)) {
|
||||
throw new InvalidParameterValueException("cidrv6 and gatewayv6 must be specified together.");
|
||||
}
|
||||
|
||||
if (userSpecified.getIp6Cidr() != null) {
|
||||
network.setIp6Cidr(userSpecified.getIp6Cidr());
|
||||
network.setIp6Gateway(userSpecified.getIp6Gateway());
|
||||
}
|
||||
}
|
||||
|
||||
network.setBroadcastDomainType(Networks.BroadcastDomainType.Netris);
|
||||
network.setState(Network.State.Allocated);
|
||||
|
||||
NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(),
|
||||
network.getBroadcastDomainType(), network.getNetworkOfferingId(), Network.State.Implemented,
|
||||
network.getDataCenterId(), network.getPhysicalNetworkId(), offering.isRedundantRouter());
|
||||
implemented.setAccountId(owner.getAccountId());
|
||||
|
||||
if (network.getGateway() != null) {
|
||||
implemented.setGateway(network.getGateway());
|
||||
}
|
||||
|
||||
if (network.getCidr() != null) {
|
||||
implemented.setCidr(network.getCidr());
|
||||
}
|
||||
|
||||
if (vpcId != null) {
|
||||
implemented.setVpcId(vpcId);
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
implemented.setName(name);
|
||||
}
|
||||
implemented.setBroadcastUri(Networks.BroadcastDomainType.Netris.toUri("netris"));
|
||||
|
||||
return network;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup(Network network, long networkId) {
|
||||
try {
|
||||
NetworkVO designedNetwork = _networkDao.findById(networkId);
|
||||
long zoneId = network.getDataCenterId();
|
||||
DataCenter zone = _dcDao.findById(zoneId);
|
||||
if (isNull(zone)) {
|
||||
throw new CloudRuntimeException(String.format("Failed to find zone with id: %s", zoneId));
|
||||
}
|
||||
createNetrisVnet(designedNetwork, zone);
|
||||
} catch (Exception ex) {
|
||||
throw new CloudRuntimeException("unable to create Netris network " + network.getUuid() + "due to: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public void deallocate(Network config, NicProfile nic, VirtualMachineProfile vm) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Network implement(Network network, NetworkOffering offering, DeployDestination dest,
|
||||
ReservationContext context) {
|
||||
NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(),
|
||||
network.getBroadcastDomainType(), network.getNetworkOfferingId(), Network.State.Implemented,
|
||||
network.getDataCenterId(), network.getPhysicalNetworkId(), offering.isRedundantRouter());
|
||||
implemented.setAccountId(network.getAccountId());
|
||||
|
||||
if (network.getGateway() != null) {
|
||||
implemented.setGateway(network.getGateway());
|
||||
}
|
||||
|
||||
if (network.getCidr() != null) {
|
||||
implemented.setCidr(network.getCidr());
|
||||
}
|
||||
|
||||
if (network.getVpcId() != null) {
|
||||
implemented.setVpcId(network.getVpcId());
|
||||
}
|
||||
|
||||
if (network.getName() != null) {
|
||||
implemented.setName(network.getName());
|
||||
}
|
||||
implemented.setBroadcastUri(Networks.BroadcastDomainType.Netris.toUri("netris"));
|
||||
return implemented;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
|
||||
NicProfile nicProfile = super.allocate(network, nic, vm);
|
||||
if (vm.getType() != VirtualMachine.Type.DomainRouter) {
|
||||
return nicProfile;
|
||||
}
|
||||
|
||||
final DataCenter zone = _dcDao.findById(network.getDataCenterId());
|
||||
long zoneId = network.getDataCenterId();
|
||||
if (Objects.isNull(zone)) {
|
||||
String msg = String.format("Unable to find zone with id: %s", zoneId);
|
||||
logger.error(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
Account account = accountDao.findById(network.getAccountId());
|
||||
if (Objects.isNull(account)) {
|
||||
String msg = String.format("Unable to find account with id: %s", network.getAccountId());
|
||||
logger.error(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
VpcVO vpc = _vpcDao.findById(network.getVpcId());
|
||||
if (Objects.isNull(vpc)) {
|
||||
String msg = String.format("Unable to find VPC with id: %s, allocating for network %s", network.getVpcId(), network.getName());
|
||||
logger.debug(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);
|
||||
}
|
||||
|
||||
NetworkOfferingVO networkOfferingVO = networkOfferingDao.findById(network.getNetworkOfferingId());
|
||||
|
||||
if (isNull(network.getVpcId()) && networkOfferingVO.getNetworkMode().equals(NetworkOffering.NetworkMode.NATTED)) {
|
||||
// Netris Natted mode
|
||||
}
|
||||
|
||||
return nicProfile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prepareMigration(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollbackMigration(NicProfile nic, Network network, VirtualMachineProfile vm, ReservationContext src, ReservationContext dst) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitMigration(NicProfile nic, Network network, VirtualMachineProfile vm, ReservationContext src, ReservationContext dst) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public void createNetrisVnet(NetworkVO networkVO, DataCenter zone) {
|
||||
Account account = accountDao.findById(networkVO.getAccountId());
|
||||
if (isNull(account)) {
|
||||
throw new CloudRuntimeException(String.format("Unable to find account with id: %s", networkVO.getAccountId()));
|
||||
}
|
||||
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);
|
||||
}
|
||||
String vpcName = null;
|
||||
Long vpcId = null;
|
||||
if (nonNull(networkVO.getVpcId())) {
|
||||
VpcVO vpc = _vpcDao.findById(networkVO.getVpcId());
|
||||
if (isNull(vpc)) {
|
||||
throw new CloudRuntimeException(String.format("Failed to find VPC network with id: %s", networkVO.getVpcId()));
|
||||
}
|
||||
vpcName = vpc.getName();
|
||||
vpcId = vpc.getId();
|
||||
} else {
|
||||
logger.debug(String.format("Creating a Tier 1 Gateway for the network %s before creating the NSX segment", networkVO.getName()));
|
||||
long networkOfferingId = networkVO.getNetworkOfferingId();
|
||||
NetworkOfferingVO networkOfferingVO = networkOfferingDao.findById(networkOfferingId);
|
||||
boolean isSourceNatSupported = !NetworkOffering.NetworkMode.ROUTED.equals(networkOfferingVO.getNetworkMode()) &&
|
||||
networkOfferingServiceMapDao.areServicesSupportedByNetworkOffering(networkVO.getNetworkOfferingId(), Network.Service.SourceNat);
|
||||
boolean result = netrisService.createVpcResource(zone.getId(), networkVO.getAccountId(), networkVO.getDomainId(),
|
||||
networkVO.getId(), networkVO.getName(), isSourceNatSupported, networkVO.getCidr(), false);
|
||||
if (!result) {
|
||||
String msg = String.format("Error creating Netris VPC for the network: %s", networkVO.getName());
|
||||
logger.error(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
}
|
||||
boolean result = netrisService.createVnetResource(zone.getId(), account.getId(), domain.getId(), vpcName, vpcId, networkVO.getName(), networkVO.getId(), networkVO.getCidr());
|
||||
if (!result) {
|
||||
throw new CloudRuntimeException("Failed to create Netris vNet resource for network: " + networkVO.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,8 +18,15 @@ package org.apache.cloudstack.service;
|
|||
|
||||
import com.cloud.network.netris.NetrisProvider;
|
||||
import com.cloud.utils.component.PluggableService;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.api.command.AddNetrisProviderCmd;
|
||||
import org.apache.cloudstack.api.response.NetrisProviderResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface NetrisProviderService extends PluggableService {
|
||||
NetrisProvider addProvider(AddNetrisProviderCmd cmd);
|
||||
List<BaseResponse> listNetrisProviders(Long zoneId);
|
||||
boolean deleteNetrisProvider(Long providerId);
|
||||
NetrisProviderResponse createNetrisProviderResponse(NetrisProvider provider);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,17 +16,184 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.service;
|
||||
|
||||
import com.amazonaws.util.CollectionUtils;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.host.DetailVO;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.dao.HostDetailsDao;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Networks;
|
||||
import com.cloud.network.dao.NetrisProviderDao;
|
||||
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.element.NetrisProviderVO;
|
||||
import com.cloud.network.netris.NetrisProvider;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.api.command.AddNetrisProviderCmd;
|
||||
import org.apache.cloudstack.api.command.DeleteNetrisProviderCmd;
|
||||
import org.apache.cloudstack.api.command.ListNetrisProvidersCmd;
|
||||
import org.apache.cloudstack.api.response.NetrisProviderResponse;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.resource.NetrisResource;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class NetrisProviderServiceImpl implements NetrisProviderService {
|
||||
|
||||
@Inject
|
||||
DataCenterDao dataCenterDao;
|
||||
@Inject
|
||||
ResourceManager resourceManager;
|
||||
@Inject
|
||||
NetrisProviderDao netrisProviderDao;
|
||||
@Inject
|
||||
HostDetailsDao hostDetailsDao;
|
||||
@Inject
|
||||
PhysicalNetworkDao physicalNetworkDao;
|
||||
@Inject
|
||||
NetworkDao networkDao;
|
||||
|
||||
@Override
|
||||
public NetrisProvider addProvider(AddNetrisProviderCmd cmd) {
|
||||
return null;
|
||||
final Long zoneId = cmd.getZoneId();
|
||||
final String name = cmd.getName();
|
||||
final String hostname = cmd.getHostname();
|
||||
final String port = cmd.getPort();
|
||||
final String username = cmd.getUsername();
|
||||
final String password = cmd.getPassword();
|
||||
final String tenantName = cmd.getTenantName();
|
||||
final String siteName = cmd.getSiteName();
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("guid", UUID.randomUUID().toString());
|
||||
params.put("zoneId", zoneId.toString());
|
||||
params.put("name", name);
|
||||
params.put("hostname", hostname);
|
||||
params.put("port", port);
|
||||
params.put("username", username);
|
||||
params.put("password", password);
|
||||
params.put("siteName", siteName);
|
||||
params.put("tenantName", tenantName);
|
||||
|
||||
Map<String, Object> hostdetails = new HashMap<>(params);
|
||||
NetrisProvider netrisProvider;
|
||||
|
||||
NetrisResource netrisResource = new NetrisResource();
|
||||
try {
|
||||
netrisResource.configure(hostname, hostdetails);
|
||||
final Host host = resourceManager.addHost(zoneId, netrisResource, netrisResource.getType(), params);
|
||||
if (host != null) {
|
||||
netrisProvider = Transaction.execute((TransactionCallback<NetrisProviderVO>) status -> {
|
||||
NetrisProviderVO netrisProviderVO = new NetrisProviderVO.Builder()
|
||||
.setZoneId(zoneId)
|
||||
.setHostId(host.getId())
|
||||
.setName(name)
|
||||
.setPort(port)
|
||||
.setHostname(hostname)
|
||||
.setUsername(username)
|
||||
.setPassword(password)
|
||||
.setSiteName(siteName)
|
||||
.setTenantName(tenantName)
|
||||
.build();
|
||||
|
||||
netrisProviderDao.persist(netrisProviderVO);
|
||||
|
||||
DetailVO detail = new DetailVO(host.getId(), "netriscontrollerid",
|
||||
String.valueOf(netrisProviderVO.getId()));
|
||||
hostDetailsDao.persist(detail);
|
||||
|
||||
return netrisProviderVO;
|
||||
});
|
||||
} else {
|
||||
throw new CloudRuntimeException("Failed to add Netris controller due to internal error.");
|
||||
}
|
||||
} catch (ConfigurationException e) {
|
||||
throw new CloudRuntimeException(e.getMessage());
|
||||
}
|
||||
return netrisProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseResponse> listNetrisProviders(Long zoneId) {
|
||||
List<BaseResponse> netrisControllersResponseList = new ArrayList<>();
|
||||
if (zoneId != null) {
|
||||
NetrisProviderVO netrisProviderVO = netrisProviderDao.findByZoneId(zoneId);
|
||||
if (Objects.nonNull(netrisProviderVO)) {
|
||||
netrisControllersResponseList.add(createNetrisProviderResponse(netrisProviderVO));
|
||||
}
|
||||
} else {
|
||||
List<NetrisProviderVO> netrisProviderVOList = netrisProviderDao.listAll();
|
||||
for (NetrisProviderVO nsxProviderVO : netrisProviderVOList) {
|
||||
netrisControllersResponseList.add(createNetrisProviderResponse(nsxProviderVO));
|
||||
}
|
||||
}
|
||||
|
||||
return netrisControllersResponseList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteNetrisProvider(Long providerId) {
|
||||
NetrisProviderVO netrisProvider = netrisProviderDao.findById(providerId);
|
||||
if (Objects.isNull(netrisProvider)) {
|
||||
throw new InvalidParameterValueException(String.format("Failed to find Netris provider with id: %s", providerId));
|
||||
}
|
||||
Long zoneId = netrisProvider.getZoneId();
|
||||
// Find the physical network we work for
|
||||
List<PhysicalNetworkVO> physicalNetworks = physicalNetworkDao.listByZone(zoneId);
|
||||
for (PhysicalNetworkVO physicalNetwork : physicalNetworks) {
|
||||
List<NetworkVO> networkList = networkDao.listByPhysicalNetwork(physicalNetwork.getId());
|
||||
if (!CollectionUtils.isNullOrEmpty(networkList)) {
|
||||
validateNetworkState(networkList);
|
||||
}
|
||||
}
|
||||
netrisProviderDao.remove(providerId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetrisProviderResponse createNetrisProviderResponse(NetrisProvider provider) {
|
||||
DataCenterVO zone = dataCenterDao.findById(provider.getZoneId());
|
||||
if (Objects.isNull(zone)) {
|
||||
throw new CloudRuntimeException(String.format("Failed to find zone with id %s", provider.getZoneId()));
|
||||
}
|
||||
|
||||
NetrisProviderResponse response = new NetrisProviderResponse();
|
||||
response.setName(provider.getName());
|
||||
response.setUuid(provider.getUuid());
|
||||
response.setHostname(provider.getHostname());
|
||||
response.setPort(provider.getPort());
|
||||
response.setZoneId(zone.getUuid());
|
||||
response.setZoneName(zone.getName());
|
||||
response.setSiteName(provider.getSiteName());
|
||||
response.setTenantName(provider.getTenantName());
|
||||
response.setObjectName("netrisProvider");
|
||||
return response;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateNetworkState(List<NetworkVO> networkList) {
|
||||
for (NetworkVO network : networkList) {
|
||||
if (network.getBroadcastDomainType() == Networks.BroadcastDomainType.Netris &&
|
||||
((network.getState() != Network.State.Shutdown) && (network.getState() != Network.State.Destroy))) {
|
||||
throw new CloudRuntimeException("This Netris provider cannot be deleted as there are one or more logical networks provisioned by CloudStack on it.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -34,6 +201,8 @@ public class NetrisProviderServiceImpl implements NetrisProviderService {
|
|||
List<Class<?>> cmdList = new ArrayList<>();
|
||||
if (Boolean.TRUE.equals(NetworkOrchestrationService.NETRIS_ENABLED.value())) {
|
||||
cmdList.add(AddNetrisProviderCmd.class);
|
||||
cmdList.add(ListNetrisProvidersCmd.class);
|
||||
cmdList.add(DeleteNetrisProviderCmd.class);
|
||||
}
|
||||
return cmdList;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
// 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.VlanDetailsVO;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Networks;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.network.guru.PublicNetworkGuru;
|
||||
import com.cloud.network.netris.NetrisService;
|
||||
import com.cloud.network.vpc.VpcOffering;
|
||||
import com.cloud.network.vpc.VpcOfferingVO;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class NetrisPublicNetworkGuru extends PublicNetworkGuru {
|
||||
|
||||
@Inject
|
||||
private NetrisService netrisService;
|
||||
|
||||
public NetrisPublicNetworkGuru() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canHandle(NetworkOffering offering) {
|
||||
boolean isForNetris = networkModel.isProviderForNetworkOffering(Network.Provider.Netris, offering.getId());
|
||||
return isMyTrafficType(offering.getTrafficType()) && offering.isSystemOnly() && isForNetris;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Network design(NetworkOffering offering, DeploymentPlan plan, Network network, String name, Long vpcId, Account owner) {
|
||||
if (!canHandle(offering)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (offering.getTrafficType() == Networks.TrafficType.Public) {
|
||||
return new NetworkVO(offering.getTrafficType(), Networks.Mode.Static, network.getBroadcastDomainType(), offering.getId(), Network.State.Setup, plan.getDataCenterId(),
|
||||
plan.getPhysicalNetworkId(), offering.isRedundantRouter());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
logger.debug("Netris Public network guru: allocate");
|
||||
|
||||
IPAddressVO ipAddress = _ipAddressDao.findByIp(nic.getIPv4Address());
|
||||
if (ipAddress == null) {
|
||||
String err = String.format("Cannot find the IP address %s", nic.getIPv4Address());
|
||||
logger.error(err);
|
||||
throw new CloudRuntimeException(err);
|
||||
}
|
||||
Long vpcId = ipAddress.getVpcId();
|
||||
boolean isForVpc = vpcId != null;
|
||||
VpcVO vpc = vpcDao.findById(vpcId);
|
||||
if (vpc == null) {
|
||||
String err = String.format("Cannot find a VPC with ID %s", vpcId);
|
||||
logger.error(err);
|
||||
throw new CloudRuntimeException(err);
|
||||
}
|
||||
|
||||
// For NSX, use VR Public IP != Source NAT
|
||||
List<IPAddressVO> ips = _ipAddressDao.listByAssociatedVpc(vpc.getId(), true);
|
||||
if (CollectionUtils.isEmpty(ips)) {
|
||||
String err = String.format("Cannot find a source NAT IP for the VPC %s", vpc.getName());
|
||||
logger.error(err);
|
||||
throw new CloudRuntimeException(err);
|
||||
}
|
||||
|
||||
ips = ips.stream().filter(x -> !x.getAddress().addr().equals(nic.getIPv4Address())).collect(Collectors.toList());
|
||||
// Use Source NAT IP address from the Netris Public Range. Do not Use the VR Public IP address
|
||||
ipAddress = ips.get(0);
|
||||
if (ipAddress.isSourceNat() && !ipAddress.isForSystemVms()) {
|
||||
VlanDetailsVO detail = vlanDetailsDao.findDetail(ipAddress.getVlanId(), ApiConstants.NETRIS_DETAIL_KEY);
|
||||
if (detail != null && detail.getValue().equalsIgnoreCase("true")) {
|
||||
long accountId = vpc.getAccountId();
|
||||
long domainId = vpc.getDomainId();
|
||||
long dataCenterId = vpc.getZoneId();
|
||||
long resourceId = vpc.getId();
|
||||
Network.Service[] services = { Network.Service.SourceNat };
|
||||
long networkOfferingId = vpc.getVpcOfferingId();
|
||||
VpcOfferingVO vpcVO = vpcOfferingDao.findById(networkOfferingId);
|
||||
boolean sourceNatEnabled = !NetworkOffering.NetworkMode.ROUTED.equals(vpcVO.getNetworkMode()) &&
|
||||
vpcOfferingServiceMapDao.areServicesSupportedByVpcOffering(vpc.getVpcOfferingId(), services);
|
||||
|
||||
logger.info(String.format("Creating Netris VPC %s", vpc.getName()));
|
||||
boolean result = netrisService.createVpcResource(dataCenterId, accountId, domainId, resourceId, vpc.getName(), sourceNatEnabled, vpc.getCidr(), true);
|
||||
if (!result) {
|
||||
String msg = String.format("Error creating Netris VPC %s", vpc.getName());
|
||||
logger.error(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
|
||||
boolean hasNatSupport = false;
|
||||
VpcOffering vpcOffering = vpcOfferingDao.findById(vpc.getVpcOfferingId());
|
||||
hasNatSupport = NetworkOffering.NetworkMode.NATTED.equals(vpcOffering.getNetworkMode());
|
||||
|
||||
if (!hasNatSupport) {
|
||||
return nic;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nic;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
// 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.agent.AgentManager;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.network.dao.NetrisProviderDao;
|
||||
import com.cloud.network.element.NetrisProviderVO;
|
||||
import com.cloud.network.netris.NetrisService;
|
||||
import com.cloud.network.vpc.Vpc;
|
||||
import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
|
||||
import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
|
||||
import org.apache.cloudstack.agent.api.NetrisAnswer;
|
||||
import org.apache.cloudstack.agent.api.NetrisCommand;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Objects;
|
||||
|
||||
public class NetrisServiceImpl implements NetrisService, Configurable {
|
||||
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
||||
@Inject
|
||||
private NetrisProviderDao netrisProviderDao;
|
||||
@Inject
|
||||
private AgentManager agentMgr;
|
||||
|
||||
@Override
|
||||
public String getConfigComponentName() {
|
||||
return NetrisService.class.getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey[0];
|
||||
}
|
||||
|
||||
private NetrisProviderVO getZoneNetrisProvider(long zoneId) {
|
||||
NetrisProviderVO netrisProviderVO = netrisProviderDao.findByZoneId(zoneId);
|
||||
if (netrisProviderVO == null) {
|
||||
logger.error("No Netris controller was found!");
|
||||
throw new InvalidParameterValueException("Failed to find a Netris controller");
|
||||
}
|
||||
return netrisProviderVO;
|
||||
}
|
||||
|
||||
private NetrisAnswer sendNetrisCommand(NetrisCommand cmd, long zoneId) {
|
||||
NetrisProviderVO netrisProviderVO = getZoneNetrisProvider(zoneId);
|
||||
Answer answer = agentMgr.easySend(netrisProviderVO.getHostId(), cmd);
|
||||
if (answer == null || !answer.getResult()) {
|
||||
logger.error("Netris API Command failed");
|
||||
throw new InvalidParameterValueException("Failed API call to Netris controller");
|
||||
}
|
||||
return (NetrisAnswer) answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createVpcResource(long zoneId, long accountId, long domainId, Long vpcId, String vpcName, boolean sourceNatEnabled, String cidr, boolean isVpc) {
|
||||
CreateNetrisVpcCommand cmd = new CreateNetrisVpcCommand(zoneId, accountId, domainId, vpcName, cidr, vpcId, isVpc);
|
||||
NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
|
||||
return answer.getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteVpcResource(long zoneId, long accountId, long domainId, Vpc vpc) {
|
||||
DeleteNetrisVpcCommand cmd = new DeleteNetrisVpcCommand(zoneId, accountId, domainId, vpc.getName(), vpc.getCidr(), vpc.getId(), true);
|
||||
NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
|
||||
return answer.getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr) {
|
||||
CreateNetrisVnetCommand cmd = new CreateNetrisVnetCommand(zoneId, accountId, domainId, vpcName, vpcId, networkName, networkId, cidr, !Objects.isNull(vpcId));
|
||||
NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
|
||||
return answer.getResult();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<bean id="netrisService" class="org.apache.cloudstack.service.NetrisServiceImpl"/>
|
||||
|
||||
</beans>
|
||||
|
|
@ -25,6 +25,17 @@
|
|||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
<bean id="Netris" class="org.apache.cloudstack.service.NetrisElement">
|
||||
<property name="name" value="Netris"/>
|
||||
</bean>
|
||||
|
||||
<bean id="netrisGuestNetworkGuru" class="org.apache.cloudstack.service.NetrisGuestNetworkGuru">
|
||||
<property name="name" value="NetrisGuestNetworkGuru" />
|
||||
</bean>
|
||||
<bean id="NetrisPublicNetworkGuru" class="org.apache.cloudstack.service.NetrisPublicNetworkGuru">
|
||||
<property name="name" value="NetrisPublicNetworkGuru" />
|
||||
</bean>
|
||||
|
||||
<bean id="netrisProviderService" class="org.apache.cloudstack.service.NetrisProviderServiceImpl"/>
|
||||
|
||||
</beans>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
// 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 org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
|
||||
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class NetrisResourceObjectUtilsTest {
|
||||
|
||||
private static final long zoneId = 1;
|
||||
private static final long accountId = 2;
|
||||
private static final long domainId = 2;
|
||||
|
||||
private static final long vpcId = 10;
|
||||
private static final String vpcName = "testVpc";
|
||||
private static final String vpcCidr = "10.10.0.0/16";
|
||||
|
||||
@Test
|
||||
public void testCreateVpcName() {
|
||||
CreateNetrisVpcCommand cmd = new CreateNetrisVpcCommand(zoneId, accountId, domainId, vpcName, vpcCidr, vpcId, true);
|
||||
String netrisVpcName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VPC);
|
||||
String expectedNetrisVpcName = String.format("D%s-A%s-Z%s-V%s-%s", domainId, accountId, zoneId, vpcId, vpcName);
|
||||
Assert.assertEquals(expectedNetrisVpcName, netrisVpcName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateVpcIpamAllocationName() {
|
||||
CreateNetrisVpcCommand cmd = new CreateNetrisVpcCommand(zoneId, accountId, domainId, vpcName, vpcCidr, vpcId, true);
|
||||
String ipamAllocationName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.IPAM_ALLOCATION, vpcCidr);
|
||||
String expectedNetrisVpcName = String.format("D%s-A%s-Z%s-V%s-%s", domainId, accountId, zoneId, vpcId, vpcCidr);
|
||||
Assert.assertEquals(expectedNetrisVpcName, ipamAllocationName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteVpcName() {
|
||||
DeleteNetrisVpcCommand cmd = new DeleteNetrisVpcCommand(zoneId, accountId, domainId, vpcName, vpcCidr, vpcId, true);
|
||||
String netrisVpcName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VPC);
|
||||
String expectedNetrisVpcName = String.format("D%s-A%s-Z%s-V%s-%s", domainId, accountId, zoneId, vpcId, vpcName);
|
||||
Assert.assertEquals(expectedNetrisVpcName, netrisVpcName);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,8 +30,10 @@ public class NetrisApiClientImplTest {
|
|||
private static final String endpointUrl = "https://shapeblue-ctl.netris.dev";
|
||||
private static final String username = "netris";
|
||||
private static final String password = "qHHa$CZ2oJv*@!7mwoSR";
|
||||
private static final String siteName = "Datacenter-1";
|
||||
private static final String adminTenantName = "Admin";
|
||||
|
||||
private static final NetrisApiClientImpl client = new NetrisApiClientImpl(endpointUrl, username, password);
|
||||
private static final NetrisApiClientImpl client = new NetrisApiClientImpl(endpointUrl, username, password, siteName, adminTenantName);
|
||||
|
||||
@Test
|
||||
public void testNetrisAuthStatus() {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ public class DeleteNsxControllerCmd extends BaseCmd {
|
|||
|
||||
@Inject
|
||||
protected NsxProviderService nsxProviderService;
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import com.cloud.dc.DataCenter;
|
|||
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;
|
||||
|
|
@ -40,9 +39,7 @@ import com.cloud.network.guru.GuestNetworkGuru;
|
|||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.NicProfile;
|
||||
|
|
@ -67,15 +64,9 @@ import java.util.Objects;
|
|||
public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigrationResponder {
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
||||
@Inject
|
||||
NetworkOfferingServiceMapDao networkOfferingServiceMapDao;
|
||||
@Inject
|
||||
NsxControllerUtils nsxControllerUtils;
|
||||
@Inject
|
||||
AccountDao accountDao;
|
||||
@Inject
|
||||
DomainDao domainDao;
|
||||
@Inject
|
||||
NetworkModel networkModel;
|
||||
|
||||
public NsxGuestNetworkGuru() {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package org.apache.cloudstack.service;
|
||||
|
||||
import com.cloud.dc.VlanDetailsVO;
|
||||
import com.cloud.dc.dao.VlanDetailsDao;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
|
|
@ -31,11 +30,7 @@ import com.cloud.network.guru.PublicNetworkGuru;
|
|||
import com.cloud.network.vpc.VpcOffering;
|
||||
import com.cloud.network.vpc.VpcOfferingVO;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.network.vpc.dao.VpcDao;
|
||||
import com.cloud.network.vpc.dao.VpcOfferingDao;
|
||||
import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.NicProfile;
|
||||
|
|
@ -55,20 +50,10 @@ import java.util.stream.Collectors;
|
|||
|
||||
public class NsxPublicNetworkGuru extends PublicNetworkGuru {
|
||||
|
||||
@Inject
|
||||
private VlanDetailsDao vlanDetailsDao;
|
||||
@Inject
|
||||
private VpcDao vpcDao;
|
||||
@Inject
|
||||
private VpcOfferingServiceMapDao vpcOfferingServiceMapDao;
|
||||
@Inject
|
||||
private NsxControllerUtils nsxControllerUtils;
|
||||
@Inject
|
||||
private NsxService nsxService;
|
||||
@Inject
|
||||
private VpcOfferingDao vpcOfferingDao;
|
||||
@Inject
|
||||
private NetworkOfferingDao offeringDao;
|
||||
|
||||
protected Logger logger = LogManager.getLogger(getClass());
|
||||
|
||||
|
|
@ -78,7 +63,8 @@ public class NsxPublicNetworkGuru extends PublicNetworkGuru {
|
|||
|
||||
@Override
|
||||
protected boolean canHandle(NetworkOffering offering) {
|
||||
return isMyTrafficType(offering.getTrafficType()) && offering.isSystemOnly() && offering.isForNsx();
|
||||
boolean isForNsx = networkModel.isProviderForNetworkOffering(Network.Provider.Nsx, offering.getId());
|
||||
return isMyTrafficType(offering.getTrafficType()) && offering.isSystemOnly() && isForNsx;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ import com.cloud.deploy.DeploymentPlan;
|
|||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.Networks;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.guru.PublicNetworkGuru;
|
||||
import com.cloud.network.vpc.VpcOfferingVO;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.network.vpc.dao.VpcDao;
|
||||
|
|
@ -56,6 +56,7 @@ import static org.mockito.ArgumentMatchers.any;
|
|||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
|
@ -80,23 +81,26 @@ public class NsxPublicNetworkGuruTest {
|
|||
VpcOfferingDao vpcOfferingDao;
|
||||
@Mock
|
||||
NsxControllerUtils nsxControllerUtils;
|
||||
@Mock
|
||||
NetworkModel networkModel;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
guru = new NsxPublicNetworkGuru();
|
||||
|
||||
ReflectionTestUtils.setField((PublicNetworkGuru) guru, "_ipAddressDao", ipAddressDao);
|
||||
ReflectionTestUtils.setField(guru, "_ipAddressDao", ipAddressDao);
|
||||
ReflectionTestUtils.setField(guru, "vpcDao", vpcDao);
|
||||
ReflectionTestUtils.setField(guru, "vlanDetailsDao", vlanDetailsDao);
|
||||
ReflectionTestUtils.setField(guru, "vpcOfferingServiceMapDao", vpcOfferingServiceMapDao);
|
||||
ReflectionTestUtils.setField(guru, "nsxService", nsxService);
|
||||
ReflectionTestUtils.setField(guru, "vpcOfferingDao", vpcOfferingDao);
|
||||
ReflectionTestUtils.setField(guru, "nsxControllerUtils", nsxControllerUtils);
|
||||
ReflectionTestUtils.setField(guru, "networkModel", networkModel);
|
||||
|
||||
offering = Mockito.mock(NetworkOffering.class);
|
||||
when(offering.getTrafficType()).thenReturn(Networks.TrafficType.Public);
|
||||
when(offering.isForNsx()).thenReturn(true);
|
||||
when(offering.isSystemOnly()).thenReturn(true);
|
||||
when(networkModel.isProviderForNetworkOffering(eq(Network.Provider.Nsx), anyLong())).thenReturn(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -165,7 +165,6 @@ public class ConfigTungstenFabricServiceCmd extends BaseCmd {
|
|||
"Default offering for Tungsten-Fabric Network", Networks.TrafficType.Guest, false, false,
|
||||
null, null, true, NetworkOffering.Availability.Optional, null, Network.GuestType.Isolated,
|
||||
false, false, false, false, true, false);
|
||||
networkOfferingVO.setForTungsten(true);
|
||||
networkOfferingVO.setState(NetworkOffering.State.Enabled);
|
||||
networkOfferingDao.persist(networkOfferingVO);
|
||||
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@
|
|||
<module>hypervisors/vmware</module>
|
||||
<module>network-elements/cisco-vnmc</module>
|
||||
<module>network-elements/nsx</module>
|
||||
<module>network-elements/netris</module>
|
||||
<module>network-elements/juniper-contrail</module>
|
||||
<module>network-elements/tungsten</module>
|
||||
</modules>
|
||||
|
|
|
|||
2
pom.xml
2
pom.xml
|
|
@ -142,7 +142,7 @@
|
|||
<cs.gmavenplus.version>3.0.2</cs.gmavenplus.version>
|
||||
<cs.google-http-client>1.42.3</cs.google-http-client>
|
||||
<cs.groovy.version>2.4.17</cs.groovy.version>
|
||||
<cs.gson.version>1.7.2</cs.gson.version>
|
||||
<cs.gson.version>2.10.1</cs.gson.version>
|
||||
<cs.guava.version>31.1-jre</cs.guava.version>
|
||||
<cs.httpclient.version>4.5.14</cs.httpclient.version>
|
||||
<cs.httpcore.version>4.4.16</cs.httpcore.version>
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import javax.inject.Inject;
|
|||
|
||||
import com.cloud.bgp.ASNumber;
|
||||
import com.cloud.bgp.ASNumberRange;
|
||||
import com.cloud.configuration.ConfigurationService;
|
||||
import com.cloud.dc.ASNumberRangeVO;
|
||||
import com.cloud.dc.ASNumberVO;
|
||||
import com.cloud.dc.VlanDetailsVO;
|
||||
|
|
@ -997,8 +998,7 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
}
|
||||
}
|
||||
vlanResponse.setForSystemVms(isForSystemVms(vlan.getId()));
|
||||
VlanDetailsVO vlanDetail = vlanDetailsDao.findDetail(vlan.getId(), ApiConstants.NSX_DETAIL_KEY);
|
||||
vlanResponse.setForNsx(Objects.nonNull(vlanDetail) && vlanDetail.getValue().equals("true"));
|
||||
vlanResponse.setProvider(getProviderFromVlanDetailKey(vlan));
|
||||
vlanResponse.setObjectName("vlan");
|
||||
return vlanResponse;
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
|
|
@ -1006,6 +1006,15 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
private String getProviderFromVlanDetailKey(Vlan vlan) {
|
||||
for (Map.Entry<String, String> entry : ConfigurationService.ProviderDetailKeyMap.entrySet()) {
|
||||
VlanDetailsVO vlanDetail = vlanDetailsDao.findDetail(vlan.getId(), entry.getValue());
|
||||
if (Objects.nonNull(vlanDetail) && "true".equals(vlanDetail.getValue())) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Return true if vlan IP range is dedicated for system vms (SSVM and CPVM), false if not
|
||||
* @param vlanId vlan id
|
||||
|
|
@ -2414,8 +2423,8 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
serviceResponses.add(svcRsp);
|
||||
}
|
||||
response.setForVpc(_configMgr.isOfferingForVpc(offering));
|
||||
response.setForTungsten(offering.isForTungsten());
|
||||
response.setForNsx(offering.isForNsx());
|
||||
response.setForTungsten(_ntwkModel.isProviderForNetworkOffering(Provider.Tungsten, offering.getId()));
|
||||
response.setForNsx(_ntwkModel.isProviderForNetworkOffering(Provider.Nsx, offering.getId()));
|
||||
if (offering.getNetworkMode() != null) {
|
||||
response.setNetworkMode(offering.getNetworkMode().name());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,10 @@ import javax.inject.Inject;
|
|||
import com.cloud.cpu.CPU;
|
||||
import com.cloud.dc.ASNumberRangeVO;
|
||||
import com.cloud.dc.dao.ASNumberRangeDao;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.dao.NetrisProviderDao;
|
||||
import com.cloud.network.dao.NsxProviderDao;
|
||||
import com.cloud.network.element.NetrisProviderVO;
|
||||
import com.cloud.network.element.NsxProviderVO;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
|
|
@ -62,6 +65,8 @@ public class DataCenterJoinDaoImpl extends GenericDaoBase<DataCenterJoinVO, Long
|
|||
@Inject
|
||||
private NsxProviderDao nsxProviderDao;
|
||||
@Inject
|
||||
private NetrisProviderDao netrisProviderDao;
|
||||
@Inject
|
||||
private ASNumberRangeDao asNumberRangeDao;
|
||||
|
||||
protected DataCenterJoinDaoImpl() {
|
||||
|
|
@ -129,10 +134,7 @@ public class DataCenterJoinDaoImpl extends GenericDaoBase<DataCenterJoinVO, Long
|
|||
}
|
||||
}
|
||||
|
||||
NsxProviderVO nsxProviderVO = nsxProviderDao.findByZoneId(dataCenter.getId());
|
||||
if (Objects.nonNull(nsxProviderVO)) {
|
||||
zoneResponse.setNsxEnabled(true);
|
||||
}
|
||||
setExternalNetworkProviderUsedByZone(zoneResponse, dataCenter.getId());
|
||||
|
||||
List<CPU.CPUArch> clusterArchs = ApiDBUtils.listZoneClustersArchs(dataCenter.getId());
|
||||
zoneResponse.setMultiArch(CollectionUtils.isNotEmpty(clusterArchs) && clusterArchs.size() > 1);
|
||||
|
|
@ -152,6 +154,19 @@ public class DataCenterJoinDaoImpl extends GenericDaoBase<DataCenterJoinVO, Long
|
|||
return zoneResponse;
|
||||
}
|
||||
|
||||
private void setExternalNetworkProviderUsedByZone(ZoneResponse zoneResponse, Long zoneId) {
|
||||
NsxProviderVO nsxProviderVO = nsxProviderDao.findByZoneId(zoneId);
|
||||
if (Objects.nonNull(nsxProviderVO)) {
|
||||
zoneResponse.setNsxEnabled(true);
|
||||
zoneResponse.setProvider(Network.Provider.Nsx.getName());
|
||||
}
|
||||
|
||||
NetrisProviderVO netrisProviderVO = netrisProviderDao.findByZoneId(zoneId);
|
||||
if (Objects.nonNull(netrisProviderVO)) {
|
||||
zoneResponse.setProvider(Network.Provider.Netris.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataCenterJoinVO newDataCenterView(DataCenter dataCenter) {
|
||||
SearchCriteria<DataCenterJoinVO> sc = dofIdSearch.create();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ package com.cloud.api.query.dao;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
|
||||
import org.apache.cloudstack.api.response.VpcOfferingResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
|
@ -29,8 +31,13 @@ import com.cloud.utils.db.SearchBuilder;
|
|||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class VpcOfferingJoinDaoImpl extends GenericDaoBase<VpcOfferingJoinVO, Long> implements VpcOfferingJoinDao {
|
||||
|
||||
@Inject
|
||||
private VpcOfferingServiceMapDao vpcOfferingServiceMapDao;
|
||||
|
||||
private SearchBuilder<VpcOfferingJoinVO> sofIdSearch;
|
||||
|
||||
protected VpcOfferingJoinDaoImpl() {
|
||||
|
|
@ -76,7 +83,7 @@ public class VpcOfferingJoinDaoImpl extends GenericDaoBase<VpcOfferingJoinVO, Lo
|
|||
offeringResponse.setDomain(offeringJoinVO.getDomainPath());
|
||||
offeringResponse.setZoneId(offeringJoinVO.getZoneUuid());
|
||||
offeringResponse.setZone(offeringJoinVO.getZoneName());
|
||||
offeringResponse.setForNsx(offeringJoinVO.isForNsx());
|
||||
offeringResponse.setForNsx(vpcOfferingServiceMapDao.isProviderForVpcOffering(Network.Provider.Nsx, offeringJoinVO.getId()));
|
||||
if (offeringJoinVO.getNetworkMode() != null) {
|
||||
offeringResponse.setNetworkMode(offeringJoinVO.getNetworkMode().name());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,12 +154,6 @@ public class NetworkOfferingJoinVO extends BaseViewVO implements NetworkOffering
|
|||
@Column(name = "for_vpc")
|
||||
private boolean forVpc;
|
||||
|
||||
@Column(name = "for_tungsten")
|
||||
boolean forTungsten;
|
||||
|
||||
@Column(name = "for_nsx")
|
||||
boolean forNsx;
|
||||
|
||||
@Column(name = "network_mode")
|
||||
NetworkMode networkMode;
|
||||
|
||||
|
|
@ -355,22 +349,8 @@ public class NetworkOfferingJoinVO extends BaseViewVO implements NetworkOffering
|
|||
return forVpc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForTungsten() {
|
||||
return forTungsten;
|
||||
}
|
||||
|
||||
public void setForVpc(boolean forVpc) { this.forVpc = forVpc; }
|
||||
|
||||
@Override
|
||||
public boolean isForNsx() {
|
||||
return forNsx;
|
||||
}
|
||||
|
||||
public void setForNsx(boolean forNsx) {
|
||||
this.forNsx = forNsx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkMode getNetworkMode() {
|
||||
return networkMode;
|
||||
|
|
|
|||
|
|
@ -78,9 +78,6 @@ public class VpcOfferingJoinVO implements VpcOffering {
|
|||
@Column(name = "sort_key")
|
||||
int sortKey;
|
||||
|
||||
@Column(name = "for_nsx")
|
||||
boolean forNsx = false;
|
||||
|
||||
@Column(name = "network_mode")
|
||||
NetworkOffering.NetworkMode networkMode;
|
||||
|
||||
|
|
@ -152,11 +149,6 @@ public class VpcOfferingJoinVO implements VpcOffering {
|
|||
return isDefault;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForNsx() {
|
||||
return forNsx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkOffering.NetworkMode getNetworkMode() {
|
||||
return networkMode;
|
||||
|
|
|
|||
|
|
@ -86,8 +86,8 @@ public class ApiResponseSerializer {
|
|||
|
||||
public static String toJSONSerializedString(ResponseObject result, StringBuilder log) {
|
||||
if (result != null && log != null) {
|
||||
Gson responseBuilder = ApiResponseGsonHelper.getBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();
|
||||
Gson logBuilder = ApiResponseGsonHelper.getLogBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();
|
||||
Gson responseBuilder = ApiResponseGsonHelper.getBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC).create();
|
||||
Gson logBuilder = ApiResponseGsonHelper.getLogBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC).create();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ import java.util.stream.Collectors;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.network.dao.NetrisProviderDao;
|
||||
import com.cloud.network.element.NetrisProviderVO;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupService;
|
||||
|
|
@ -470,6 +472,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
Ipv6Service ipv6Service;
|
||||
@Inject
|
||||
NsxProviderDao nsxProviderDao;
|
||||
@Inject
|
||||
NetrisProviderDao netrisProviderDao;
|
||||
|
||||
// FIXME - why don't we have interface for DataCenterLinkLocalIpAddressDao?
|
||||
@Inject
|
||||
|
|
@ -2613,10 +2617,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
final boolean success = _zoneDao.remove(zoneId);
|
||||
|
||||
if (success) {
|
||||
NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(zoneId);
|
||||
if (Objects.nonNull(nsxProvider)) {
|
||||
nsxProviderDao.remove(nsxProvider.getId());
|
||||
}
|
||||
deleteExternalProviderIfAny(zoneId);
|
||||
|
||||
// delete template refs for this zone
|
||||
templateZoneDao.deleteByZoneId(zoneId);
|
||||
|
|
@ -2642,6 +2643,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
});
|
||||
}
|
||||
|
||||
private void deleteExternalProviderIfAny(Long zoneId) {
|
||||
NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(zoneId);
|
||||
if (Objects.nonNull(nsxProvider)) {
|
||||
nsxProviderDao.remove(nsxProvider.getId());
|
||||
}
|
||||
NetrisProviderVO netrisProvider = netrisProviderDao.findByZoneId(zoneId);
|
||||
if (Objects.nonNull(netrisProvider)) {
|
||||
netrisProviderDao.remove(netrisProvider.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
@ActionEvent(eventType = EventTypes.EVENT_ZONE_EDIT, eventDescription = "editing zone", async = false)
|
||||
|
|
@ -4696,12 +4708,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
|
||||
return commitVlan(zoneId, podId, startIP, endIP, newVlanGateway, newVlanNetmask, vlanId, forVirtualNetwork, forSystemVms, networkId, physicalNetworkId, startIPv6, endIPv6, ip6Gateway,
|
||||
ip6Cidr, domain, vlanOwner, network, sameSubnet, cmd.isForNsx());
|
||||
ip6Cidr, domain, vlanOwner, network, sameSubnet, cmd.getProvider());
|
||||
}
|
||||
|
||||
private Vlan commitVlan(final Long zoneId, final Long podId, final String startIP, final String endIP, final String newVlanGatewayFinal, final String newVlanNetmaskFinal,
|
||||
final String vlanId, final Boolean forVirtualNetwork, final Boolean forSystemVms, final Long networkId, final Long physicalNetworkId, final String startIPv6, final String endIPv6,
|
||||
final String ip6Gateway, final String ip6Cidr, final Domain domain, final Account vlanOwner, final Network network, final Pair<Boolean, Pair<String, String>> sameSubnet, boolean forNsx) {
|
||||
final String ip6Gateway, final String ip6Cidr, final Domain domain, final Account vlanOwner, final Network network, final Pair<Boolean, Pair<String, String>> sameSubnet, Provider provider) {
|
||||
final GlobalLock commitVlanLock = GlobalLock.getInternLock("CommitVlan");
|
||||
commitVlanLock.lock(5);
|
||||
logger.debug("Acquiring lock for committing vlan");
|
||||
|
|
@ -4729,7 +4741,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
newVlanNetmask = sameSubnet.second().second();
|
||||
}
|
||||
final Vlan vlan = createVlanAndPublicIpRange(zoneId, networkId, physicalNetworkId, forVirtualNetwork, forSystemVms, podId, startIP, endIP, newVlanGateway, newVlanNetmask, vlanId,
|
||||
false, domain, vlanOwner, startIPv6, endIPv6, ip6Gateway, ip6Cidr, forNsx);
|
||||
false, domain, vlanOwner, startIPv6, endIPv6, ip6Gateway, ip6Cidr, provider);
|
||||
// create an entry in the nic_secondary table. This will be the new
|
||||
// gateway that will be configured on the corresponding routervm.
|
||||
return vlan;
|
||||
|
|
@ -4856,7 +4868,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
@Override
|
||||
@DB
|
||||
public Vlan createVlanAndPublicIpRange(final long zoneId, final long networkId, final long physicalNetworkId, final boolean forVirtualNetwork, final boolean forSystemVms, final Long podId, final String startIP, final String endIP,
|
||||
final String vlanGateway, final String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, final Account vlanOwner, final String startIPv6, final String endIPv6, final String vlanIp6Gateway, final String vlanIp6Cidr, boolean forNsx) {
|
||||
final String vlanGateway, final String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, final Account vlanOwner, final String startIPv6, final String endIPv6, final String vlanIp6Gateway, final String vlanIp6Cidr, Provider provider) {
|
||||
final Network network = _networkModel.getNetwork(networkId);
|
||||
|
||||
boolean ipv4 = false, ipv6 = false;
|
||||
|
|
@ -4906,6 +4918,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
// 1) if vlan is specified for the guest network range, it should be the
|
||||
// same as network's vlan
|
||||
// 2) if vlan is missing, default it to the guest network's vlan
|
||||
boolean forExternalProvider = ConfigurationService.IsIpRangeForProvider(provider);
|
||||
if (network.getTrafficType() == TrafficType.Guest) {
|
||||
String networkVlanId = null;
|
||||
boolean connectivityWithoutVlan = false;
|
||||
|
|
@ -4938,11 +4951,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
} else {
|
||||
vlanId = networkVlanId;
|
||||
}
|
||||
} else if (network.getTrafficType() == TrafficType.Public && vlanId == null && !forNsx) {
|
||||
} else if (network.getTrafficType() == TrafficType.Public && vlanId == null && !forExternalProvider) {
|
||||
throw new InvalidParameterValueException("Unable to determine vlan id or untagged vlan for public network");
|
||||
}
|
||||
|
||||
if (vlanId == null && !forNsx) {
|
||||
if (vlanId == null && !forExternalProvider) {
|
||||
vlanId = Vlan.UNTAGGED;
|
||||
}
|
||||
|
||||
|
|
@ -5039,7 +5052,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
if (isSharedNetworkWithoutSpecifyVlan) {
|
||||
bypassVlanOverlapCheck = true;
|
||||
}
|
||||
if (!bypassVlanOverlapCheck && !forNsx && !_zoneDao.findVnet(zoneId, physicalNetworkId, BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlanId))).isEmpty()) {
|
||||
if (!bypassVlanOverlapCheck && !forExternalProvider && !_zoneDao.findVnet(zoneId, physicalNetworkId, BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlanId))).isEmpty()) {
|
||||
throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone "
|
||||
+ zone.getName());
|
||||
}
|
||||
|
|
@ -5055,7 +5068,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
|
||||
// Everything was fine, so persist the VLAN
|
||||
final VlanVO vlan = commitVlanAndIpRange(zoneId, networkId, physicalNetworkId, podId, startIP, endIP, vlanGateway, vlanNetmask, vlanId, domain, vlanOwner, vlanIp6Gateway, vlanIp6Cidr,
|
||||
ipv4, zone, vlanType, ipv6Range, ipRange, forSystemVms, forNsx);
|
||||
ipv4, zone, vlanType, ipv6Range, ipRange, forSystemVms, provider);
|
||||
|
||||
return vlan;
|
||||
}
|
||||
|
|
@ -5126,14 +5139,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
|
||||
private VlanVO commitVlanAndIpRange(final long zoneId, final long networkId, final long physicalNetworkId, final Long podId, final String startIP, final String endIP,
|
||||
final String vlanGateway, final String vlanNetmask, final String vlanId, final Domain domain, final Account vlanOwner, final String vlanIp6Gateway, final String vlanIp6Cidr,
|
||||
final boolean ipv4, final DataCenterVO zone, final VlanType vlanType, final String ipv6Range, final String ipRange, final boolean forSystemVms, final boolean forNsx) {
|
||||
final boolean ipv4, final DataCenterVO zone, final VlanType vlanType, final String ipv6Range, final String ipRange, final boolean forSystemVms, final Provider provider) {
|
||||
return Transaction.execute(new TransactionCallback<VlanVO>() {
|
||||
@Override
|
||||
public VlanVO doInTransaction(final TransactionStatus status) {
|
||||
VlanVO vlan = new VlanVO(vlanType, vlanId, vlanGateway, vlanNetmask, zone.getId(), ipRange, networkId, physicalNetworkId, vlanIp6Gateway, vlanIp6Cidr, ipv6Range);
|
||||
logger.debug("Saving vlan range " + vlan);
|
||||
vlan = _vlanDao.persist(vlan);
|
||||
vlanDetailsDao.addDetail(vlan.getId(), ApiConstants.NSX_DETAIL_KEY, String.valueOf(forNsx), true);
|
||||
if (Objects.nonNull(provider)) {
|
||||
addProviderVlanDetailKey(vlan, provider);
|
||||
}
|
||||
|
||||
// IPv6 use a used ip map, is different from ipv4, no need to save
|
||||
// public ip range
|
||||
|
|
@ -5174,6 +5189,15 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
|
||||
}
|
||||
|
||||
private void addProviderVlanDetailKey(Vlan vlan, Provider provider) {
|
||||
vlanDetailsDao.addDetail(vlan.getId(), getProviderDetailKey(provider.getName()),
|
||||
String.valueOf(ConfigurationService.IsIpRangeForProvider(provider)), true);
|
||||
}
|
||||
|
||||
private String getProviderDetailKey(String providerName) {
|
||||
return ConfigurationService.ProviderDetailKeyMap.get(providerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vlan updateVlanAndPublicIpRange(UpdateVlanIpRangeCmd cmd) throws ConcurrentOperationException,
|
||||
ResourceUnavailableException,ResourceAllocationException {
|
||||
|
|
@ -6829,9 +6853,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
if (serviceOfferingId != null) {
|
||||
offeringFinal.setServiceOfferingId(serviceOfferingId);
|
||||
}
|
||||
|
||||
offeringFinal.setForTungsten(Objects.requireNonNullElse(forTungsten, false));
|
||||
offeringFinal.setForNsx(Objects.requireNonNullElse(forNsx, false));
|
||||
offeringFinal.setNetworkMode(networkMode);
|
||||
|
||||
if (enableOffering) {
|
||||
|
|
|
|||
|
|
@ -2046,7 +2046,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
|
|||
}
|
||||
|
||||
public static String logDeploymentWithoutException(VirtualMachine vm, DeploymentPlan plan, ExcludeList avoids, DeploymentPlanner planner) {
|
||||
return LogUtils.logGsonWithoutException("Trying to deploy VM [%s] and details: Plan [%s]; avoid list [%s] and planner: [%s].", vm, plan, avoids, planner);
|
||||
return LogUtils.logGsonWithoutException("Trying to deploy VM [%s] and details: Plan [%s]; avoid list [%s] and planner: [%s].", vm, plan, avoids, planner != null ? planner.getName() : null);
|
||||
}
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
|
|||
DomainManager _domainMgr;
|
||||
|
||||
@Inject
|
||||
NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
|
||||
protected NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
|
||||
@Inject
|
||||
PhysicalNetworkDao _physicalNetworkDao;
|
||||
@Inject
|
||||
|
|
@ -494,7 +494,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
|
|||
@Override
|
||||
public Map<Provider, ArrayList<PublicIpAddress>> getProviderToIpList(Network network, Map<PublicIpAddress, Set<Service>> ipToServices) {
|
||||
NetworkOffering offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
|
||||
if (!offering.isConserveMode() && !offering.isForNsx()) {
|
||||
boolean isForNsx = isProviderForNetworkOffering(Provider.Nsx, offering.getId());
|
||||
if (!offering.isConserveMode() && !isForNsx) {
|
||||
for (PublicIpAddress ip : ipToServices.keySet()) {
|
||||
Set<Service> services = new HashSet<Service>();
|
||||
services.addAll(ipToServices.get(ip));
|
||||
|
|
@ -1623,7 +1624,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
|
|||
if (!canIpUsedForService(publicIp, service, networkId)) {
|
||||
return false;
|
||||
}
|
||||
if (!offering.isConserveMode() && !offering.isForNsx()) {
|
||||
boolean isForNsx = isProviderForNetworkOffering(Provider.Nsx, offering.getId());
|
||||
if (!offering.isConserveMode() && !isForNsx) {
|
||||
return canIpUsedForNonConserveService(publicIp, service);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -2305,9 +2305,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
}
|
||||
|
||||
if (createVlan && network != null) {
|
||||
Provider networkProvider = getNetworkOfferingProvider(ntwkOff);
|
||||
// Create vlan ip range
|
||||
_configMgr.createVlanAndPublicIpRange(pNtwk.getDataCenterId(), network.getId(), physicalNetworkId, false, false, null, startIP, endIP, gateway, netmask, vlanId,
|
||||
bypassVlanOverlapCheck, null, null, startIPv6, endIPv6, ip6Gateway, ip6Cidr, ntwkOff.isForNsx());
|
||||
bypassVlanOverlapCheck, null, null, startIPv6, endIPv6, ip6Gateway, ip6Cidr, networkProvider);
|
||||
}
|
||||
if (associatedNetwork != null) {
|
||||
_networkDetailsDao.persist(new NetworkDetailVO(network.getId(), Network.AssociatedNetworkId, String.valueOf(associatedNetwork.getId()), true));
|
||||
|
|
@ -2333,6 +2334,15 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
}
|
||||
}
|
||||
|
||||
private Provider getNetworkOfferingProvider(NetworkOffering networkOffering) {
|
||||
if (_networkModel.isProviderForNetworkOffering(Provider.Nsx, networkOffering.getId())) {
|
||||
return Provider.Nsx;
|
||||
} else if (_networkModel.isProviderForNetworkOffering(Provider.Netris, networkOffering.getId())) {
|
||||
return Provider.Netris;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<? extends Network>, Integer> searchForNetworks(ListNetworksCmd cmd) {
|
||||
Long id = cmd.getId();
|
||||
|
|
@ -4236,6 +4246,13 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
logger.warn("Failed to add NSX provider to physical network due to:", ex.getMessage());
|
||||
}
|
||||
|
||||
// Add Netris provider
|
||||
try {
|
||||
addNetrisProviderToPhysicalNetwork(pNetwork.getId());
|
||||
} catch (Exception ex) {
|
||||
logger.warn("Failed to add Netris provider to physical network due to:", ex.getMessage());
|
||||
}
|
||||
|
||||
CallContext.current().putContextParameter(PhysicalNetwork.class, pNetwork.getUuid());
|
||||
|
||||
return pNetwork;
|
||||
|
|
@ -5646,6 +5663,22 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
return null;
|
||||
}
|
||||
|
||||
private PhysicalNetworkServiceProvider addNetrisProviderToPhysicalNetwork(long physicalNetworkId) {
|
||||
PhysicalNetworkVO pvo = _physicalNetworkDao.findById(physicalNetworkId);
|
||||
DataCenterVO dvo = _dcDao.findById(pvo.getDataCenterId());
|
||||
if (dvo.getNetworkType() == NetworkType.Advanced) {
|
||||
|
||||
Provider provider = Network.Provider.getProvider(Provider.Netris.getName());
|
||||
if (provider == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
addProviderToPhysicalNetwork(physicalNetworkId, Provider.Netris.getName(), null, null);
|
||||
enableProvider(Provider.Netris.getName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean isNetworkSystem(Network network) {
|
||||
NetworkOffering no = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId());
|
||||
if (no.isSystemOnly()) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ import java.util.Random;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
|
|
@ -121,6 +124,12 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur
|
|||
Ipv6AddressManager ipv6AddressManager;
|
||||
@Inject
|
||||
DomainRouterDao domainRouterDao;
|
||||
@Inject
|
||||
public NetworkOfferingServiceMapDao networkOfferingServiceMapDao;
|
||||
@Inject
|
||||
public AccountDao accountDao;
|
||||
@Inject
|
||||
public DomainDao domainDao;
|
||||
|
||||
Random _rand = new Random(System.currentTimeMillis());
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ package com.cloud.network.guru;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.dc.dao.VlanDetailsDao;
|
||||
import com.cloud.network.vpc.dao.VpcDao;
|
||||
import com.cloud.network.vpc.dao.VpcOfferingDao;
|
||||
import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
|
|
@ -74,7 +78,15 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru {
|
|||
@Inject
|
||||
Ipv6Service ipv6Service;
|
||||
@Inject
|
||||
NetworkModel networkModel;
|
||||
protected NetworkModel networkModel;
|
||||
@Inject
|
||||
protected VpcDao vpcDao;
|
||||
@Inject
|
||||
protected VlanDetailsDao vlanDetailsDao;
|
||||
@Inject
|
||||
protected VpcOfferingDao vpcOfferingDao;
|
||||
@Inject
|
||||
protected VpcOfferingServiceMapDao vpcOfferingServiceMapDao;
|
||||
|
||||
private static final TrafficType[] TrafficTypes = {TrafficType.Public};
|
||||
|
||||
|
|
|
|||
|
|
@ -866,7 +866,11 @@ public class CommandSetupHelper {
|
|||
String vlanTag = ipAddr.getVlanTag();
|
||||
String key = null;
|
||||
if (Objects.isNull(vlanTag)) {
|
||||
key = "nsx-" + ipAddr.getAddress().addr();
|
||||
if (Hypervisor.HypervisorType.VMware == router.getHypervisorType()) {
|
||||
key = "nsx-" + ipAddr.getAddress().addr();
|
||||
} else if (Hypervisor.HypervisorType.KVM == router.getHypervisorType()) {
|
||||
key = "netris-" + ipAddr.getAddress().addr();
|
||||
}
|
||||
} else {
|
||||
key = BroadcastDomainType.getValue(BroadcastDomainType.fromString(ipAddr.getVlanTag()));
|
||||
}
|
||||
|
|
@ -1215,7 +1219,8 @@ public class CommandSetupHelper {
|
|||
final SetupGuestNetworkCommand setupCmd = new SetupGuestNetworkCommand(dhcpRange, networkDomain, router.getIsRedundantRouter(), defaultDns1, defaultDns2, add, _itMgr.toNicTO(nicProfile,
|
||||
router.getHypervisorType()));
|
||||
|
||||
setupCmd.setVrGuestGateway(networkOfferingVO.isForNsx());
|
||||
boolean isForNsx = _networkModel.isProviderForNetworkOffering(Provider.Nsx, networkOfferingVO.getId());
|
||||
setupCmd.setVrGuestGateway(isForNsx);
|
||||
NicVO publicNic = _nicDao.findDefaultNicForVM(router.getId());
|
||||
if (publicNic != null) {
|
||||
updateSetupGuestNetworkCommandIpv6(setupCmd, network, publicNic, defaultIp6Dns1, defaultIp6Dns2);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@ import com.cloud.bgp.BGPService;
|
|||
import com.cloud.dc.ASNumberVO;
|
||||
import com.cloud.dc.dao.ASNumberDao;
|
||||
import com.cloud.dc.Vlan;
|
||||
import com.cloud.network.dao.NetrisProviderDao;
|
||||
import com.cloud.network.dao.NsxProviderDao;
|
||||
import com.cloud.network.element.NetrisProviderVO;
|
||||
import com.cloud.network.element.NsxProviderVO;
|
||||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.google.common.collect.Sets;
|
||||
|
|
@ -291,13 +293,15 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
@Inject
|
||||
private NsxProviderDao nsxProviderDao;
|
||||
@Inject
|
||||
private NetrisProviderDao netrisProviderDao;
|
||||
@Inject
|
||||
RoutedIpv4Manager routedIpv4Manager;
|
||||
|
||||
private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpcChecker"));
|
||||
private List<VpcProvider> vpcElements = null;
|
||||
private final List<Service> nonSupportedServices = Arrays.asList(Service.SecurityGroup, Service.Firewall);
|
||||
private final List<Provider> supportedProviders = Arrays.asList(Provider.VPCVirtualRouter, Provider.NiciraNvp, Provider.InternalLbVm, Provider.Netscaler,
|
||||
Provider.JuniperContrailVpcRouter, Provider.Ovs, Provider.BigSwitchBcf, Provider.ConfigDrive, Provider.Nsx);
|
||||
Provider.JuniperContrailVpcRouter, Provider.Ovs, Provider.BigSwitchBcf, Provider.ConfigDrive, Provider.Nsx, Provider.Netris);
|
||||
|
||||
int _cleanupInterval;
|
||||
int _maxNetworks;
|
||||
|
|
@ -353,7 +357,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
}
|
||||
createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap,
|
||||
true, State.Enabled, null, false,
|
||||
false, false, false, null, null, false);
|
||||
false, false, null, null, false);
|
||||
}
|
||||
|
||||
// configure default vpc offering with Netscaler as LB Provider
|
||||
|
|
@ -373,7 +377,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
}
|
||||
}
|
||||
createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName,
|
||||
svcProviderMap, false, State.Enabled, null, false, false, false, false, null, null, false);
|
||||
svcProviderMap, false, State.Enabled, null, false, false, false, null, null, false);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +398,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
}
|
||||
}
|
||||
createVpcOffering(VpcOffering.redundantVPCOfferingName, VpcOffering.redundantVPCOfferingName, svcProviderMap, true, State.Enabled,
|
||||
null, false, false, true, false, null, null, false);
|
||||
null, false, false, true, null, null, false);
|
||||
}
|
||||
|
||||
// configure default vpc offering with NSX as network service provider in NAT mode
|
||||
|
|
@ -411,7 +415,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
}
|
||||
}
|
||||
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.NetworkMode.NATTED, null, false);
|
||||
State.Enabled, null, false, false, false, NetworkOffering.NetworkMode.NATTED, null, false);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -429,7 +433,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
}
|
||||
}
|
||||
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.NetworkMode.ROUTED, null, false);
|
||||
State.Enabled, null, false, false, false, NetworkOffering.NetworkMode.ROUTED, null, false);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -447,7 +451,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
}
|
||||
}
|
||||
createVpcOffering(VpcOffering.DEFAULT_VPC_ROUTE_NETRIS_OFFERING_NAME, VpcOffering.DEFAULT_VPC_ROUTE_NETRIS_OFFERING_NAME, svcProviderMap, false,
|
||||
State.Enabled, null, false, false, false, true, NetworkOffering.NetworkMode.ROUTED, null, false);
|
||||
State.Enabled, null, false, false, false, NetworkOffering.NetworkMode.ROUTED, null, false);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -660,7 +664,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
final boolean offersRegionLevelVPC = isVpcOfferingForRegionLevelVpc(serviceCapabilityList);
|
||||
final boolean redundantRouter = isVpcOfferingRedundantRouter(serviceCapabilityList, redundantRouterService);
|
||||
final VpcOfferingVO offering = createVpcOffering(name, displayText, svcProviderMap, false, state, serviceOfferingId, supportsDistributedRouter, offersRegionLevelVPC,
|
||||
redundantRouter, forNsx, networkMode, routingMode, specifyAsNumber);
|
||||
redundantRouter, networkMode, routingMode, specifyAsNumber);
|
||||
|
||||
if (offering != null) {
|
||||
List<VpcOfferingDetailsVO> detailsVO = new ArrayList<>();
|
||||
|
|
@ -686,9 +690,9 @@ 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,
|
||||
protected VpcOfferingVO createVpcOffering(final String name, final String displayText, final Map<Service, Set<Provider>> svcProviderMap,
|
||||
final boolean isDefault, final State state, final Long serviceOfferingId, final boolean supportsDistributedRouter, final boolean offersRegionLevelVPC,
|
||||
final boolean redundantRouter, Boolean forNsx, NetworkOffering.NetworkMode networkMode, NetworkOffering.RoutingMode routingMode, boolean specifyAsNumber) {
|
||||
final boolean redundantRouter, NetworkOffering.NetworkMode networkMode, NetworkOffering.RoutingMode routingMode, boolean specifyAsNumber) {
|
||||
|
||||
return Transaction.execute(new TransactionCallback<VpcOfferingVO>() {
|
||||
@Override
|
||||
|
|
@ -699,7 +703,6 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
if (state != null) {
|
||||
offering.setState(state);
|
||||
}
|
||||
offering.setForNsx(forNsx);
|
||||
offering.setNetworkMode(networkMode);
|
||||
offering.setSpecifyAsNumber(specifyAsNumber);
|
||||
if (Objects.nonNull(routingMode)) {
|
||||
|
|
@ -1308,11 +1311,12 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
cmd.getIp6Dns2(), cmd.isDisplay(), cmd.getPublicMtu(), cmd.getCidrSize(), cmd.getAsNumber(), bgpPeerIds);
|
||||
|
||||
String sourceNatIP = cmd.getSourceNatIP();
|
||||
boolean forNsx = isVpcForNsx(vpc);
|
||||
boolean forNsx = isVpcForProvider(Provider.Nsx, vpc);
|
||||
boolean forNetris = isVpcForProvider(Provider.Netris, vpc);
|
||||
try {
|
||||
if (sourceNatIP != null || forNsx) {
|
||||
if (forNsx) {
|
||||
logger.info("Provided source NAT IP will be ignored in an NSX-enabled zone");
|
||||
if (sourceNatIP != null || forNsx || forNetris) {
|
||||
if (forNsx || forNetris) {
|
||||
logger.info("Provided source NAT IP will be ignored in an NSX-enabled or Netris-enabled zone");
|
||||
sourceNatIP = null;
|
||||
}
|
||||
logger.info(String.format("Trying to allocate the specified IP [%s] as the source NAT of VPC [%s].", sourceNatIP, vpc));
|
||||
|
|
@ -1341,15 +1345,11 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
return NetworkOffering.RoutingMode.Dynamic == vpcOffering.getRoutingMode();
|
||||
}
|
||||
|
||||
private boolean isVpcForNsx(Vpc vpc) {
|
||||
private boolean isVpcForProvider(Provider provider, Vpc vpc) {
|
||||
if (vpc == null) {
|
||||
return false;
|
||||
}
|
||||
VpcOfferingServiceMapVO mapVO = _vpcOffSvcMapDao.findByServiceProviderAndOfferingId(Service.SourceNat.getName(), Provider.Nsx.getName(), vpc.getVpcOfferingId());
|
||||
if (mapVO != null) {
|
||||
logger.debug(String.format("The VPC %s is NSX-based and supports the %s service", vpc.getName(), Service.SourceNat.getName()));
|
||||
}
|
||||
return mapVO != null;
|
||||
return _vpcOffSvcMapDao.isProviderForVpcOffering(provider, vpc.getVpcOfferingId());
|
||||
}
|
||||
|
||||
private void allocateSourceNatIp(Vpc vpc, String sourceNatIP) {
|
||||
|
|
@ -1357,9 +1357,12 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
DataCenter zone = _dcDao.findById(vpc.getZoneId());
|
||||
// reserve this ip and then
|
||||
try {
|
||||
if (isVpcForNsx(vpc) && org.apache.commons.lang3.StringUtils.isBlank(sourceNatIP)) {
|
||||
if (isVpcForProvider(Provider.Nsx, vpc) && org.apache.commons.lang3.StringUtils.isBlank(sourceNatIP)) {
|
||||
logger.debug(String.format("Reserving a source NAT IP for NSX VPC %s", vpc.getName()));
|
||||
sourceNatIP = reserveSourceNatIpForNsxVpc(account, zone);
|
||||
sourceNatIP = reserveSourceNatIpForProviderVpc(account, zone, Provider.Nsx);
|
||||
} else if (isVpcForProvider(Provider.Netris, vpc) && org.apache.commons.lang3.StringUtils.isBlank(sourceNatIP)) {
|
||||
logger.debug(String.format("Reserving a source NAT IP for Netris VPC %s", vpc.getName()));
|
||||
sourceNatIP = reserveSourceNatIpForProviderVpc(account, zone, Provider.Netris);
|
||||
}
|
||||
IpAddress ip = _ipAddrMgr.allocateIp(account, false, CallContext.current().getCallingAccount(), CallContext.current().getCallingUserId(), zone, null, sourceNatIP);
|
||||
this.associateIPToVpc(ip.getId(), vpc.getId());
|
||||
|
|
@ -1368,8 +1371,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
}
|
||||
}
|
||||
|
||||
private String reserveSourceNatIpForNsxVpc(Account account, DataCenter zone) throws ResourceAllocationException {
|
||||
IpAddress ipAddress = _ntwkSvc.reserveIpAddressWithVlanDetail(account, zone, true, ApiConstants.NSX_DETAIL_KEY);
|
||||
private String reserveSourceNatIpForProviderVpc(Account account, DataCenter zone, Provider provider) throws ResourceAllocationException {
|
||||
String detailKey = provider == Provider.Nsx ? ApiConstants.NSX_DETAIL_KEY : ApiConstants.NETRIS_DETAIL_KEY;
|
||||
IpAddress ipAddress = _ntwkSvc.reserveIpAddressWithVlanDetail(account, zone, true, detailKey);
|
||||
return ipAddress.getAddress().addr();
|
||||
}
|
||||
|
||||
|
|
@ -1571,7 +1575,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
}
|
||||
}
|
||||
return vpcDao.findById(vpcId);
|
||||
} else if (isVpcForNsx(vpcToUpdate)) {
|
||||
} else if (isVpcForProvider(Provider.Nsx, vpcToUpdate)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("no restart needed.");
|
||||
}
|
||||
|
|
@ -1590,7 +1594,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
if (! userIps.isEmpty()) {
|
||||
try {
|
||||
_ipAddrMgr.updateSourceNatIpAddress(requestedIp, userIps);
|
||||
if (isVpcForNsx(vpc)) {
|
||||
if (isVpcForProvider(Provider.Nsx, vpc) || isVpcForProvider(Provider.Netris, vpc)) {
|
||||
VpcProvider nsxElement = (VpcProvider) _ntwkModel.getElementImplementingProvider(Provider.Nsx.getName());
|
||||
if (nsxElement == null) {
|
||||
return true;
|
||||
|
|
@ -2053,7 +2057,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
|
||||
// 5) When aclId is provided, verify that ACLProvider is supported by
|
||||
// network offering
|
||||
if (aclId != null && !_ntwkModel.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.NetworkACL) && !guestNtwkOff.isForNsx()) {
|
||||
boolean isForNsx = _ntwkModel.isProviderForNetworkOffering(Provider.Nsx, guestNtwkOff.getId());
|
||||
if (aclId != null && !_ntwkModel.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.NetworkACL) && !isForNsx) {
|
||||
throw new InvalidParameterValueException("Cannot apply NetworkACL. Network Offering does not support NetworkACL service");
|
||||
}
|
||||
|
||||
|
|
@ -2071,7 +2076,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
|
||||
// 2) Only Isolated networks with Source nat service enabled can be
|
||||
// added to vpc
|
||||
if (!guestNtwkOff.isForNsx()
|
||||
boolean isForNsx = _ntwkModel.isProviderForNetworkOffering(Provider.Nsx, guestNtwkOff.getId());
|
||||
boolean isForNNetris = _ntwkModel.isProviderForNetworkOffering(Provider.Netris, guestNtwkOff.getId());
|
||||
if (!isForNsx && !isForNNetris
|
||||
&& !(guestNtwkOff.getGuestType() == GuestType.Isolated && (supportedSvcs.contains(Service.SourceNat) || supportedSvcs.contains(Service.Gateway)))) {
|
||||
|
||||
throw new InvalidParameterValueException("Only network offerings of type " + GuestType.Isolated + " with service " + Service.SourceNat.getName()
|
||||
|
|
@ -3196,7 +3203,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
|
||||
logger.debug("Associating ip " + ipToAssoc + " to vpc " + vpc);
|
||||
|
||||
final boolean isSourceNatFinal = isSrcNatIpRequired(vpc.getVpcOfferingId()) && getExistingSourceNatInVpc(vpc.getAccountId(), vpcId, false) == null;
|
||||
final boolean isSourceNatFinal = isSrcNatIpRequired(vpc.getVpcOfferingId()) && getExistingSourceNatInVpc(vpc.getAccountId(), vpcId, false, false) == null;
|
||||
try (CheckedReservation publicIpReservation = new CheckedReservation(owner, ResourceType.public_ip, 1l, reservationDao, _resourceLimitMgr)) {
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
|
|
@ -3298,7 +3305,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
return guestNetwork;
|
||||
}
|
||||
|
||||
protected IPAddressVO getExistingSourceNatInVpc(final long ownerId, final long vpcId, final boolean forNsx) {
|
||||
protected IPAddressVO getExistingSourceNatInVpc(final long ownerId, final long vpcId, final boolean forNsx, final boolean forNetris) {
|
||||
|
||||
final List<IPAddressVO> addrs = listPublicIpsAssignedToVpc(ownerId, true, vpcId);
|
||||
|
||||
|
|
@ -3309,7 +3316,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
// Account already has ip addresses
|
||||
for (final IPAddressVO addr : addrs) {
|
||||
if (addr.isSourceNat()) {
|
||||
if (!forNsx) {
|
||||
if (!forNsx && !forNetris) {
|
||||
sourceNatIp = addr;
|
||||
} else {
|
||||
if (addr.isForSystemVms()) {
|
||||
|
|
@ -3346,15 +3353,17 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
final long dcId = vpc.getZoneId();
|
||||
NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(dcId);
|
||||
boolean forNsx = nsxProvider != null;
|
||||
NetrisProviderVO netrisProvider = netrisProviderDao.findByZoneId(dcId);
|
||||
boolean forNetris = netrisProvider != null;
|
||||
|
||||
final IPAddressVO sourceNatIp = getExistingSourceNatInVpc(owner.getId(), vpc.getId(), forNsx);
|
||||
final IPAddressVO sourceNatIp = getExistingSourceNatInVpc(owner.getId(), vpc.getId(), forNsx, forNetris);
|
||||
|
||||
PublicIp ipToReturn = null;
|
||||
|
||||
if (sourceNatIp != null) {
|
||||
ipToReturn = PublicIp.createFromAddrAndVlan(sourceNatIp, _vlanDao.findById(sourceNatIp.getVlanId()));
|
||||
} else {
|
||||
if (forNsx) {
|
||||
if (forNsx || forNetris) {
|
||||
ipToReturn = _ipAddrMgr.assignPublicIpAddress(dcId, podId, owner, Vlan.VlanType.VirtualNetwork, null, null, false, true);
|
||||
} else {
|
||||
ipToReturn = _ipAddrMgr.assignDedicateIpAddress(owner, null, vpc.getId(), dcId, true);
|
||||
|
|
@ -3398,7 +3407,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
final Map<Network.Service, Set<Network.Provider>> vpcOffSvcProvidersMap = getVpcOffSvcProvidersMap(vpcOfferingId);
|
||||
return (Objects.nonNull(vpcOffSvcProvidersMap.get(Network.Service.SourceNat))
|
||||
&& (vpcOffSvcProvidersMap.get(Network.Service.SourceNat).contains(Network.Provider.VPCVirtualRouter)
|
||||
|| vpcOffSvcProvidersMap.get(Service.SourceNat).contains(Provider.Nsx)))
|
||||
|| vpcOffSvcProvidersMap.get(Service.SourceNat).contains(Provider.Nsx)
|
||||
|| vpcOffSvcProvidersMap.get(Service.SourceNat).contains(Provider.Netris)))
|
||||
|| (Objects.nonNull(vpcOffSvcProvidersMap.get(Network.Service.Gateway))
|
||||
&& vpcOffSvcProvidersMap.get(Service.Gateway).contains(Network.Provider.VPCVirtualRouter));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1055,8 +1055,6 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
|
|||
NetworkOfferingVO defaultTungstenSharedSGNetworkOffering =
|
||||
new NetworkOfferingVO(NetworkOffering.DEFAULT_TUNGSTEN_SHARED_NETWORK_OFFERING_WITH_SGSERVICE, "Offering for Tungsten Shared Security group enabled networks",
|
||||
TrafficType.Guest, false, true, null, null, true, Availability.Optional, null, Network.GuestType.Shared, true, true, false, false, false, false);
|
||||
|
||||
defaultTungstenSharedSGNetworkOffering.setForTungsten(true);
|
||||
defaultTungstenSharedSGNetworkOffering.setState(NetworkOffering.State.Enabled);
|
||||
defaultTungstenSharedSGNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultTungstenSharedSGNetworkOffering);
|
||||
|
||||
|
|
@ -1234,7 +1232,6 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
|
|||
false, false, false, false, forVpc);
|
||||
defaultNatProviderNetworkOffering.setPublicLb(publicLB);
|
||||
defaultNatProviderNetworkOffering.setInternalLb(!publicLB);
|
||||
defaultNatProviderNetworkOffering.setForNsx(Provider.Nsx.equals(provider));
|
||||
defaultNatProviderNetworkOffering.setNetworkMode(networkMode);
|
||||
defaultNatProviderNetworkOffering.setState(NetworkOffering.State.Enabled);
|
||||
defaultNatProviderNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNatProviderNetworkOffering);
|
||||
|
|
|
|||
|
|
@ -23,14 +23,17 @@ import java.util.Objects;
|
|||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.Vlan;
|
||||
import com.cloud.network.dao.NetrisProviderDao;
|
||||
import com.cloud.network.dao.NetworkDetailVO;
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import com.cloud.network.dao.NsxProviderDao;
|
||||
import com.cloud.network.element.NetrisProviderVO;
|
||||
import com.cloud.network.element.NsxProviderVO;
|
||||
import com.cloud.network.router.VirtualRouter;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
|
|
@ -93,6 +96,7 @@ public class RouterDeploymentDefinition {
|
|||
protected NetworkDao networkDao;
|
||||
protected DomainRouterDao routerDao;
|
||||
protected NsxProviderDao nsxProviderDao;
|
||||
protected NetrisProviderDao netrisProviderDao;
|
||||
protected PhysicalNetworkServiceProviderDao physicalProviderDao;
|
||||
protected NetworkModel networkModel;
|
||||
protected VirtualRouterProviderDao vrProviderDao;
|
||||
|
|
@ -395,10 +399,11 @@ public class RouterDeploymentDefinition {
|
|||
if (Objects.nonNull(zone)) {
|
||||
zoneId = zone.getId();
|
||||
}
|
||||
NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(zoneId);
|
||||
|
||||
boolean isExternalProvider = isExternalProviderPresent(zoneId);
|
||||
|
||||
if (isPublicNetwork) {
|
||||
if (Objects.isNull(nsxProvider)) {
|
||||
if (!isExternalProvider) {
|
||||
sourceNatIp = ipAddrMgr.assignSourceNatIpAddressToGuestNetwork(owner, guestNetwork);
|
||||
} else {
|
||||
sourceNatIp = ipAddrMgr.assignPublicIpAddress(zoneId, getPodId(), owner, Vlan.VlanType.VirtualNetwork, null, null, false, true);
|
||||
|
|
@ -406,6 +411,16 @@ public class RouterDeploymentDefinition {
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean isExternalProviderPresent(Long zoneId) {
|
||||
NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(zoneId);
|
||||
NetrisProviderVO netrisProviderVO = netrisProviderDao.findByZoneId(zoneId);
|
||||
|
||||
if (ObjectUtils.anyNotNull(nsxProvider, netrisProviderVO)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void findDefaultServiceOfferingId() {
|
||||
ServiceOfferingVO serviceOffering = serviceOfferingDao.findDefaultSystemOffering(ServiceOffering.routerDefaultOffUniqueName, ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dest.getDataCenter().getId()));
|
||||
serviceOfferingId = serviceOffering.getId();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import java.util.Map;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.network.dao.NetrisProviderDao;
|
||||
import com.cloud.network.dao.NetworkDetailsDao;
|
||||
import com.cloud.network.dao.NsxProviderDao;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
|
|
@ -66,6 +67,8 @@ public class RouterDeploymentDefinitionBuilder {
|
|||
@Inject
|
||||
private NsxProviderDao nsxProviderDao;
|
||||
@Inject
|
||||
private NetrisProviderDao netrisProviderDao;
|
||||
@Inject
|
||||
private PhysicalNetworkServiceProviderDao physicalProviderDao;
|
||||
@Inject
|
||||
private NetworkModel networkModel;
|
||||
|
|
@ -129,6 +132,7 @@ public class RouterDeploymentDefinitionBuilder {
|
|||
routerDeploymentDefinition.networkDao = networkDao;
|
||||
routerDeploymentDefinition.routerDao = routerDao;
|
||||
routerDeploymentDefinition.nsxProviderDao = nsxProviderDao;
|
||||
routerDeploymentDefinition.netrisProviderDao = netrisProviderDao;
|
||||
routerDeploymentDefinition.physicalProviderDao = physicalProviderDao;
|
||||
routerDeploymentDefinition.networkModel = networkModel;
|
||||
routerDeploymentDefinition.vrProviderDao = vrProviderDao;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import java.util.Objects;
|
|||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.element.NsxProviderVO;
|
||||
|
||||
import com.cloud.dc.dao.VlanDao;
|
||||
import com.cloud.deploy.DataCenterDeployment;
|
||||
|
|
@ -127,10 +126,11 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition {
|
|||
if (Objects.nonNull(zone)) {
|
||||
zoneId = zone.getId();
|
||||
}
|
||||
NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(zoneId);
|
||||
|
||||
boolean isExternalProvider = isExternalProviderPresent(zoneId);
|
||||
|
||||
if (isPublicNetwork) {
|
||||
if (Objects.isNull(nsxProvider)) {
|
||||
if (!isExternalProvider) {
|
||||
sourceNatIp = vpcMgr.assignSourceNatIpAddressToVpc(owner, vpc, null);
|
||||
} else {
|
||||
sourceNatIp = vpcMgr.assignSourceNatIpAddressToVpc(owner, vpc, getPodId());
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import com.cloud.offerings.NetworkOfferingVO;
|
|||
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.network.vpc.dao.VpcDao;
|
||||
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.net.Ip;
|
||||
import org.junit.Assert;
|
||||
|
|
@ -44,6 +45,7 @@ import org.mockito.Mockito;
|
|||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
|
@ -60,6 +62,8 @@ public class NetworkModelImplTest {
|
|||
|
||||
@Mock
|
||||
private VpcDao vpcDao;
|
||||
@Inject
|
||||
private NetworkOfferingServiceMapDao networkOfferingServiceMapDao;
|
||||
|
||||
@InjectMocks
|
||||
private NetworkModelImpl networkModel = new NetworkModelImpl();
|
||||
|
|
@ -70,8 +74,10 @@ public class NetworkModelImplTest {
|
|||
public void setUp() {
|
||||
networkOfferingDao = Mockito.mock(NetworkOfferingDao.class);
|
||||
networkServiceMapDao = Mockito.mock(NetworkServiceMapDao.class);
|
||||
networkOfferingServiceMapDao = Mockito.mock(NetworkOfferingServiceMapDao.class);
|
||||
networkModel._networkOfferingDao = networkOfferingDao;
|
||||
networkModel._ntwkSrvcDao = networkServiceMapDao;
|
||||
networkModel._ntwkOfferingSrvcDao = networkOfferingServiceMapDao;
|
||||
}
|
||||
|
||||
private void prepareMocks(boolean isIp6, Network network, DataCenter zone, VpcVO vpc,
|
||||
|
|
@ -216,7 +222,6 @@ public class NetworkModelImplTest {
|
|||
PublicIpAddress publicIpAddress2 = new PublicIp(ipAddressVO2, vlanVO, 0x0ac00000L);
|
||||
NetworkOfferingVO networkOfferingVO = new NetworkOfferingVO();
|
||||
networkOfferingVO.setForVpc(true);
|
||||
networkOfferingVO.setForNsx(false);
|
||||
Network network = new NetworkVO();
|
||||
List<NetworkServiceMapVO> networkServiceMapVOs = new ArrayList<>();
|
||||
networkServiceMapVOs.add(new NetworkServiceMapVO(15L, Network.Service.Firewall, Network.Provider.VPCVirtualRouter));
|
||||
|
|
@ -229,6 +234,7 @@ public class NetworkModelImplTest {
|
|||
Map<PublicIpAddress, Set<Network.Service>> ipToServices = new HashMap<>();
|
||||
ipToServices.put(publicIpAddress1, services1);
|
||||
ipToServices.put(publicIpAddress2, services2);
|
||||
Mockito.when(networkOfferingServiceMapDao.isProviderForNetworkOffering(networkOfferingVO.getId(), Network.Provider.Nsx)).thenReturn(false);
|
||||
Map<Network.Provider, ArrayList<PublicIpAddress>> result = networkModel.getProviderToIpList(network, ipToServices);
|
||||
Assert.assertNotNull(result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -558,7 +558,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
|
|||
*/
|
||||
@Override
|
||||
public 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 vlanGatewayv6, String vlanCidrv6, boolean forNsx)
|
||||
String vlanGateway, String vlanNetmask, String vlanId, boolean bypassVlanOverlapCheck, Domain domain, Account vlanOwner, String startIPv6, String endIPv6, String vlanGatewayv6, String vlanCidrv6, Provider provider)
|
||||
throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
// under the License.
|
||||
package com.cloud.vpc.dao;
|
||||
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Network.Service;
|
||||
import com.cloud.network.vpc.VpcOfferingServiceMapVO;
|
||||
import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
|
||||
|
|
@ -62,6 +63,11 @@ public class MockVpcOfferingServiceMapDaoImpl extends GenericDaoBase<VpcOffering
|
|||
return new VpcOfferingServiceMapVO();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProviderForVpcOffering(Network.Provider provider, long vpcOffering) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VpcOfferingServiceMapVO persist(VpcOfferingServiceMapVO vo) {
|
||||
return vo;
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@
|
|||
<bean id="configurationGroupDaoImpl" class="org.apache.cloudstack.framework.config.dao.ConfigurationGroupDaoImpl" />
|
||||
<bean id="configurationSubGroupDaoImpl" class="org.apache.cloudstack.framework.config.dao.ConfigurationSubGroupDaoImpl" />
|
||||
<bean id="nsxControllerDaoImpl" class="com.cloud.network.dao.NsxProviderDaoImpl" />
|
||||
<bean id="netrisProviderDaoImpl" class="com.cloud.network.dao.NetrisProviderDaoImpl" />
|
||||
<bean id="vlanDetailsDao" class="com.cloud.dc.dao.VlanDetailsDaoImpl" />
|
||||
<bean id="publicIpQuarantineDaoImpl" class="com.cloud.network.dao.PublicIpQuarantineDaoImpl" />
|
||||
<bean id="reservationDao" class="org.apache.cloudstack.reservation.dao.ReservationDaoImpl" />
|
||||
|
|
|
|||
|
|
@ -98,6 +98,9 @@ known_categories = {
|
|||
'listNsxControllers': 'NSX',
|
||||
'addNsxController': 'NSX',
|
||||
'deleteNsxController': 'NSX',
|
||||
'addNetrisProvider': 'Netris',
|
||||
'listNetrisProviders': 'Netris',
|
||||
'deleteNetrisProvider': 'Netris',
|
||||
'Vpn': 'VPN',
|
||||
'Limit': 'Resource Limit',
|
||||
'Netscaler': 'Netscaler',
|
||||
|
|
|
|||
|
|
@ -1491,6 +1491,8 @@
|
|||
"label.netris.provider.port": "Netris provider port",
|
||||
"label.netris.provider.username": "Netris provider username",
|
||||
"label.netris.provider.password": "Netris provider password",
|
||||
"label.netris.provider.site": "Netris provider Site name",
|
||||
"label.netris.provider.tenant.name": "Netris provider Admin Tenant name",
|
||||
"label.netscaler": "NetScaler",
|
||||
"label.netscaler.mpx": "NetScaler MPX LoadBalancer",
|
||||
"label.netscaler.sdx": "NetScaler SDX LoadBalancer",
|
||||
|
|
@ -2077,6 +2079,7 @@
|
|||
"label.shutdown": "Shutdown",
|
||||
"label.shutdown.provider": "Shutdown provider",
|
||||
"label.simplified.chinese.keyboard": "Simplified Chinese keyboard",
|
||||
"label.site": "Netris Site",
|
||||
"label.site.to.site.vpn": "Site-to-site VPN",
|
||||
"label.site.to.site.vpn.connections": "Site-to-site VPN Connections",
|
||||
"label.size": "Size",
|
||||
|
|
@ -2265,6 +2268,7 @@
|
|||
"label.templatesubject": "Subject",
|
||||
"label.templatetype": "Template type",
|
||||
"label.templateversion": "Template version",
|
||||
"label.tenantname": "Netris Tenant",
|
||||
"label.term.type": "Term type",
|
||||
"label.test": "Test",
|
||||
"label.test.webhook.delivery": "Test Webhook Delivery",
|
||||
|
|
@ -2745,6 +2749,7 @@
|
|||
"message.remove.ip.v6.firewall.rule.failed": "Failed to remove IPv6 firewall rule",
|
||||
"message.remove.ip.v6.firewall.rule.processing": "Removing IPv6 firewall rule...",
|
||||
"message.remove.ip.v6.firewall.rule.success": "Removed IPv6 firewall rule",
|
||||
"message.add.netris.controller": "Add Netris Provider",
|
||||
"message.add.nsx.controller": "Add NSX Provider",
|
||||
"message.add.network": "Add a new network for zone: <b><span id=\"zone_name\"></span></b>",
|
||||
"message.add.network.acl.failed": "Adding network ACL list failed.",
|
||||
|
|
@ -2832,6 +2837,7 @@
|
|||
"message.configuring.guest.traffic": "Configuring guest traffic",
|
||||
"message.configuring.physical.networks": "Configuring physical Networks",
|
||||
"message.configuring.public.traffic": "Configuring public traffic",
|
||||
"message.configuring.netris.public.traffic": "Configuring Netris public traffic",
|
||||
"message.configuring.nsx.public.traffic": "Configuring NSX public traffic",
|
||||
"message.configuring.storage.traffic": "Configuring storage traffic",
|
||||
"message.confirm.action.force.reconnect": "Please confirm that you want to force reconnect this host.",
|
||||
|
|
@ -3221,6 +3227,8 @@
|
|||
"message.installwizard.tooltip.netris.provider.hostname": "Netris Provider hostname / IP address not provided",
|
||||
"message.installwizard.tooltip.netris.provider.username": "Netris Provider username not provided",
|
||||
"message.installwizard.tooltip.netris.provider.password": "Netris Provider password not provided",
|
||||
"message.installwizard.tooltip.netris.provider.site": "Netris Provider Site name not provided",
|
||||
"message.installwizard.tooltip.netris.provider.tenant.name": "Netris Provider Admin Tenant name not provided",
|
||||
"message.installwizard.tooltip.nsx.provider.hostname": "NSX Provider hostname / IP address not provided",
|
||||
"message.installwizard.tooltip.nsx.provider.username": "NSX Provider username not provided",
|
||||
"message.installwizard.tooltip.nsx.provider.password": "NSX Provider password not provided",
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export default {
|
|||
args: ['name', 'zoneid', 'isolationmethods', 'vlan', 'tags', 'networkspeed', 'broadcastdomainrange'],
|
||||
mapping: {
|
||||
isolationmethods: {
|
||||
options: ['VLAN', 'VXLAN', 'GRE', 'STT', 'BCF_SEGMENT', 'SSP', 'ODL', 'L3VPN', 'VCS']
|
||||
options: ['VLAN', 'VXLAN', 'GRE', 'STT', 'BCF_SEGMENT', 'SSP', 'ODL', 'L3VPN', 'VCS', 'NSX', 'NETRIS']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1128,6 +1128,50 @@ export default {
|
|||
columns: ['name', 'hostname', 'port', 'tier0gateway', 'edgecluster', 'transportzone']
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Netris',
|
||||
details: ['name', 'state', 'id', 'physicalnetworkid', 'servicelist'],
|
||||
actions: [
|
||||
{
|
||||
api: 'updateNetworkServiceProvider',
|
||||
icon: 'stop-outlined',
|
||||
listView: true,
|
||||
label: 'label.disable.provider',
|
||||
confirm: 'message.confirm.disable.provider',
|
||||
show: (record) => { return (record && record.id && record.state === 'Enabled') },
|
||||
mapping: {
|
||||
state: {
|
||||
value: (record) => { return 'Disabled' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
api: 'updateNetworkServiceProvider',
|
||||
icon: 'play-circle-outlined',
|
||||
listView: true,
|
||||
label: 'label.enable.provider',
|
||||
confirm: 'message.confirm.enable.provider',
|
||||
show: (record) => { return (record && record.id && record.state === 'Disabled') },
|
||||
mapping: {
|
||||
state: {
|
||||
value: (record) => { return 'Enabled' }
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
lists: [
|
||||
{
|
||||
title: 'label.netris.provider',
|
||||
api: 'listNetrisProviders',
|
||||
mapping: {
|
||||
zoneid: {
|
||||
value: (record) => { return record.zoneid }
|
||||
}
|
||||
},
|
||||
columns: ['name', 'hostname', 'port', 'site', 'tenantname']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1168,7 +1212,6 @@ export default {
|
|||
this.fetchLoading = true
|
||||
api('listNetworkServiceProviders', { physicalnetworkid: this.resource.id, name: name }).then(json => {
|
||||
const sps = json.listnetworkserviceprovidersresponse.networkserviceprovider || []
|
||||
console.log(sps)
|
||||
if (sps.length > 0) {
|
||||
for (const sp of sps) {
|
||||
this.nsps[sp.name] = sp
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
<a-tab-pane v-for="(item, index) in traffictypes" :tab="item.traffictype" :key="index">
|
||||
<a-popconfirm
|
||||
:title="$t('message.confirm.delete.traffic.type')"
|
||||
@confirm="deleteTrafficType(itemd)"
|
||||
@confirm="deleteTrafficType(item)"
|
||||
:okText="$t('label.yes')"
|
||||
:cancelText="$t('label.no')" >
|
||||
<a-button
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
isolationMethods () {
|
||||
return ['VLAN', 'VXLAN', 'GRE', 'STT', 'BCF_SEGMENT', 'SSP', 'ODL', 'L3VPN', 'VCS']
|
||||
return ['VLAN', 'VXLAN', 'GRE', 'STT', 'BCF_SEGMENT', 'SSP', 'ODL', 'L3VPN', 'VCS', 'NSX', 'NETRIS']
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -472,7 +472,6 @@ export default {
|
|||
if (physicalNetwork.tags) {
|
||||
params.tags = physicalNetwork.tags
|
||||
}
|
||||
|
||||
try {
|
||||
if (!this.stepData.stepMove.includes('createPhysicalNetwork' + index)) {
|
||||
const physicalNetworkResult = await this.createPhysicalNetwork(params)
|
||||
|
|
@ -490,7 +489,7 @@ export default {
|
|||
physicalNetwork.traffics.findIndex(traffic => traffic.type === 'public' || traffic.type === 'guest') > -1) {
|
||||
this.stepData.isNsxZone = true
|
||||
}
|
||||
if (physicalNetwork.isolationMethod === 'NETRIS' &&
|
||||
if (physicalNetwork.isolationMethod.toLowerCase() === 'netris' &&
|
||||
physicalNetwork.traffics.findIndex(traffic => traffic.type === 'public' || traffic.type === 'guest') > -1) {
|
||||
this.stepData.isNetrisZone = true
|
||||
}
|
||||
|
|
@ -921,7 +920,7 @@ export default {
|
|||
let stopNow = false
|
||||
this.stepData.returnedPublicTraffic = this.stepData?.returnedPublicTraffic || []
|
||||
let publicIpRanges = this.prefillContent['public-ipranges']
|
||||
publicIpRanges = publicIpRanges.filter(item => item.fornsx === (idx === 1))
|
||||
publicIpRanges = publicIpRanges.filter(item => (item.fornsx || item.fornetris) === (idx === 1))
|
||||
for (let index = 0; index < publicIpRanges.length; index++) {
|
||||
const publicVlanIpRange = publicIpRanges[index]
|
||||
let isExisting = false
|
||||
|
|
@ -944,16 +943,22 @@ export default {
|
|||
params.zoneId = this.stepData.zoneReturned.id
|
||||
if (publicVlanIpRange.vlan && publicVlanIpRange.vlan.length > 0) {
|
||||
params.vlan = publicVlanIpRange.vlan
|
||||
} else if (publicVlanIpRange.fornsx) { // TODO: should this be the same for Netris?
|
||||
} else if (publicVlanIpRange.fornsx || publicVlanIpRange.fornetris) { // TODO: should this be the same for Netris?
|
||||
params.vlan = null
|
||||
} else {
|
||||
params.vlan = 'untagged'
|
||||
}
|
||||
let provider = null
|
||||
if (publicVlanIpRange.fornsx) {
|
||||
provider = 'Nsx'
|
||||
} else if (publicVlanIpRange.fornetris) {
|
||||
provider = 'Netris'
|
||||
}
|
||||
params.gateway = publicVlanIpRange.gateway
|
||||
params.netmask = publicVlanIpRange.netmask
|
||||
params.startip = publicVlanIpRange.startIp
|
||||
params.endip = publicVlanIpRange.endIp
|
||||
params.fornsx = publicVlanIpRange.fornsx
|
||||
params.provider = provider
|
||||
params.forsystemvms = publicVlanIpRange.forsystemvms
|
||||
|
||||
if (this.isBasicZone) {
|
||||
|
|
@ -986,16 +991,20 @@ export default {
|
|||
if (stopNow) {
|
||||
return
|
||||
}
|
||||
|
||||
if (idx === 0) {
|
||||
await this.stepConfigurePublicTraffic('message.configuring.nsx.public.traffic', 'nsxPublicTraffic', 1)
|
||||
const isolationMethods = Object.values(this.stepData.physicalNetworkItem).map(network => network.isolationmethods.toLowerCase())
|
||||
if (isolationMethods.includes('nsx')) {
|
||||
await this.stepConfigurePublicTraffic('message.configuring.nsx.public.traffic', 'nsxPublicTraffic', 1)
|
||||
} else if (isolationMethods.includes('netris')) {
|
||||
await this.stepConfigurePublicTraffic('message.configuring.netris.public.traffic', 'netrisPublicTraffic', 1)
|
||||
}
|
||||
} else {
|
||||
if (this.stepData.isTungstenZone) {
|
||||
await this.stepCreateTungstenFabricPublicNetwork()
|
||||
} else if (this.stepData.isNsxZone) {
|
||||
await this.stepAddNsxController()
|
||||
} else if (this.stepData.isNetrisZone) {
|
||||
await this.stepAddNetrisController()
|
||||
await this.stepAddNetrisProvider()
|
||||
} else {
|
||||
await this.stepConfigureStorageTraffic()
|
||||
}
|
||||
|
|
@ -1099,7 +1108,7 @@ export default {
|
|||
this.setStepStatus(STATUS_FAILED)
|
||||
}
|
||||
},
|
||||
async stepAddNetrisController () {
|
||||
async stepAddNetrisProvider () {
|
||||
this.setStepStatus(STATUS_FINISH)
|
||||
this.currentStep++
|
||||
this.addStep('message.add.netris.controller', 'netris')
|
||||
|
|
@ -1111,14 +1120,16 @@ export default {
|
|||
if (!this.stepData.stepMove.includes('addNetrisProvider')) {
|
||||
const providerParams = {}
|
||||
providerParams.name = this.prefillContent?.netrisName || ''
|
||||
providerParams.netrisproviderhostname = this.prefillContent?.netrisHostname || ''
|
||||
providerParams.netrisproviderport = this.prefillContent?.netrisPort || ''
|
||||
providerParams.hostname = this.prefillContent?.hostname || ''
|
||||
providerParams.port = this.prefillContent?.netrisPort || ''
|
||||
providerParams.username = this.prefillContent?.username || ''
|
||||
providerParams.password = this.prefillContent?.password || ''
|
||||
providerParams.zoneid = this.stepData.zoneReturned.id
|
||||
providerParams.sitename = this.prefillContent?.siteName || ''
|
||||
providerParams.tenantname = this.prefillContent?.tenantName || ''
|
||||
|
||||
await this.addNetrisProvider(providerParams)
|
||||
this.stepData.stepMove.push('addNetrisController')
|
||||
this.stepData.stepMove.push('addNetrisProvider')
|
||||
}
|
||||
this.stepData.stepMove.push('netris')
|
||||
await this.stepConfigureStorageTraffic()
|
||||
|
|
@ -2285,7 +2296,7 @@ export default {
|
|||
})
|
||||
})
|
||||
},
|
||||
addNetrisPovider (args) {
|
||||
addNetrisProvider (args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
api('addNetrisProvider', {}, 'POST', args).then(json => {
|
||||
resolve()
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@
|
|||
</div>
|
||||
<div v-else>
|
||||
<advanced-guest-traffic-form
|
||||
v-if="steps && steps[currentStep].formKey === 'guestTraffic' && !isNsxZone && !isNetrisZone"
|
||||
v-if="steps && steps[currentStep].formKey === 'guestTraffic' && !isNsxZone"
|
||||
@nextPressed="nextPressed"
|
||||
@backPressed="handleBack"
|
||||
@fieldsChanged="fieldsChanged"
|
||||
|
|
@ -290,7 +290,7 @@ export default {
|
|||
title: 'label.pod',
|
||||
formKey: 'pod'
|
||||
})
|
||||
if (!this.isTungstenZone && !this.isNsxZone && !this.isNetrisZone) {
|
||||
if (!this.isTungstenZone && !this.isNsxZone) {
|
||||
steps.push({
|
||||
title: 'label.guest.traffic',
|
||||
formKey: 'guestTraffic',
|
||||
|
|
@ -485,7 +485,7 @@ export default {
|
|||
},
|
||||
{
|
||||
title: 'label.netris.provider.hostname',
|
||||
key: 'netrisHostname',
|
||||
key: 'hostname',
|
||||
placeHolder: 'message.installwizard.tooltip.netris.provider.hostname',
|
||||
required: true
|
||||
},
|
||||
|
|
@ -507,6 +507,18 @@ export default {
|
|||
placeHolder: 'message.installwizard.tooltip.netris.provider.password',
|
||||
required: true,
|
||||
password: true
|
||||
},
|
||||
{
|
||||
title: 'label.netris.provider.site',
|
||||
key: 'siteName',
|
||||
placeHolder: 'message.installwizard.tooltip.netris.provider.site',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
title: 'label.netris.provider.tenant.name',
|
||||
key: 'tenantName',
|
||||
placeHolder: 'message.installwizard.tooltip.netris.provider.tenant.name',
|
||||
required: true
|
||||
}
|
||||
]
|
||||
return fields
|
||||
|
|
@ -631,7 +643,7 @@ export default {
|
|||
}
|
||||
this.scrollToStepActive()
|
||||
if (this.zoneType === 'Basic' ||
|
||||
(this.zoneType === 'Advanced' && (this.sgEnabled || this.isNsxZone || this.isNetrisZone))) {
|
||||
(this.zoneType === 'Advanced' && (this.sgEnabled || this.isNsxZone))) {
|
||||
this.skipGuestTrafficStep = false
|
||||
} else {
|
||||
this.fetchConfiguration()
|
||||
|
|
|
|||
|
|
@ -457,6 +457,7 @@ export default {
|
|||
publicLBExists: false,
|
||||
setMTU: false,
|
||||
isNsxEnabled: false,
|
||||
zoneExtNetProvider: null,
|
||||
isOfferingNatMode: false,
|
||||
isOfferingRoutedMode: false,
|
||||
displayCollapsible: [],
|
||||
|
|
@ -533,6 +534,7 @@ export default {
|
|||
this.setMTU = json?.listzonesresponse?.zone?.[0]?.allowuserspecifyvrmtu || false
|
||||
this.privateMtuMax = json?.listzonesresponse?.zone?.[0]?.routerprivateinterfacemaxmtu || 1500
|
||||
this.isNsxEnabled = json?.listzonesresponse?.zone?.[0]?.isnsxenabled || false
|
||||
this.zoneExtNetProvider = json?.listzonesresponse?.zone?.[0]?.provider || null
|
||||
})
|
||||
},
|
||||
fetchNetworkAclList () {
|
||||
|
|
@ -612,7 +614,7 @@ export default {
|
|||
guestiptype: 'Isolated',
|
||||
state: 'Enabled'
|
||||
}
|
||||
if (!this.isNsxEnabled && !this.isOfferingRoutedMode) {
|
||||
if ((!this.isNsxEnabled || !['netris', 'nsx'].includes(this.zoneExtNetProvider.toLowerCase())) && !this.isOfferingRoutedMode) {
|
||||
params.supportedServices = 'SourceNat'
|
||||
}
|
||||
api('listNetworkOfferings', params).then(json => {
|
||||
|
|
@ -635,7 +637,7 @@ export default {
|
|||
}
|
||||
}
|
||||
this.networkOfferings = filteredOfferings
|
||||
if (this.isNsxEnabled) {
|
||||
if (this.isNsxEnabled || ['netris', 'nsx'].includes(this.zoneExtNetProvider.toLowerCase())) {
|
||||
this.networkOfferings = this.networkOfferings.filter(offering => offering.networkmode === (this.isOfferingNatMode ? 'NATTED' : 'ROUTED'))
|
||||
}
|
||||
if (this.resource.asnumberid) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public class LogUtilsTest {
|
|||
|
||||
@Test
|
||||
public void logGsonWithoutExceptionTestLogCorrectlyPrimitives() {
|
||||
String expected = "test primitives: int [1], double [1.11], float [1.2222], boolean [true], null [], char [\"c\"].";
|
||||
String expected = "test primitives: int [1], double [1.11], float [1.2222], boolean [true], null [null], char [\"c\"].";
|
||||
String log = LogUtils.logGsonWithoutException("test primitives: int [%s], double [%s], float [%s], boolean [%s], null [%s], char [%s].",
|
||||
1, 1.11d, 1.2222f, true, null, 'c');
|
||||
assertEquals(expected, log);
|
||||
|
|
|
|||
Loading…
Reference in New Issue