Skip to content

Commit 9e46c65

Browse files
committed
NSX: support segment discovery and security profiles
1 parent 4f11707 commit 9e46c65

14 files changed

Lines changed: 425 additions & 7 deletions

File tree

api/src/main/java/com/cloud/offering/NetworkOffering.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ public enum State {
4040
}
4141

4242
public enum Detail {
43-
InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, MacLearning, RelatedNetworkOffering, domainid, zoneid, pvlanType, internetProtocol
43+
InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, MacLearning,
44+
NsxIpDiscoveryProfileId, NsxMacDiscoveryProfileId, NsxSegmentSecurityProfileId,
45+
RelatedNetworkOffering, domainid, zoneid, pvlanType, internetProtocol
4446
}
4547

4648
public enum NetworkMode {

plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/CreateNsxSegmentCommand.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,31 @@ public class CreateNsxSegmentCommand extends NsxCommand {
2626
private String networkName;
2727
private String networkGateway;
2828
private String networkCidr;
29+
private String ipDiscoveryProfileId;
30+
private String macDiscoveryProfileId;
31+
private String segmentSecurityProfileId;
2932

3033
public CreateNsxSegmentCommand(long domainId, long accountId, long zoneId,
3134
Long vpcId, String vpcName, long networkId, String networkName,
3235
String networkGateway, String networkCidr) {
36+
this(domainId, accountId, zoneId, vpcId, vpcName, networkId, networkName, networkGateway,
37+
networkCidr, null, null, null);
38+
}
39+
40+
public CreateNsxSegmentCommand(long domainId, long accountId, long zoneId,
41+
Long vpcId, String vpcName, long networkId, String networkName,
42+
String networkGateway, String networkCidr, String ipDiscoveryProfileId,
43+
String macDiscoveryProfileId, String segmentSecurityProfileId) {
3344
super(domainId, accountId, zoneId);
3445
this.vpcId = vpcId;
3546
this.vpcName = vpcName;
3647
this.networkId = networkId;
3748
this.networkName = networkName;
3849
this.networkGateway = networkGateway;
3950
this.networkCidr = networkCidr;
51+
this.ipDiscoveryProfileId = ipDiscoveryProfileId;
52+
this.macDiscoveryProfileId = macDiscoveryProfileId;
53+
this.segmentSecurityProfileId = segmentSecurityProfileId;
4054
}
4155

4256
public Long getVpcId() {
@@ -63,6 +77,18 @@ public String getNetworkCidr() {
6377
return networkCidr;
6478
}
6579

80+
public String getIpDiscoveryProfileId() {
81+
return ipDiscoveryProfileId;
82+
}
83+
84+
public String getMacDiscoveryProfileId() {
85+
return macDiscoveryProfileId;
86+
}
87+
88+
public String getSegmentSecurityProfileId() {
89+
return segmentSecurityProfileId;
90+
}
91+
6692
@Override
6793
public boolean equals(Object o) {
6894
if (this == o) return true;

plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,8 @@ private Answer executeRequest(CreateNsxSegmentCommand cmd) {
351351
boolean isResourceVpc = !Objects.isNull(cmd.getVpcId());
352352
String tier1GatewayName = NsxControllerUtils.getTier1GatewayName(cmd.getDomainId(), cmd.getAccountId(),
353353
cmd.getZoneId(), networkResourceId, isResourceVpc);
354-
nsxApiClient.createSegment(segmentName, tier1GatewayName, gatewayAddress, enforcementPointPath, transportZones);
354+
nsxApiClient.createSegment(segmentName, tier1GatewayName, gatewayAddress, enforcementPointPath, transportZones,
355+
cmd.getIpDiscoveryProfileId(), cmd.getMacDiscoveryProfileId(), cmd.getSegmentSecurityProfileId());
355356
nsxApiClient.createGroupForSegment(segmentName);
356357
} catch (Exception e) {
357358
logger.error(String.format("Failed to create network: %s", cmd.getNetworkName()));

plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@
2626
import com.vmware.nsx.model.TransportZone;
2727
import com.vmware.nsx.model.TransportZoneListResult;
2828
import com.vmware.nsx_policy.infra.DhcpRelayConfigs;
29+
import com.vmware.nsx_policy.infra.IpDiscoveryProfiles;
2930
import com.vmware.nsx_policy.infra.LbAppProfiles;
3031
import com.vmware.nsx_policy.infra.LbMonitorProfiles;
3132
import com.vmware.nsx_policy.infra.LbPools;
3233
import com.vmware.nsx_policy.infra.LbServices;
3334
import com.vmware.nsx_policy.infra.LbVirtualServers;
35+
import com.vmware.nsx_policy.infra.MacDiscoveryProfiles;
36+
import com.vmware.nsx_policy.infra.SegmentSecurityProfiles;
3437
import com.vmware.nsx_policy.infra.Segments;
3538
import com.vmware.nsx_policy.infra.Services;
3639
import com.vmware.nsx_policy.infra.Sites;
@@ -39,6 +42,8 @@
3942
import com.vmware.nsx_policy.infra.domains.SecurityPolicies;
4043
import com.vmware.nsx_policy.infra.domains.groups.members.SegmentPorts;
4144
import com.vmware.nsx_policy.infra.domains.security_policies.Rules;
45+
import com.vmware.nsx_policy.infra.segments.SegmentDiscoveryProfileBindingMaps;
46+
import com.vmware.nsx_policy.infra.segments.SegmentSecurityProfileBindingMaps;
4247
import com.vmware.nsx_policy.infra.sites.EnforcementPoints;
4348
import com.vmware.nsx_policy.infra.tier_0s.LocaleServices;
4449
import com.vmware.nsx_policy.infra.tier_1s.nat.NatRules;
@@ -49,6 +54,7 @@
4954
import com.vmware.nsx_policy.model.Group;
5055
import com.vmware.nsx_policy.model.GroupListResult;
5156
import com.vmware.nsx_policy.model.ICMPTypeServiceEntry;
57+
import com.vmware.nsx_policy.model.IPDiscoveryProfile;
5258
import com.vmware.nsx_policy.model.L4PortSetServiceEntry;
5359
import com.vmware.nsx_policy.model.LBAppProfileListResult;
5460
import com.vmware.nsx_policy.model.LBIcmpMonitorProfile;
@@ -61,6 +67,7 @@
6167
import com.vmware.nsx_policy.model.LBVirtualServer;
6268
import com.vmware.nsx_policy.model.LBVirtualServerListResult;
6369
import com.vmware.nsx_policy.model.LocaleServicesListResult;
70+
import com.vmware.nsx_policy.model.MacDiscoveryProfile;
6471
import com.vmware.nsx_policy.model.PathExpression;
6572
import com.vmware.nsx_policy.model.PolicyGroupMembersListResult;
6673
import com.vmware.nsx_policy.model.PolicyNatRule;
@@ -69,6 +76,9 @@
6976
import com.vmware.nsx_policy.model.Rule;
7077
import com.vmware.nsx_policy.model.SecurityPolicy;
7178
import com.vmware.nsx_policy.model.Segment;
79+
import com.vmware.nsx_policy.model.SegmentDiscoveryProfileBindingMap;
80+
import com.vmware.nsx_policy.model.SegmentSecurityProfile;
81+
import com.vmware.nsx_policy.model.SegmentSecurityProfileBindingMap;
7282
import com.vmware.nsx_policy.model.SegmentSubnet;
7383
import com.vmware.nsx_policy.model.ServiceListResult;
7484
import com.vmware.nsx_policy.model.Site;
@@ -90,9 +100,10 @@
90100
import org.apache.cloudstack.resource.NsxNetworkRule;
91101
import org.apache.cloudstack.utils.NsxControllerUtils;
92102
import org.apache.commons.collections.CollectionUtils;
103+
import org.apache.commons.lang3.BooleanUtils;
104+
import org.apache.commons.lang3.StringUtils;
93105
import org.apache.logging.log4j.LogManager;
94106
import org.apache.logging.log4j.Logger;
95-
import org.apache.commons.lang3.BooleanUtils;
96107

97108
import java.util.ArrayList;
98109
import java.util.List;
@@ -128,6 +139,8 @@ public class NsxApiClient {
128139
private static final String TIER_1_RESOURCE_TYPE = "Tier1";
129140
private static final String TIER_1_LOCALE_SERVICE_ID = "default";
130141
private static final String SEGMENT_RESOURCE_TYPE = "Segment";
142+
private static final String SEGMENT_DISCOVERY_PROFILE_BINDING_ID = "cloudstack-discovery-profile-binding";
143+
private static final String SEGMENT_SECURITY_PROFILE_BINDING_ID = "cloudstack-security-profile-binding";
131144
private static final String TIER_0_GATEWAY_PATH_PREFIX = "/infra/tier-0s/";
132145
private static final String TIER_1_GATEWAY_PATH_PREFIX = "/infra/tier-1s/";
133146
protected static final String SEGMENTS_PATH = "/infra/segments";
@@ -466,7 +479,16 @@ public TransportZoneListResult getTransportZones() {
466479

467480
public void createSegment(String segmentName, String tier1GatewayName, String gatewayAddress, String enforcementPointPath,
468481
List<TransportZone> transportZones) {
482+
createSegment(segmentName, tier1GatewayName, gatewayAddress, enforcementPointPath, transportZones, null, null, null);
483+
}
484+
485+
public void createSegment(String segmentName, String tier1GatewayName, String gatewayAddress, String enforcementPointPath,
486+
List<TransportZone> transportZones, String ipDiscoveryProfileId, String macDiscoveryProfileId,
487+
String segmentSecurityProfileId) {
469488
try {
489+
String ipDiscoveryProfilePath = getIpDiscoveryProfilePath(ipDiscoveryProfileId);
490+
String macDiscoveryProfilePath = getMacDiscoveryProfilePath(macDiscoveryProfileId);
491+
String segmentSecurityProfilePath = getSegmentSecurityProfilePath(segmentSecurityProfileId);
470492
Segments segmentService = (Segments) nsxService.apply(Segments.class);
471493
SegmentSubnet subnet = new SegmentSubnet.Builder()
472494
.setGatewayAddress(gatewayAddress)
@@ -481,6 +503,7 @@ public void createSegment(String segmentName, String tier1GatewayName, String ga
481503
.setTransportZonePath(enforcementPointPath + "/transport-zones/" + transportZones.get(0).getId())
482504
.build();
483505
segmentService.patch(segmentName, segment);
506+
bindSegmentProfiles(segmentName, ipDiscoveryProfilePath, macDiscoveryProfilePath, segmentSecurityProfilePath);
484507
} catch (Error error) {
485508
ApiError ae = error.getData()._convertTo(ApiError.class);
486509
String msg = String.format("Error creating segment %s: %s", segmentName, ae.getErrorMessage());
@@ -489,6 +512,63 @@ public void createSegment(String segmentName, String tier1GatewayName, String ga
489512
}
490513
}
491514

515+
protected String getIpDiscoveryProfilePath(String profileId) {
516+
if (StringUtils.isBlank(profileId)) {
517+
return null;
518+
}
519+
IpDiscoveryProfiles profiles = (IpDiscoveryProfiles) nsxService.apply(IpDiscoveryProfiles.class);
520+
IPDiscoveryProfile profile = profiles.get(profileId);
521+
return validateProfilePath(profileId, profile.getPath());
522+
}
523+
524+
protected String getMacDiscoveryProfilePath(String profileId) {
525+
if (StringUtils.isBlank(profileId)) {
526+
return null;
527+
}
528+
MacDiscoveryProfiles profiles = (MacDiscoveryProfiles) nsxService.apply(MacDiscoveryProfiles.class);
529+
MacDiscoveryProfile profile = profiles.get(profileId);
530+
return validateProfilePath(profileId, profile.getPath());
531+
}
532+
533+
protected String getSegmentSecurityProfilePath(String profileId) {
534+
if (StringUtils.isBlank(profileId)) {
535+
return null;
536+
}
537+
SegmentSecurityProfiles profiles = (SegmentSecurityProfiles) nsxService.apply(SegmentSecurityProfiles.class);
538+
SegmentSecurityProfile profile = profiles.get(profileId);
539+
return validateProfilePath(profileId, profile.getPath());
540+
}
541+
542+
protected String validateProfilePath(String profileId, String profilePath) {
543+
if (StringUtils.isBlank(profilePath)) {
544+
throw new CloudRuntimeException(String.format("NSX profile %s did not return a canonical resource path", profileId));
545+
}
546+
return profilePath;
547+
}
548+
549+
protected void bindSegmentProfiles(String segmentName, String ipDiscoveryProfilePath, String macDiscoveryProfilePath,
550+
String segmentSecurityProfilePath) {
551+
if (StringUtils.isNotBlank(ipDiscoveryProfilePath) || StringUtils.isNotBlank(macDiscoveryProfilePath)) {
552+
SegmentDiscoveryProfileBindingMaps discoveryBindings =
553+
(SegmentDiscoveryProfileBindingMaps) nsxService.apply(SegmentDiscoveryProfileBindingMaps.class);
554+
SegmentDiscoveryProfileBindingMap binding = new SegmentDiscoveryProfileBindingMap.Builder()
555+
.setId(SEGMENT_DISCOVERY_PROFILE_BINDING_ID)
556+
.setIpDiscoveryProfilePath(ipDiscoveryProfilePath)
557+
.setMacDiscoveryProfilePath(macDiscoveryProfilePath)
558+
.build();
559+
discoveryBindings.patch(segmentName, SEGMENT_DISCOVERY_PROFILE_BINDING_ID, binding);
560+
}
561+
if (StringUtils.isNotBlank(segmentSecurityProfilePath)) {
562+
SegmentSecurityProfileBindingMaps securityBindings =
563+
(SegmentSecurityProfileBindingMaps) nsxService.apply(SegmentSecurityProfileBindingMaps.class);
564+
SegmentSecurityProfileBindingMap binding = new SegmentSecurityProfileBindingMap.Builder()
565+
.setId(SEGMENT_SECURITY_PROFILE_BINDING_ID)
566+
.setSegmentSecurityProfilePath(segmentSecurityProfilePath)
567+
.build();
568+
securityBindings.patch(segmentName, SEGMENT_SECURITY_PROFILE_BINDING_ID, binding);
569+
}
570+
}
571+
492572
public void deleteSegment(long zoneId, long domainId, long accountId, Long vpcId, long networkId, String segmentName) {
493573
try {
494574
removeSegmentDistributedFirewallRules(segmentName);

plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxGuestNetworkGuru.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959

6060
import javax.inject.Inject;
6161
import java.util.List;
62+
import java.util.Map;
6263
import java.util.Objects;
6364

6465
public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigrationResponder {
@@ -324,10 +325,19 @@ public void createNsxSegment(NetworkVO networkVO, DataCenter zone) {
324325
throw new CloudRuntimeException(msg);
325326
}
326327
}
327-
CreateNsxSegmentCommand command = NsxHelper.createNsxSegmentCommand(domain, account, zone, vpcName, networkVO);
328+
Map<NetworkOffering.Detail, String> offeringDetails = _networkModel.getNtwkOffDetails(networkVO.getNetworkOfferingId());
329+
String ipDiscoveryProfile = getOfferingDetail(offeringDetails, NetworkOffering.Detail.NsxIpDiscoveryProfileId);
330+
String macDiscoveryProfile = getOfferingDetail(offeringDetails, NetworkOffering.Detail.NsxMacDiscoveryProfileId);
331+
String segmentSecurityProfile = getOfferingDetail(offeringDetails, NetworkOffering.Detail.NsxSegmentSecurityProfileId);
332+
CreateNsxSegmentCommand command = NsxHelper.createNsxSegmentCommand(domain, account, zone, vpcName, networkVO,
333+
ipDiscoveryProfile, macDiscoveryProfile, segmentSecurityProfile);
328334
NsxAnswer answer = nsxControllerUtils.sendNsxCommand(command, zone.getId());
329335
if (!answer.getResult()) {
330336
throw new CloudRuntimeException("can not create NSX network");
331337
}
332338
}
339+
340+
protected String getOfferingDetail(Map<NetworkOffering.Detail, String> offeringDetails, NetworkOffering.Detail detail) {
341+
return offeringDetails == null ? null : offeringDetails.get(detail);
342+
}
333343
}

plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/utils/NsxHelper.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,14 @@ public static CreateNsxDhcpRelayConfigCommand createNsxDhcpRelayConfigCommand(Do
4141
}
4242

4343
public static CreateNsxSegmentCommand createNsxSegmentCommand(DomainVO domain, Account account, DataCenter zone, String vpcName, NetworkVO networkVO) {
44+
return createNsxSegmentCommand(domain, account, zone, vpcName, networkVO, null, null, null);
45+
}
46+
47+
public static CreateNsxSegmentCommand createNsxSegmentCommand(DomainVO domain, Account account, DataCenter zone, String vpcName, NetworkVO networkVO,
48+
String ipDiscoveryProfileId, String macDiscoveryProfileId, String segmentSecurityProfileId) {
4449
return new CreateNsxSegmentCommand(domain.getId(), account.getId(), zone.getId(),
45-
networkVO.getVpcId(), vpcName, networkVO.getId(), networkVO.getName(), networkVO.getGateway(), networkVO.getCidr());
50+
networkVO.getVpcId(), vpcName, networkVO.getId(), networkVO.getName(), networkVO.getGateway(), networkVO.getCidr(),
51+
ipDiscoveryProfileId, macDiscoveryProfileId, segmentSecurityProfileId);
4652
}
4753

4854
public static CreateOrUpdateNsxTier1NatRuleCommand createOrUpdateNsxNatRuleCommand(long domainId, long accountId, long zoneId,

plugins/network-elements/nsx/src/test/java/org/apache/cloudstack/resource/NsxResourceTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import static org.mockito.ArgumentMatchers.anyBoolean;
6161
import static org.mockito.ArgumentMatchers.anyLong;
6262
import static org.mockito.ArgumentMatchers.anyString;
63+
import static org.mockito.ArgumentMatchers.eq;
6364
import static org.mockito.Mockito.doThrow;
6465
import static org.mockito.Mockito.mock;
6566
import static org.mockito.Mockito.verify;
@@ -184,6 +185,24 @@ public void testCreateNsxSegment() {
184185
assertTrue(answer.getResult());
185186
}
186187

188+
@Test
189+
public void testCreateNsxSegmentPassesProfileIdsToApiClient() {
190+
List<TransportZone> transportZoneList = List.of(new TransportZone.Builder().setDisplayName(transportZone).build());
191+
CreateNsxSegmentCommand command = new CreateNsxSegmentCommand(domainId, accountId, zoneId,
192+
2L, "VPC01", 3L, "Web", "10.10.10.1", "10.10.10.0/24",
193+
"ip-profile", "mac-profile", "security-profile");
194+
when(nsxApi.getDefaultSiteId()).thenReturn("site1");
195+
when(nsxApi.getDefaultEnforcementPointPath("site1")).thenReturn("enforcementPointPath");
196+
when(nsxApi.getTransportZones()).thenReturn(transportZoneListResult);
197+
when(transportZoneListResult.getResults()).thenReturn(transportZoneList);
198+
199+
NsxAnswer answer = (NsxAnswer) nsxResource.executeRequest(command);
200+
201+
assertTrue(answer.getResult());
202+
verify(nsxApi).createSegment(anyString(), anyString(), anyString(), eq("enforcementPointPath"),
203+
eq(transportZoneList), eq("ip-profile"), eq("mac-profile"), eq("security-profile"));
204+
}
205+
187206
@Test
188207
public void testCreateNsxSegmentEmptySites() {
189208
when(nsxApi.getDefaultSiteId()).thenReturn(null);

0 commit comments

Comments
 (0)