2929import io .netris .api .v2 .VpcApi ;
3030import io .netris .model .AllocationBody ;
3131import io .netris .model .AllocationBodyVpc ;
32+ import io .netris .model .FilterBySites ;
33+ import io .netris .model .FilterByVpc ;
3234import io .netris .model .GetSiteBody ;
3335import io .netris .model .InlineResponse2004 ;
3436import io .netris .model .IpTreeAllocationTenant ;
37+ import io .netris .model .IpTreeSubnet ;
3538import io .netris .model .IpTreeSubnetSites ;
3639import io .netris .model .SitesResponseOK ;
3740import io .netris .model .SubnetBody ;
41+ import io .netris .model .SubnetResBody ;
3842import io .netris .model .VPCAdminTenant ;
3943import io .netris .model .VPCCreate ;
4044import io .netris .model .VPCListing ;
4953import io .netris .model .VnetAddBodyGateways ;
5054import io .netris .model .VnetAddBodyVpc ;
5155import io .netris .model .VnetResAddBody ;
56+ import io .netris .model .VnetResDeleteBody ;
57+ import io .netris .model .VnetResListBody ;
58+ import io .netris .model .VnetsBody ;
5259import io .netris .model .response .AuthResponse ;
5360import io .netris .model .response .TenantResponse ;
5461import io .netris .model .response .TenantsResponse ;
5562import org .apache .cloudstack .agent .api .CreateNetrisVnetCommand ;
5663import org .apache .cloudstack .agent .api .CreateNetrisVpcCommand ;
64+ import org .apache .cloudstack .agent .api .DeleteNetrisVnetCommand ;
5765import org .apache .cloudstack .agent .api .DeleteNetrisVpcCommand ;
5866import org .apache .cloudstack .resource .NetrisResourceObjectUtils ;
5967import org .apache .commons .collections .CollectionUtils ;
6371import java .math .BigDecimal ;
6472import java .util .ArrayList ;
6573import java .util .List ;
74+ import java .util .Objects ;
6675import java .util .stream .Collectors ;
6776
6877public class NetrisApiClientImpl implements NetrisApiClient {
@@ -238,6 +247,10 @@ private void deleteVpcIpamAllocationInternal(VPCListing vpcResource, String vpcC
238247 VpcApi vpcApi = apiClient .getApiStubForMethod (VpcApi .class );
239248 VPCResponseResourceOK vpcResourcesResponse = vpcApi .apiV2VpcVpcIdResourcesGet (vpcResource .getId ());
240249 VPCResourceIpam vpcAllocationResource = getVpcAllocationResource (vpcResourcesResponse );
250+ if (Objects .isNull (vpcAllocationResource )) {
251+ logger .info ("No VPC IPAM Allocation found for VPC {}" , vpcCidr );
252+ return ;
253+ }
241254 IpamApi ipamApi = apiClient .getApiStubForMethod (IpamApi .class );
242255 logger .debug ("Removing the IPAM allocation {} with ID {}" , vpcAllocationResource .getName (), vpcAllocationResource .getId ());
243256 ipamApi .apiV2IpamTypeIdDelete ("allocation" , vpcAllocationResource .getId ());
@@ -304,11 +317,11 @@ public boolean createVnet(CreateNetrisVnetCommand cmd) {
304317 String vnetCidr = cmd .getCidr ();
305318 boolean isVpc = cmd .isVpc ();
306319
307- String suffix = String . format ( "%s-%s" , vpcId , vpcName );
320+ String suffix = getNetrisVpcNameSuffix ( vpcId , vpcName , networkId , networkName , isVpc );
308321 String netrisVpcName = NetrisResourceObjectUtils .retrieveNetrisResourceObjectName (cmd , NetrisResourceObjectUtils .NetrisObjectType .VPC , suffix );
309322 VPCListing associatedVpc = getVpcByNameAndTenant (netrisVpcName );
310323 if (associatedVpc == null ) {
311- logger .error (String . format ( "Failed to find Netris VPC with name: %s , to create the corresponding vNet for network %s " , vpcName , networkName ) );
324+ logger .error ("Failed to find Netris VPC with name: {} , to create the corresponding vNet for network {} " , netrisVpcName , networkName );
312325 return false ;
313326 }
314327
@@ -324,20 +337,102 @@ public boolean createVnet(CreateNetrisVnetCommand cmd) {
324337 InlineResponse2004 subnetResponse = createVpcSubnetInternal (associatedVpc , vNetName , vnetCidr , netrisSubnetName );
325338 if (subnetResponse == null || !subnetResponse .isIsSuccess ()) {
326339 String reason = subnetResponse == null ? "Empty response" : "Operation failed on Netris" ;
327- logger .debug ("The Netris Subnet {} for VPC {} for network {} creation failed: {}" , vnetCidr , vpcName , networkName , reason );
340+ logger .debug ("The Netris Subnet {} for network {} creation failed: {}" , vnetCidr , networkName , reason );
328341 return false ;
329342 }
330- logger .debug ("Successfully created VPC {} and its IPAM Subnet {} on Netris" , vpcName , vnetCidr );
343+ logger .debug ("Successfully created IPAM Subnet {} for network {} on Netris" , netrisSubnetName , networkName );
331344
332345 VnetResAddBody vnetResponse = createVnetInternal (associatedVpc , netrisVnetName , vnetCidr );
333346 if (vnetResponse == null || !vnetResponse .isIsSuccess ()) {
334347 String reason = vnetResponse == null ? "Empty response" : "Operation failed on Netris" ;
335- logger .debug ("The Netris vNet creation {} for VPC {} failed: {}" , vNetName , vpcName , reason );
348+ logger .debug ("The Netris vNet creation {} failed: {}" , vNetName , reason );
336349 return false ;
337350 }
338351 return true ;
339352 }
340353
354+ @ Override
355+ public boolean deleteVnet (DeleteNetrisVnetCommand cmd ) {
356+ String vpcName = cmd .getVpcName ();
357+ Long vpcId = cmd .getVpcId ();
358+ String networkName = cmd .getName ();
359+ Long networkId = cmd .getId ();
360+ boolean isVpc = cmd .isVpc ();
361+ String vnetCidr = cmd .getVNetCidr ();
362+ try {
363+ String suffix = getNetrisVpcNameSuffix (vpcId , vpcName , networkId , networkName , isVpc );
364+ String netrisVpcName = NetrisResourceObjectUtils .retrieveNetrisResourceObjectName (cmd , NetrisResourceObjectUtils .NetrisObjectType .VPC , suffix );
365+ VPCListing associatedVpc = getVpcByNameAndTenant (netrisVpcName );
366+ if (associatedVpc == null ) {
367+ logger .error ("Failed to find Netris VPC with name: {}, to create the corresponding vNet for network {}" , netrisVpcName , networkName );
368+ return false ;
369+ }
370+
371+ String vNetName ;
372+ if (isVpc ) {
373+ vNetName = String .format ("V%s-N%s-%s" , vpcId , networkId , networkName );
374+ } else {
375+ vNetName = String .format ("N%s-%s" , networkId , networkName );
376+ }
377+
378+ String netrisVnetName = NetrisResourceObjectUtils .retrieveNetrisResourceObjectName (cmd , NetrisResourceObjectUtils .NetrisObjectType .VNET , vNetName ) ;
379+ String netrisSubnetName = NetrisResourceObjectUtils .retrieveNetrisResourceObjectName (cmd , NetrisResourceObjectUtils .NetrisObjectType .IPAM_SUBNET , vnetCidr ) ;
380+ FilterByVpc vpcFilter = new FilterByVpc ();
381+ vpcFilter .add (associatedVpc .getId ());
382+ FilterBySites siteFilter = new FilterBySites ();
383+ siteFilter .add (siteId );
384+ deleteVnetInternal (associatedVpc , siteFilter , vpcFilter , netrisVnetName , vNetName );
385+
386+ logger .debug ("Successfully deleted vNet {}" , vNetName );
387+ deleteSubnetInternal (vpcFilter , netrisVnetName , netrisSubnetName );
388+
389+ } catch (Exception e ) {
390+ throw new CloudRuntimeException (String .format ("Failed to delete Netris vNet %s" , networkName ), e );
391+ }
392+ return true ;
393+ }
394+
395+ private void deleteVnetInternal (VPCListing associatedVpc , FilterBySites siteFilter , FilterByVpc vpcFilter , String netrisVnetName , String vNetName ) {
396+ try {
397+ VNetApi vNetApi = apiClient .getApiStubForMethod (VNetApi .class );
398+ VnetResListBody vnetList = vNetApi .apiV2VnetGet (siteFilter , vpcFilter );
399+ if (vnetList == null || !vnetList .isIsSuccess ()) {
400+ throw new CloudRuntimeException (String .format ("Failed to list vNets for the given VPC: %s and site: %s" , associatedVpc .getName (), siteName ));
401+ }
402+ List <VnetsBody > vnetsList = vnetList .getData ().stream ().filter (vnet -> vnet .getName ().equals (netrisVnetName )).collect (Collectors .toList ());
403+ if (CollectionUtils .isEmpty (vnetsList )) {
404+ logger .debug ("vNet: {} for the given VPC: {} appears to already be deleted on Netris" , vNetName , associatedVpc .getName ());
405+ return ;
406+ }
407+ VnetsBody vnetsBody = vnetsList .get (0 );
408+
409+ VnetResDeleteBody deleteVnetResponse = vNetApi .apiV2VnetIdDelete (vnetsBody .getId ().intValue ());
410+ if (deleteVnetResponse == null || !deleteVnetResponse .isIsSuccess ()) {
411+ throw new CloudRuntimeException (String .format ("Failed to delete vNet: %s" , vNetName ));
412+ }
413+ } catch (ApiException e ) {
414+ logAndThrowException (String .format ("Failed to delete vNet: %s" , netrisVnetName ), e );
415+ }
416+ }
417+
418+ private void deleteSubnetInternal (FilterByVpc vpcFilter , String netrisVnetName , String netrisSubnetName ) {
419+ try {
420+ logger .debug ("Deleting Netris VPC IPAM Subnet {} for vNet: {}" , netrisSubnetName , netrisVnetName );
421+ IpamApi ipamApi = apiClient .getApiStubForMethod (IpamApi .class );
422+ SubnetResBody subnetsResponse = ipamApi .apiV2IpamSubnetsGet (vpcFilter );
423+ List <IpTreeSubnet > subnets = subnetsResponse .getData ();
424+ List <IpTreeSubnet > matchedSubnets = subnets .stream ().filter (subnet -> subnet .getName ().equals (netrisSubnetName )).collect (Collectors .toList ());
425+ if (CollectionUtils .isEmpty (matchedSubnets )) {
426+ logger .debug ("IPAM subnet: {} for the given vNet: {} appears to already be deleted on Netris" , netrisSubnetName , netrisVnetName );
427+ return ;
428+ }
429+
430+ ipamApi .apiV2IpamTypeIdDelete ("subnet" , matchedSubnets .get (0 ).getId ().intValue ());
431+ } catch (ApiException e ) {
432+ logAndThrowException (String .format ("Failed to delete vNet: %s" , netrisVnetName ), e );
433+ }
434+ }
435+
341436 private InlineResponse2004 createVpcSubnetInternal (VPCListing associatedVpc , String vNetName , String vNetCidr , String netrisSubnetName ) {
342437 logger .debug ("Creating Netris VPC Subnet {} for VPC {} for vNet {}" , vNetCidr , associatedVpc .getName (), vNetName );
343438 try {
@@ -427,4 +522,13 @@ VnetResAddBody createVnetInternal(VPCListing associatedVpc, String netrisVnetNam
427522 return null ;
428523 }
429524 }
525+
526+ private String getNetrisVpcNameSuffix (Long vpcId , String vpcName , Long networkId , String networkName , boolean isVpc ) {
527+ String suffix = null ;
528+ if (isVpc ) {
529+ suffix = String .format ("%s-%s" , vpcId , vpcName );
530+ } else {
531+ suffix = String .format ("%s-%s" , networkId , networkName );
532+ }
533+ }
430534}
0 commit comments