Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions PendingReleaseNotes
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ example.ver.1 > example.ver.2:
which can now be attached to Instances. This is to prevent the Secondary
Storage to grow to enormous sizes as Linux Distributions keep growing in
size while a stripped down Linux should fit on a 2.88MB floppy.

4.22.1.0 > 4.23.0.0:
* NSX network offerings can reference existing IP discovery, MAC discovery,
and segment security profiles. New NSX segments bind selected profiles in
the same hierarchical request as segment creation. Existing networks are
not silently reconfigured when profile bindings change.
4 changes: 3 additions & 1 deletion api/src/main/java/com/cloud/offering/NetworkOffering.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ public enum State {
}

public enum Detail {
InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, MacLearning, RelatedNetworkOffering, domainid, zoneid, pvlanType, internetProtocol
InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, MacLearning,
NsxIpDiscoveryProfileId, NsxMacDiscoveryProfileId, NsxSegmentSecurityProfileId,
RelatedNetworkOffering, domainid, zoneid, pvlanType, internetProtocol
Comment on lines +43 to +45

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe a good moment to just format one/line? (no req, just suggestion for readability)

}

public enum NetworkMode {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,9 @@ public abstract class NetworkOfferingBaseCmd extends BaseCmd {

@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, since = "4.2.0", description = "Network offering details in key/value pairs."
+ " Supported keys are internallbprovider/publiclbprovider with service provider as a value, and"
+ " promiscuousmode/macaddresschanges/forgedtransmits with true/false as value to accept/reject the security settings if available for a nic/portgroup")
+ " promiscuousmode/macaddresschanges/forgedtransmits with true/false as value to accept/reject the security settings if available for a nic/portgroup."
+ " NSX offerings also support nsxipdiscoveryprofileid, nsxmacdiscoveryprofileid, and nsxsegmentsecurityprofileid."
+ " Values are IDs of existing operator-managed NSX profiles to bind to segments created from the offering.")
protected Map details;

