NSX: Improve segment deletion process (#8538)

This commit is contained in:
Nicolas Vazquez 2024-01-19 16:59:05 -03:00 committed by GitHub
parent 330c99ca57
commit f01bb5d440
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 62 additions and 58 deletions

View File

@ -30,9 +30,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.vmware.nsx.model.TransportZone;
import com.vmware.nsx.model.TransportZoneListResult;
import com.vmware.nsx_policy.model.EnforcementPointListResult;
import com.vmware.nsx_policy.model.Segment;
import com.vmware.nsx_policy.model.SiteListResult;
import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.StartupNsxCommand;
import org.apache.cloudstack.agent.api.CreateNsxDhcpRelayConfigCommand;
@ -320,33 +318,17 @@ public class NsxResource implements ServerResource {
private Answer executeRequest(CreateNsxSegmentCommand cmd) {
try {
SiteListResult sites = nsxApiClient.getSites();
String errorMsg;
String networkName = cmd.getNetworkName();
if (CollectionUtils.isEmpty(sites.getResults())) {
errorMsg = String.format("Failed to create network: %s as no sites are found in the linked NSX infrastructure", networkName);
LOGGER.error(errorMsg);
return new NsxAnswer(cmd, new CloudRuntimeException(errorMsg));
}
String siteId = sites.getResults().get(0).getId();
EnforcementPointListResult epList = nsxApiClient.getEnforcementPoints(siteId);
if (CollectionUtils.isEmpty(epList.getResults())) {
errorMsg = String.format("Failed to create network: %s as no enforcement points are found in the linked NSX infrastructure", networkName);
LOGGER.error(errorMsg);
return new NsxAnswer(cmd, new CloudRuntimeException(errorMsg));
}
String enforcementPointPath = epList.getResults().get(0).getPath();
String siteId = nsxApiClient.getDefaultSiteId();
String enforcementPointPath = nsxApiClient.getDefaultEnforcementPointPath(siteId);
TransportZoneListResult transportZoneListResult = nsxApiClient.getTransportZones();
if (CollectionUtils.isEmpty(transportZoneListResult.getResults())) {
errorMsg = String.format("Failed to create network: %s as no transport zones were found in the linked NSX infrastructure", networkName);
String errorMsg = String.format("Failed to create network: %s as no transport zones were found in the linked NSX infrastructure", cmd.getNetworkName());
LOGGER.error(errorMsg);
return new NsxAnswer(cmd, new CloudRuntimeException(errorMsg));
}
List<TransportZone> transportZones = transportZoneListResult.getResults().stream().filter(tz -> tz.getDisplayName().equals(transportZone)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(transportZones)) {
errorMsg = String.format("Failed to create network: %s as no transport zone of name %s was found in the linked NSX infrastructure", networkName, transportZone);
String errorMsg = String.format("Failed to create network: %s as no transport zone of name %s was found in the linked NSX infrastructure", cmd.getNetworkName(), transportZone);
LOGGER.error(errorMsg);
return new NsxAnswer(cmd, new CloudRuntimeException(errorMsg));
}
@ -371,14 +353,9 @@ public class NsxResource implements ServerResource {
String segmentName = NsxControllerUtils.getNsxSegmentId(cmd.getDomainId(), cmd.getAccountId(), cmd.getZoneId(),
cmd.getVpcId(), cmd.getNetworkId());
try {
Thread.sleep(30 * 1000L);
nsxApiClient.deleteSegment(cmd.getZoneId(), cmd.getDomainId(), cmd.getAccountId(), cmd.getVpcId(), cmd.getNetworkId(), segmentName);
} catch (InterruptedException | ThreadDeath e) {
LOGGER.error("Thread interrupted", e);
Thread.currentThread().interrupt();
return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage()));
} catch (Exception e) {
LOGGER.error(String.format("Failed to delete NSX segment: %s", segmentName));
LOGGER.error(String.format("Failed to delete NSX segment %s: %s", segmentName, e.getMessage()));
return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage()));
}
return new NsxAnswer(cmd, true, null);
@ -485,7 +462,7 @@ public class NsxResource implements ServerResource {
try {
nsxApiClient.deleteDistributedFirewallRules(segmentName, rules);
} catch (Exception e) {
LOGGER.error(String.format("Failed to create NSX distributed firewall %s: %s", segmentName, e.getMessage()), e);
LOGGER.error(String.format("Failed to delete NSX distributed firewall %s: %s", segmentName, e.getMessage()), e);
return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage()));
}
return new NsxAnswer(cmd, true, null);

View File

