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:
Pearl Dsilva 2024-10-22 10:31:05 -04:00 committed by GitHub
parent 9f76e377d4
commit bfb017426d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
95 changed files with 2976 additions and 301 deletions

View File

@ -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());
}
}

View File

@ -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;

View File

@ -25,4 +25,6 @@ public interface NetrisProvider extends InternalIdentity, Identity {
String getHostname();
String getPort();
String getUsername();
String getSiteName();
String getTenantName();
}

View File

@ -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);
}

View File

@ -57,8 +57,6 @@ public interface VpcOffering extends InternalIdentity, Identity {
*/
boolean isDefault();
boolean isForNsx();
NetworkOffering.NetworkMode getNetworkMode();
/**

View File

@ -103,10 +103,6 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
boolean isForVpc();
boolean isForTungsten();
boolean isForNsx();
NetworkMode getNetworkMode();
TrafficType getTrafficType();

View File

@ -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";

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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>

View File

@ -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());
}
}
}

View File

@ -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;

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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" />

View File

@ -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`;

View File

@ -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`,

View File

@ -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`,

View File

@ -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);

View File

@ -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());

View File

@ -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));

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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() {

View File

@ -41,7 +41,8 @@ public class DeleteNsxControllerCmd extends BaseCmd {
@Inject
protected NsxProviderService nsxProviderService;
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////

View File

@ -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() {

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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());
}

View File

@ -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();

View File

@ -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());
}

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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) {

View File

@ -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() {

View File

@ -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;

View File

@ -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()) {

View File

@ -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());

View File

@ -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};

View File

@ -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);

View File

@ -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));
}

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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());

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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" />

View File

@ -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',

View File

@ -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",

View File

@ -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']
}
}
},

View File

@ -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

View File

@ -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

View File

@ -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: {

View File

@ -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()

View File

@ -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()

View File

@ -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) {

View File

@ -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);