@Parameter(name = ApiConstants.EGRESS_DEFAULT_POLICY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,31 @@ public class CreateNsxSegmentCommand extends NsxCommand {
private String networkName;
private String networkGateway;
private String networkCidr;
private String ipDiscoveryProfileId;
private String macDiscoveryProfileId;
private String segmentSecurityProfileId;

public CreateNsxSegmentCommand(long domainId, long accountId, long zoneId,
Long vpcId, String vpcName, long networkId, String networkName,
String networkGateway, String networkCidr) {
this(domainId, accountId, zoneId, vpcId, vpcName, networkId, networkName, networkGateway,
networkCidr, null, null, null);
}

public CreateNsxSegmentCommand(long domainId, long accountId, long zoneId,
Long vpcId, String vpcName, long networkId, String networkName,
String networkGateway, String networkCidr, String ipDiscoveryProfileId,
String macDiscoveryProfileId, String segmentSecurityProfileId) {
super(domainId, accountId, zoneId);
this.vpcId = vpcId;
this.vpcName = vpcName;
this.networkId = networkId;
this.networkName = networkName;
this.networkGateway = networkGateway;
this.networkCidr = networkCidr;
this.ipDiscoveryProfileId = ipDiscoveryProfileId;
this.macDiscoveryProfileId = macDiscoveryProfileId;
this.segmentSecurityProfileId = segmentSecurityProfileId;
}

public Long getVpcId() {
Expand All @@ -63,6 +77,18 @@ public String getNetworkCidr() {
return networkCidr;
}

public String getIpDiscoveryProfileId() {
return ipDiscoveryProfileId;
}

public String getMacDiscoveryProfileId() {
return macDiscoveryProfileId;
}

public String getSegmentSecurityProfileId() {
return segmentSecurityProfileId;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,8 @@ private Answer executeRequest(CreateNsxSegmentCommand cmd) {
boolean isResourceVpc = !Objects.isNull(cmd.getVpcId());
String tier1GatewayName = NsxControllerUtils.getTier1GatewayName(cmd.getDomainId(), cmd.getAccountId(),
cmd.getZoneId(), networkResourceId, isResourceVpc);
nsxApiClient.createSegment(segmentName, tier1GatewayName, gatewayAddress, enforcementPointPath, transportZones);
nsxApiClient.createSegment(segmentName, tier1GatewayName, gatewayAddress, enforcementPointPath, transportZones,
cmd.getIpDiscoveryProfileId(), cmd.getMacDiscoveryProfileId(), cmd.getSegmentSecurityProfileId());
nsxApiClient.createGroupForSegment(segmentName);
} catch (Exception e) {
logger.error(String.format("Failed to create network: %s", cmd.getNetworkName()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@
import com.vmware.nsx.model.ControllerClusterStatus;
import com.vmware.nsx.model.TransportZone;
import com.vmware.nsx.model.TransportZoneListResult;
import com.vmware.nsx_policy.Infra;
import com.vmware.nsx_policy.infra.DhcpRelayConfigs;
import com.vmware.nsx_policy.infra.IpDiscoveryProfiles;
import com.vmware.nsx_policy.infra.LbAppProfiles;
import com.vmware.nsx_policy.infra.LbMonitorProfiles;
import com.vmware.nsx_policy.infra.LbPools;
import com.vmware.nsx_policy.infra.LbServices;
import com.vmware.nsx_policy.infra.LbVirtualServers;
import com.vmware.nsx_policy.infra.MacDiscoveryProfiles;
import com.vmware.nsx_policy.infra.SegmentSecurityProfiles;
import com.vmware.nsx_policy.infra.Segments;
import com.vmware.nsx_policy.infra.Services;
import com.vmware.nsx_policy.infra.Sites;
Expand All @@ -43,12 +47,16 @@
import com.vmware.nsx_policy.infra.tier_0s.LocaleServices;
import com.vmware.nsx_policy.infra.tier_1s.nat.NatRules;
import com.vmware.nsx_policy.model.ApiError;
import com.vmware.nsx_policy.model.ChildSegment;
import com.vmware.nsx_policy.model.ChildSegmentDiscoveryProfileBindingMap;
import com.vmware.nsx_policy.model.ChildSegmentSecurityProfileBindingMap;
import com.vmware.nsx_policy.model.DhcpRelayConfig;
import com.vmware.nsx_policy.model.EnforcementPoint;
import com.vmware.nsx_policy.model.EnforcementPointListResult;
import com.vmware.nsx_policy.model.Group;
import com.vmware.nsx_policy.model.GroupListResult;
import com.vmware.nsx_policy.model.ICMPTypeServiceEntry;
import com.vmware.nsx_policy.model.IPDiscoveryProfile;
import com.vmware.nsx_policy.model.L4PortSetServiceEntry;
import com.vmware.nsx_policy.model.LBAppProfileListResult;
import com.vmware.nsx_policy.model.LBIcmpMonitorProfile;
Expand All @@ -61,6 +69,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.MacDiscoveryProfile;
import com.vmware.nsx_policy.model.PathExpression;
import com.vmware.nsx_policy.model.PolicyGroupMembersListResult;
import com.vmware.nsx_policy.model.PolicyNatRule;
Expand All @@ -69,6 +78,9 @@
import com.vmware.nsx_policy.model.Rule;
import com.vmware.nsx_policy.model.SecurityPolicy;
import com.vmware.nsx_policy.model.Segment;
import com.vmware.nsx_policy.model.SegmentDiscoveryProfileBindingMap;
import com.vmware.nsx_policy.model.SegmentSecurityProfile;
import com.vmware.nsx_policy.model.SegmentSecurityProfileBindingMap;
import com.vmware.nsx_policy.model.SegmentSubnet;
import com.vmware.nsx_policy.model.ServiceListResult;
import com.vmware.nsx_policy.model.Site;
Expand All @@ -90,9 +102,10 @@
import org.apache.cloudstack.resource.NsxNetworkRule;
import org.apache.cloudstack.utils.NsxControllerUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.commons.lang3.BooleanUtils;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -128,6 +141,11 @@ public class NsxApiClient {
private static final String TIER_1_RESOURCE_TYPE = "Tier1";
private static final String TIER_1_LOCALE_SERVICE_ID = "default";
private static final String SEGMENT_RESOURCE_TYPE = "Segment";
private static final String INFRA_RESOURCE_TYPE = "Infra";
private static final String SEGMENT_DISCOVERY_PROFILE_BINDING_RESOURCE_TYPE = "SegmentDiscoveryProfileBindingMap";
private static final String SEGMENT_SECURITY_PROFILE_BINDING_RESOURCE_TYPE = "SegmentSecurityProfileBindingMap";
private static final String SEGMENT_DISCOVERY_PROFILE_BINDING_ID = "cloudstack-discovery-profile-binding";
private static final String SEGMENT_SECURITY_PROFILE_BINDING_ID = "cloudstack-security-profile-binding";
private static final String TIER_0_GATEWAY_PATH_PREFIX = "/infra/tier-0s/";
private static final String TIER_1_GATEWAY_PATH_PREFIX = "/infra/tier-1s/";
protected static final String SEGMENTS_PATH = "/infra/segments";
Expand Down Expand Up @@ -466,8 +484,16 @@ public TransportZoneListResult getTransportZones() {

public void createSegment(String segmentName, String tier1GatewayName, String gatewayAddress, String enforcementPointPath,
List<TransportZone> transportZones) {
createSegment(segmentName, tier1GatewayName, gatewayAddress, enforcementPointPath, transportZones, null, null, null);
}

public void createSegment(String segmentName, String tier1GatewayName, String gatewayAddress, String enforcementPointPath,
List<TransportZone> transportZones, String ipDiscoveryProfileId, String macDiscoveryProfileId,
String segmentSecurityProfileId) {
try {
Segments segmentService = (Segments) nsxService.apply(Segments.class);
String ipDiscoveryProfilePath = getIpDiscoveryProfilePath(ipDiscoveryProfileId);
String macDiscoveryProfilePath = getMacDiscoveryProfilePath(macDiscoveryProfileId);
String segmentSecurityProfilePath = getSegmentSecurityProfilePath(segmentSecurityProfileId);
SegmentSubnet subnet = new SegmentSubnet.Builder()
.setGatewayAddress(gatewayAddress)
.build();
Expand All @@ -480,7 +506,24 @@ public void createSegment(String segmentName, String tier1GatewayName, String ga
.setSubnets(List.of(subnet))
.setTransportZonePath(enforcementPointPath + "/transport-zones/" + transportZones.get(0).getId())
.build();
segmentService.patch(segmentName, segment);
List<Structure> profileBindings = getSegmentProfileBindings(ipDiscoveryProfilePath, macDiscoveryProfilePath,
segmentSecurityProfilePath);
if (profileBindings.isEmpty()) {
Segments segmentService = (Segments) nsxService.apply(Segments.class);
segmentService.patch(segmentName, segment);
} else {
segment.setChildren(profileBindings);
ChildSegment childSegment = new ChildSegment.Builder()
.setId(segmentName)
.setSegment(segment)
.build();
com.vmware.nsx_policy.model.Infra infra = new com.vmware.nsx_policy.model.Infra.Builder()
.setResourceType(INFRA_RESOURCE_TYPE)
.setChildren(List.of(childSegment))
.build();
Infra infraService = (Infra) nsxService.apply(Infra.class);
infraService.patch(infra, false);
}
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
String msg = String.format("Error creating segment %s: %s", segmentName, ae.getErrorMessage());
Expand All @@ -489,6 +532,76 @@ public void createSegment(String segmentName, String tier1GatewayName, String ga
}
}

protected String getIpDiscoveryProfilePath(String profileId) {
if (StringUtils.isBlank(profileId)) {
return null;
}
IpDiscoveryProfiles profiles = (IpDiscoveryProfiles) nsxService.apply(IpDiscoveryProfiles.class);
IPDiscoveryProfile profile = profiles.get(profileId);
return validateProfile(profileId, profile.getId(), profile.getPath(), "/infra/ip-discovery-profiles/", profile.getMarkedForDelete());
}
Comment on lines +535 to +542

protected String getMacDiscoveryProfilePath(String profileId) {
if (StringUtils.isBlank(profileId)) {
return null;
}
MacDiscoveryProfiles profiles = (MacDiscoveryProfiles) nsxService.apply(MacDiscoveryProfiles.class);
MacDiscoveryProfile profile = profiles.get(profileId);
return validateProfile(profileId, profile.getId(), profile.getPath(), "/infra/mac-discovery-profiles/", profile.getMarkedForDelete());
}

protected String getSegmentSecurityProfilePath(String profileId) {
if (StringUtils.isBlank(profileId)) {
return null;
}
SegmentSecurityProfiles profiles = (SegmentSecurityProfiles) nsxService.apply(SegmentSecurityProfiles.class);
SegmentSecurityProfile profile = profiles.get(profileId);
return validateProfile(profileId, profile.getId(), profile.getPath(), "/infra/segment-security-profiles/", profile.getMarkedForDelete());
}

protected String validateProfile(String requestedId, String resolvedId, String profilePath,
String expectedPathPrefix, Boolean markedForDelete) {
if (!Objects.equals(requestedId, resolvedId)) {
throw new CloudRuntimeException(String.format("NSX returned profile %s while resolving requested profile %s", resolvedId, requestedId));
}
if (!Objects.equals(expectedPathPrefix + requestedId, profilePath)) {
throw new CloudRuntimeException(String.format("NSX profile %s did not return a canonical resource path of the expected type", requestedId));
}
if (Boolean.TRUE.equals(markedForDelete)) {
throw new CloudRuntimeException(String.format("NSX profile %s is marked for deletion", requestedId));
}
return profilePath;
}

protected List<Structure> getSegmentProfileBindings(String ipDiscoveryProfilePath, String macDiscoveryProfilePath,
String segmentSecurityProfilePath) {
List<Structure> bindings = new ArrayList<>();
if (StringUtils.isNotBlank(ipDiscoveryProfilePath) || StringUtils.isNotBlank(macDiscoveryProfilePath)) {
SegmentDiscoveryProfileBindingMap binding = new SegmentDiscoveryProfileBindingMap.Builder()
.setResourceType(SEGMENT_DISCOVERY_PROFILE_BINDING_RESOURCE_TYPE)
.setId(SEGMENT_DISCOVERY_PROFILE_BINDING_ID)
.setIpDiscoveryProfilePath(ipDiscoveryProfilePath)
.setMacDiscoveryProfilePath(macDiscoveryProfilePath)
.build();
bindings.add(new ChildSegmentDiscoveryProfileBindingMap.Builder()
.setId(SEGMENT_DISCOVERY_PROFILE_BINDING_ID)
.setSegmentDiscoveryProfileBindingMap(binding)
.build());
}
if (StringUtils.isNotBlank(segmentSecurityProfilePath)) {
SegmentSecurityProfileBindingMap binding = new SegmentSecurityProfileBindingMap.Builder()
.setResourceType(SEGMENT_SECURITY_PROFILE_BINDING_RESOURCE_TYPE)
.setId(SEGMENT_SECURITY_PROFILE_BINDING_ID)
.setSegmentSecurityProfilePath(segmentSecurityProfilePath)
.build();
bindings.add(new ChildSegmentSecurityProfileBindingMap.Builder()
.setId(SEGMENT_SECURITY_PROFILE_BINDING_ID)
.setSegmentSecurityProfileBindingMap(binding)
.build());
}
return bindings;
}

public void deleteSegment(long zoneId, long domainId, long accountId, Long vpcId, long networkId, String segmentName) {
try {
removeSegmentDistributedFirewallRules(segmentName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@

import javax.inject.Inject;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigrationResponder {
Expand Down Expand Up @@ -324,10 +325,19 @@ public void createNsxSegment(NetworkVO networkVO, DataCenter zone) {
throw new CloudRuntimeException(msg);
}
}
CreateNsxSegmentCommand command = NsxHelper.createNsxSegmentCommand(domain, account, zone, vpcName, networkVO);
Map<NetworkOffering.Detail, String> offeringDetails = _networkModel.getNtwkOffDetails(networkVO.getNetworkOfferingId());
String ipDiscoveryProfile = getOfferingDetail(offeringDetails, NetworkOffering.Detail.NsxIpDiscoveryProfileId);
String macDiscoveryProfile = getOfferingDetail(offeringDetails, NetworkOffering.Detail.NsxMacDiscoveryProfileId);
String segmentSecurityProfile = getOfferingDetail(offeringDetails, NetworkOffering.Detail.NsxSegmentSecurityProfileId);
CreateNsxSegmentCommand command = NsxHelper.createNsxSegmentCommand(domain, account, zone, vpcName, networkVO,
ipDiscoveryProfile, macDiscoveryProfile, segmentSecurityProfile);
NsxAnswer answer = nsxControllerUtils.sendNsxCommand(command, zone.getId());
if (!answer.getResult()) {
throw new CloudRuntimeException("can not create NSX network");
}
}

protected String getOfferingDetail(Map<NetworkOffering.Detail, String> offeringDetails, NetworkOffering.Detail detail) {
return offeringDetails == null ? null : offeringDetails.get(detail);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,14 @@ public static CreateNsxDhcpRelayConfigCommand createNsxDhcpRelayConfigCommand(Do
}

public static CreateNsxSegmentCommand createNsxSegmentCommand(DomainVO domain, Account account, DataCenter zone, String vpcName, NetworkVO networkVO) {
return createNsxSegmentCommand(domain, account, zone, vpcName, networkVO, null, null, null);
}

public static CreateNsxSegmentCommand createNsxSegmentCommand(DomainVO domain, Account account, DataCenter zone, String vpcName, NetworkVO networkVO,
String ipDiscoveryProfileId, String macDiscoveryProfileId, String segmentSecurityProfileId) {
return new CreateNsxSegmentCommand(domain.getId(), account.getId(), zone.getId(),
networkVO.getVpcId(), vpcName, networkVO.getId(), networkVO.getName(), networkVO.getGateway(), networkVO.getCidr());
networkVO.getVpcId(), vpcName, networkVO.getId(), networkVO.getName(), networkVO.getGateway(), networkVO.getCidr(),
ipDiscoveryProfileId, macDiscoveryProfileId, segmentSecurityProfileId);
}

public static CreateOrUpdateNsxTier1NatRuleCommand createOrUpdateNsxNatRuleCommand(long domainId, long accountId, long zoneId,
Expand Down
Loading
Loading