add support to update vpc tier name

This commit is contained in:
Pearl Dsilva 2025-03-05 17:48:27 -05:00
parent 8572d6a776
commit 1ee69a923a
11 changed files with 225 additions and 5 deletions

View File

@ -215,4 +215,8 @@ public interface NetworkGuru extends Adapter {
default boolean isSlaacV6Only() {
return true;
}
default boolean update(Network network, String prevNetworkName) {
return true;
}
}

View File

@ -34,6 +34,8 @@ public interface NetrisService {
boolean createVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr, Boolean globalRouting);
boolean updateVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String prevNetworkName);
boolean deleteVnetResource(long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr);
boolean createSnatRule(long zoneId, long accountId, long domainId, String vpcName, long vpcId, String networkName, long networkId, boolean isForVpc, String vpcCidr, String sourceNatIp);

View File

@ -1099,8 +1099,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
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);
NetworkGuru netrisGuru = AdapterBase.getAdapterByName(networkGurus, guruName);
netrisGuru.allocate(network, profile, vm);
}
if (isDefaultNic != null) {

View File

@ -2,6 +2,8 @@ package org.apache.cloudstack.agent.api;
public class UpdateNetrisVnetCommand extends NetrisCommand{
private String prevNetworkName;
private String vpcName;
private Long vpcId;
public UpdateNetrisVnetCommand(long zoneId, Long accountId, Long domainId, String name, Long id, boolean isVpc) {
super(zoneId, accountId, domainId, name, id, isVpc);
@ -14,4 +16,20 @@ public class UpdateNetrisVnetCommand extends NetrisCommand{
public void setPrevNetworkName(String prevNetworkName) {
this.prevNetworkName = prevNetworkName;
}
public String getVpcName() {
return vpcName;
}
public void setVpcName(String vpcName) {
this.vpcName = vpcName;
}
public Long getVpcId() {
return vpcId;
}
public void setVpcId(Long vpcId) {
this.vpcId = vpcId;
}
}

View File

@ -44,6 +44,7 @@ import org.apache.cloudstack.agent.api.NetrisAnswer;
import org.apache.cloudstack.StartupNetrisCommand;
import org.apache.cloudstack.agent.api.ReleaseNatIpCommand;
import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
import org.apache.cloudstack.agent.api.UpdateNetrisVnetCommand;
import org.apache.cloudstack.agent.api.UpdateNetrisVpcCommand;
import org.apache.cloudstack.service.NetrisApiClient;
import org.apache.cloudstack.service.NetrisApiClientImpl;
@ -105,6 +106,8 @@ public class NetrisResource implements ServerResource {
return executeRequest((DeleteNetrisVpcCommand) cmd);
} else if (cmd instanceof CreateNetrisVnetCommand) {
return executeRequest((CreateNetrisVnetCommand) cmd);
} else if (cmd instanceof UpdateNetrisVnetCommand) {
return executeRequest((UpdateNetrisVnetCommand) cmd);
} else if (cmd instanceof DeleteNetrisVnetCommand) {
return executeRequest((DeleteNetrisVnetCommand) cmd);
} else if (cmd instanceof SetupNetrisPublicRangeCommand) {
@ -274,6 +277,22 @@ public class NetrisResource implements ServerResource {
}
}
private Answer executeRequest(UpdateNetrisVnetCommand cmd) {
try {
String networkName = cmd.getName();
String prevNetworkName = cmd.getPrevNetworkName();
boolean result = netrisApiClient.updateVnet(cmd);
if (!result) {
return new NetrisAnswer(cmd, false, String.format("Failed to update network name from %s to %s", prevNetworkName, networkName));
}
return new NetrisAnswer(cmd, true, "OK");
} catch (CloudRuntimeException e) {
String msg = String.format("Error updating Netris vNet: %s", e.getMessage());
logger.error(msg, e);
return new NetrisAnswer(cmd, new CloudRuntimeException(msg));
}
}
private Answer executeRequest(DeleteNetrisVnetCommand cmd) {
try {
String networkName = cmd.getName();

View File

@ -34,6 +34,7 @@ import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
import org.apache.cloudstack.agent.api.ReleaseNatIpCommand;
import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
import org.apache.cloudstack.agent.api.UpdateNetrisVnetCommand;
import org.apache.cloudstack.agent.api.UpdateNetrisVpcCommand;
import java.util.List;
@ -67,6 +68,8 @@ public interface NetrisApiClient {
*/
boolean createVnet(CreateNetrisVnetCommand cmd);
boolean updateVnet(UpdateNetrisVnetCommand cmd);
/**
* Deletion of a VPC network tier deletes the following Netris resources:
* - Deletes the Netris IPAM Subnet for the specified network tier's CIDR

View File

@ -94,6 +94,9 @@ import io.netris.model.VnetAddBodyDhcp;
import io.netris.model.VnetAddBodyDhcpOptionSet;
import io.netris.model.VnetAddBodyGateways;
import io.netris.model.VnetAddBodyVpc;
import io.netris.model.VnetEditBody;
import io.netris.model.VnetEditBodyDhcp;
import io.netris.model.VnetEditBodyGateways;
import io.netris.model.VnetResAddBody;
import io.netris.model.VnetResDeleteBody;
import io.netris.model.VnetResListBody;
@ -119,6 +122,7 @@ import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
import org.apache.cloudstack.agent.api.NetrisCommand;
import org.apache.cloudstack.agent.api.ReleaseNatIpCommand;
import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
import org.apache.cloudstack.agent.api.UpdateNetrisVnetCommand;
import org.apache.cloudstack.agent.api.UpdateNetrisVpcCommand;
import org.apache.cloudstack.resource.NetrisResourceObjectUtils;
import org.apache.commons.collections.CollectionUtils;
@ -989,6 +993,127 @@ public class NetrisApiClientImpl implements NetrisApiClient {
return true;
}
@Override
public boolean updateVnet(UpdateNetrisVnetCommand cmd) {
String networkName = cmd.getName();
Long networkId = cmd.getId();
String prevNetworkName = cmd.getPrevNetworkName();
String vpcName = cmd.getVpcName();
Long vpcId = cmd.getVpcId();
boolean isVpc = cmd.isVpc();
String netrisVpcName = getNetrisVpcName(cmd, vpcId, vpcName);
VPCListing associatedVpc = getNetrisVpcResource(netrisVpcName);
if (associatedVpc == null) {
logger.error("Failed to find Netris VPC with name: {}, to create the corresponding vNet for network {}", netrisVpcName, networkName);
return false;
}
String vNetName;
String prevVnetName;
if (isVpc) {
vNetName = String.format("V%s-N%s-%s", vpcId, networkId, networkName);
prevVnetName = String.format("V%s-N%s-%s", vpcId, networkId, prevNetworkName);
} else {
vNetName = String.format("N%s-%s", networkId, networkName);
prevVnetName = String.format("N%s-%s", networkId, prevNetworkName);
}
String netrisVnetName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VNET, vNetName) ;
String prevNetrisVnetName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VNET, prevVnetName) ;
VnetResAddBody response = updateVnetInternal(associatedVpc, netrisVnetName, prevNetrisVnetName);
if (response == null || !response.isIsSuccess()) {
String reason = response == null ? "Empty response" : "Operation failed on Netris";
logger.debug("Netris vNet: {} update failed: {}", vNetName, reason);
return false;
}
return true;
}
private VnetResAddBody updateVnetInternal(VPCListing associatedVpc, String netrisVnetName, String prevVnetName) {
logger.debug("Updating Netris vNet name from {} to {} ", netrisVnetName, prevVnetName);
try {
FilterByVpc vpcFilter = new FilterByVpc();
vpcFilter.add(associatedVpc.getId());
FilterBySites siteFilter = new FilterBySites();
siteFilter.add(siteId);
List<VnetsBody> vnetsList = getVnets(associatedVpc, prevVnetName, siteFilter, vpcFilter);
if (CollectionUtils.isEmpty(vnetsList)) {
String errorMsg = String.format("Could not find vNet with name: %s", prevVnetName);
logger.error(errorMsg);
throw new CloudRuntimeException(errorMsg);
}
VnetsBody vnetsBody = vnetsList.get(0);
VnetEditBody vnetBody = new VnetEditBody();
vnetBody.setCustomAnycastMac(vnetBody.getCustomAnycastMac());
VnetEditBodyGateways gatewayV4 = new VnetEditBodyGateways();
gatewayV4.prefix(vnetsBody.getGateways().get(0).getPrefix());
gatewayV4.setDhcpEnabled(false);
VnetEditBodyDhcp dhcp = new VnetEditBodyDhcp();
dhcp.setEnd("");
dhcp.setStart("");
dhcp.setOptionSet(new VnetAddBodyDhcpOptionSet());
gatewayV4.setDhcp(dhcp);
List<VnetEditBodyGateways> gatewaysList = new ArrayList<>();
gatewaysList.add(gatewayV4);
if (vnetsBody.getGateways().size() > 1 && Objects.nonNull(vnetsBody.getGateways().get(1))) {
String netrisV6Gateway = vnetsBody.getGateways().get(1).getPrefix();
VnetEditBodyGateways gatewayV6 = new VnetEditBodyGateways();
gatewayV6.prefix(netrisV6Gateway);
gatewayV6.setDhcpEnabled(false);
gatewayV6.setDhcp(dhcp);
gatewaysList.add(gatewayV6);
}
vnetBody.setGateways(gatewaysList);
vnetBody.setGuestTenants(new ArrayList<>());
vnetBody.setL3vpn(false);
vnetBody.setName(netrisVnetName);
vnetBody.setNativeVlan(0);
vnetBody.setVxlanID(vnetsBody.getVxlanID());
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(VnetEditBody.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);
vnetBody.setTags(vnetsBody.getTags());
VNetApi vnetApi = apiClient.getApiStubForMethod(VNetApi.class);
return vnetApi.apiV2VnetIdPut(vnetBody, vnetsBody.getId().intValue());
} catch (ApiException e) {
logAndThrowException(String.format("Error creating Netris vNet %s for VPC %s", netrisVnetName, associatedVpc.getName()), e);
return null;
}
}
@Override
public boolean deleteVnet(DeleteNetrisVnetCommand cmd) {
String vpcName = cmd.getVpcName();
@ -1400,14 +1525,24 @@ public class NetrisApiClientImpl implements NetrisApiClient {
return true;
}
private void deleteVnetInternal(VPCListing associatedVpc, FilterBySites siteFilter, FilterByVpc vpcFilter, String netrisVnetName, String vNetName) {
private List<VnetsBody> getVnets(VPCListing associatedVpc, String netrisVnetName, FilterBySites siteFilter, FilterByVpc vpcFilter) {
try {
VNetApi vNetApi = apiClient.getApiStubForMethod(VNetApi.class);
VnetResListBody vnetList = vNetApi.apiV2VnetGet(siteFilter, vpcFilter);
if (vnetList == null || !vnetList.isIsSuccess()) {
throw new CloudRuntimeException(String.format("Failed to list vNets for the given VPC: %s and site: %s", associatedVpc.getName(), siteName));
}
List<VnetsBody> vnetsList = vnetList.getData().stream().filter(vnet -> vnet.getName().equals(netrisVnetName)).collect(Collectors.toList());
return vnetList.getData().stream().filter(vnet -> vnet.getName().equals(netrisVnetName)).collect(Collectors.toList());
} catch (ApiException e) {
logAndThrowException(String.format("Failed to get vNets: %s", netrisVnetName), e);
}
return Collections.emptyList();
}
private void deleteVnetInternal(VPCListing associatedVpc, FilterBySites siteFilter, FilterByVpc vpcFilter, String netrisVnetName, String vNetName) {
try {
VNetApi vNetApi = apiClient.getApiStubForMethod(VNetApi.class);
List<VnetsBody> vnetsList = getVnets(associatedVpc, netrisVnetName, siteFilter, vpcFilter);
if (CollectionUtils.isEmpty(vnetsList)) {
logger.debug("vNet: {} for the given VPC: {} appears to already be deleted on Netris", vNetName, associatedVpc.getName());
return;

View File

@ -159,6 +159,20 @@ public class NetrisGuestNetworkGuru extends GuestNetworkGuru implements Network
// Do nothing
}
@Override
public boolean update(Network network, String prevNetworkName) {
Long vpcId = network.getVpcId();
String vpcName = null;
if (Objects.nonNull(vpcId)) {
VpcVO vpc = _vpcDao.findById(vpcId);
if (Objects.nonNull(vpc)) {
vpcName = vpc.getName();
}
}
return netrisService.updateVnetResource(network.getDataCenterId(), network.getAccountId(), network.getDomainId(),
vpcName, vpcId, network.getName(), network.getId(), prevNetworkName);
}
@Override
public Network implement(Network network, NetworkOffering offering, DeployDestination dest,
ReservationContext context) throws InsufficientVirtualNetworkCapacityException {

View File

@ -58,6 +58,7 @@ import org.apache.cloudstack.agent.api.NetrisAnswer;
import org.apache.cloudstack.agent.api.NetrisCommand;
import org.apache.cloudstack.agent.api.ReleaseNatIpCommand;
import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
import org.apache.cloudstack.agent.api.UpdateNetrisVnetCommand;
import org.apache.cloudstack.agent.api.UpdateNetrisVpcCommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.framework.config.ConfigKey;
@ -233,6 +234,16 @@ public class NetrisServiceImpl implements NetrisService, Configurable {
return answer.getResult();
}
@Override
public boolean updateVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String prevNetworkName) {
UpdateNetrisVnetCommand cmd = new UpdateNetrisVnetCommand(zoneId, accountId, domainId, networkName, networkId, Objects.nonNull(vpcId));
cmd.setPrevNetworkName(prevNetworkName);
cmd.setVpcId(vpcId);
cmd.setVpcName(vpcName);
NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
return answer.getResult();
}
@Override
public boolean deleteVnetResource(long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr) {
DeleteNetrisVnetCommand cmd = new DeleteNetrisVnetCommand(zoneId, accountId, domainId, networkName, networkId, vpcName, vpcId, cidr, Objects.nonNull(vpcName));

View File

@ -51,6 +51,7 @@ import com.cloud.network.element.NsxProviderVO;
import com.cloud.network.element.VirtualRouterProviderVO;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.utils.component.AdapterBase;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.alert.AlertService;
@ -3087,7 +3088,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
// verify input parameters
final NetworkVO network = getNetworkVO(networkId, "Specified network id doesn't exist in the system");
String prevNetworkName = network.getName();
//perform below validation if the network is vpc network
if (network.getVpcId() != null && networkOfferingId != null) {
Vpc vpc = _entityMgr.findById(Vpc.class, network.getVpcId());
@ -3572,9 +3573,17 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
Network updatedNetwork = getNetwork(network.getId());
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_UPDATE, updatedNetwork.getAccountId(), updatedNetwork.getDataCenterId(), updatedNetwork.getId(),
updatedNetwork.getName(), updatedNetwork.getNetworkOfferingId(), null, updatedNetwork.getState().name(), Network.class.getName(), updatedNetwork.getUuid(), true);
updateProviderNetwork(updatedNetwork, prevNetworkName);
return updatedNetwork;
}
private void updateProviderNetwork(Network network, String prevNetworkName) {
final NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName());
if (Objects.nonNull(guru) && !guru.update(network, prevNetworkName)) {
logger.error("Failed to update name of network on provider");
}
}
protected Pair<Integer, Integer> validateMtuOnUpdate(NetworkVO network, Long zoneId, Integer publicMtu, Integer privateMtu) {
if (!AllowUsersToSpecifyVRMtu.valueIn(zoneId)) {
return new Pair<>(null, null);

View File

@ -51,6 +51,11 @@ public class NetrisServiceMockTest implements NetrisService {
return true;
}
@Override
public boolean updateVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String prevNetworkName) {
return true;
}
@Override
public boolean deleteVnetResource(long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr) {
return true;