@ -31,6 +31,7 @@ import com.vmware.nsx_policy.infra.Sites;
import com.vmware.nsx_policy.infra.Tier1s;
import com.vmware.nsx_policy.infra.domains.Groups;
import com.vmware.nsx_policy.infra.domains.SecurityPolicies;
import com.vmware.nsx_policy.infra.domains.groups.members.SegmentPorts;
import com.vmware.nsx_policy.infra.domains.security_policies.Rules;
import com.vmware.nsx_policy.infra.sites.EnforcementPoints;
import com.vmware.nsx_policy.infra.tier_0s.LocaleServices;
@ -51,6 +52,7 @@ import com.vmware.nsx_policy.model.LBVirtualServer;
import com.vmware.nsx_policy.model.LBVirtualServerListResult;
import com.vmware.nsx_policy.model.LocaleServicesListResult;
import com.vmware.nsx_policy.model.PathExpression;
import com.vmware.nsx_policy.model.PolicyGroupMembersListResult;
import com.vmware.nsx_policy.model.PolicyNatRule;
import com.vmware.nsx_policy.model.PolicyNatRuleListResult;
import com.vmware.nsx_policy.model.Rule;
@ -343,7 +345,17 @@ public class NsxApiClient {
}
public SiteListResult getSites() {
public String getDefaultSiteId() {
SiteListResult sites = getSites();
if (CollectionUtils.isEmpty(sites.getResults())) {
String errorMsg = "No sites are found in the linked NSX infrastructure";
LOGGER.error(errorMsg);
throw new CloudRuntimeException(errorMsg);
}
return sites.getResults().get(0).getId();
}
protected SiteListResult getSites() {
try {
Sites sites = (Sites) nsxService.apply(Sites.class);
return sites.list(null, false, null, null, null, null);
@ -352,7 +364,17 @@ public class NsxApiClient {
}
}
public EnforcementPointListResult getEnforcementPoints(String siteId) {
public String getDefaultEnforcementPointPath(String siteId) {
EnforcementPointListResult epList = getEnforcementPoints(siteId);
if (CollectionUtils.isEmpty(epList.getResults())) {
String errorMsg = String.format("No enforcement points are found in the linked NSX infrastructure for site ID %s", siteId);
LOGGER.error(errorMsg);
throw new CloudRuntimeException(errorMsg);
}
return epList.getResults().get(0).getPath();
}
protected EnforcementPointListResult getEnforcementPoints(String siteId) {
try {
EnforcementPoints enforcementPoints = (EnforcementPoints) nsxService.apply(EnforcementPoints.class);
return enforcementPoints.list(siteId, null, false, null, null, null, null);
@ -397,11 +419,8 @@ public class NsxApiClient {
public void deleteSegment(long zoneId, long domainId, long accountId, Long vpcId, long networkId, String segmentName) {
try {
Segments segmentService = (Segments) nsxService.apply(Segments.class);
removeSegmentDistributedFirewallRules(segmentName);
removeGroupForSegment(segmentName);
LOGGER.debug(String.format("Removing the segment with ID %s", segmentName));
segmentService.delete(segmentName);
removeSegment(segmentName);
DhcpRelayConfigs dhcpRelayConfig = (DhcpRelayConfigs) nsxService.apply(DhcpRelayConfigs.class);
String dhcpRelayConfigId = NsxControllerUtils.getNsxDhcpRelayConfigId(zoneId, domainId, accountId, vpcId, networkId);
LOGGER.debug(String.format("Removing the DHCP relay config with ID %s", dhcpRelayConfigId));
@ -414,6 +433,30 @@ public class NsxApiClient {
}
}
protected void removeSegment(String segmentName) {
LOGGER.debug(String.format("Removing the segment with ID %s", segmentName));
Segments segmentService = (Segments) nsxService.apply(Segments.class);
Segment segment = segmentService.get(segmentName);
if (segment == null) {
LOGGER.error(String.format("The segment with ID %s is not found, skipping removal", segmentName));
return;
}
String siteId = getDefaultSiteId();
String enforcementPointPath = getDefaultEnforcementPointPath(siteId);
SegmentPorts segmentPortsService = (SegmentPorts) nsxService.apply(SegmentPorts.class);
PolicyGroupMembersListResult segmentPortsList = segmentPortsService.list(DEFAULT_DOMAIN, segmentName, null, enforcementPointPath,
false, null, 50L, false, null);
if (segmentPortsList.getResultCount() == 0L) {
LOGGER.debug(String.format("Removing the segment with ID %s", segmentName));
removeGroupForSegment(segmentName);
segmentService.delete(segmentName);
} else {
String msg = String.format("Cannot remove the NSX segment %s because there are still %s port group(s) attached to it", segmentName, segmentPortsList.getResultCount());
LOGGER.debug(msg);
throw new CloudRuntimeException(msg);
}
}
public void createStaticNatRule(String vpcName, String tier1GatewayName,
String ruleName, String publicIp, String vmIp) {
try {

View File

@ -109,7 +109,7 @@ public class NsxServiceImpl implements NsxService {
network.getVpcId(), vpcName, network.getId(), network.getName());
NsxAnswer result = nsxControllerUtils.sendNsxCommand(deleteNsxSegmentCommand, network.getDataCenterId());
if (!result.getResult()) {
String msg = String.format("Could not remove the NSX segment for network %s", network.getName());
String msg = String.format("Could not remove the NSX segment for network %s: %s", network.getName(), result.getDetails());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}

View File

@ -21,9 +21,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.vmware.nsx.model.TransportZone;
import com.vmware.nsx.model.TransportZoneListResult;
import com.vmware.nsx_policy.model.EnforcementPoint;
import com.vmware.nsx_policy.model.EnforcementPointListResult;
import com.vmware.nsx_policy.model.Site;
import com.vmware.nsx_policy.model.SiteListResult;
import junit.framework.Assert;
import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.agent.api.CreateNsxDistributedFirewallRulesCommand;
@ -74,10 +72,6 @@ public class NsxResourceTest {
NsxResource nsxResource;
AutoCloseable closeable;
@Mock
EnforcementPointListResult enforcementPointListResult;
@Mock
SiteListResult siteListResult;
@Mock
TransportZoneListResult transportZoneListResult;
private static final String transportZone = "Overlay";
@ -177,13 +171,9 @@ public class NsxResourceTest {
NsxCommand command = new CreateNsxSegmentCommand(domainId, accountId, zoneId,
2L, "VPC01", 3L, "Web", "10.10.10.1", "10.10.10.0/24");
when(nsxApi.getSites()).thenReturn(siteListResult);
when(siteListResult.getResults()).thenReturn(siteList);
when(siteList.get(0).getId()).thenReturn("site1");
when(nsxApi.getDefaultSiteId()).thenReturn("site1");
when(nsxApi.getEnforcementPoints(anyString())).thenReturn(enforcementPointListResult);
when(enforcementPointListResult.getResults()).thenReturn(enforcementPointList);
when(enforcementPointList.get(0).getPath()).thenReturn("enforcementPointPath");
when(nsxApi.getDefaultEnforcementPointPath(anyString())).thenReturn("enforcementPointPath");
when(nsxApi.getTransportZones()).thenReturn(transportZoneListResult);
when(transportZoneListResult.getResults()).thenReturn(transportZoneList);
@ -194,7 +184,7 @@ public class NsxResourceTest {
@Test
public void testCreateNsxSegmentEmptySites() {
when(nsxApi.getSites()).thenReturn(null);
when(nsxApi.getDefaultSiteId()).thenReturn(null);
CreateNsxSegmentCommand command = Mockito.mock(CreateNsxSegmentCommand.class);
NsxAnswer answer = (NsxAnswer) nsxResource.executeRequest(command);
assertFalse(answer.getResult());
@ -203,11 +193,8 @@ public class NsxResourceTest {
@Test
public void testCreateNsxSegmentEmptyEnforcementPoints() {
Site site = mock(Site.class);
List<Site> siteList = List.of(site);
when(nsxApi.getSites()).thenReturn(siteListResult);
when(siteListResult.getResults()).thenReturn(siteList);
when(siteList.get(0).getId()).thenReturn("site1");
when(nsxApi.getEnforcementPoints(anyString())).thenReturn(null);
when(nsxApi.getDefaultSiteId()).thenReturn("site1");
when(nsxApi.getDefaultEnforcementPointPath(anyString())).thenReturn(null);
CreateNsxSegmentCommand command = Mockito.mock(CreateNsxSegmentCommand.class);
NsxAnswer answer = (NsxAnswer) nsxResource.executeRequest(command);
assertFalse(answer.getResult());
@ -216,10 +203,7 @@ public class NsxResourceTest {
@Test
public void testCreateNsxSegmentEmptyTransportZones() {
Site site = mock(Site.class);
List<Site> siteList = List.of(site);
when(nsxApi.getSites()).thenReturn(siteListResult);
when(siteListResult.getResults()).thenReturn(siteList);
when(siteList.get(0).getId()).thenReturn("site1");
when(nsxApi.getDefaultSiteId()).thenReturn("site1");
CreateNsxSegmentCommand command = Mockito.mock(CreateNsxSegmentCommand.class);
NsxAnswer answer = (NsxAnswer) nsxResource.executeRequest(command);
assertFalse(answer.getResult());