[NSX] Create a DHCP relay and add it to a VPC tier segment (#107)

* Create DHCP relay command and execute request

* In progress integrate with networking

* Create DHCP relay config on the network VR allocation

* Revert domain router dao changes

* Create DHCP relay con VR nic plug to NSX network

* Link DHCP relay config to segment after creation
This commit is contained in:
Nicolas Vazquez 2023-10-08 20:59:16 -03:00 committed by GitHub
parent 83540aab27
commit e7e511b685
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 148 additions and 1 deletions

View File

@ -0,0 +1,46 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.agent.api;
import java.util.List;
public class CreateNsxDhcpRelayConfigCommand extends NsxCommand {
private String vpcName;
private String networkName;
private List<String> addresses;
public CreateNsxDhcpRelayConfigCommand(String zoneName, Long zoneId, String accountName, Long accountId,
String vpcName, String networkName, List<String> addresses) {
super(zoneName, zoneId, accountName, accountId);
this.vpcName = vpcName;
this.networkName = networkName;
this.addresses = addresses;
}
public String getVpcName() {
return vpcName;
}
public String getNetworkName() {
return networkName;
}
public List<String> getAddresses() {
return addresses;
}
}

View File

@ -31,12 +31,14 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.vmware.nsx.model.TransportZone;
import com.vmware.nsx.model.TransportZoneListResult;
import com.vmware.nsx_policy.infra.DhcpRelayConfigs;
import com.vmware.nsx_policy.infra.Segments;
import com.vmware.nsx_policy.infra.Sites;
import com.vmware.nsx_policy.infra.Tier1s;
import com.vmware.nsx_policy.infra.sites.EnforcementPoints;
import com.vmware.nsx_policy.infra.tier_0s.LocaleServices;
import com.vmware.nsx_policy.model.ApiError;
import com.vmware.nsx_policy.model.DhcpRelayConfig;
import com.vmware.nsx_policy.model.EnforcementPointListResult;
import com.vmware.nsx_policy.model.LocaleServicesListResult;
import com.vmware.nsx_policy.model.Segment;
@ -47,6 +49,7 @@ import com.vmware.vapi.bindings.Service;
import com.vmware.vapi.std.errors.Error;
import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.StartupNsxCommand;
import org.apache.cloudstack.agent.api.CreateNsxDhcpRelayConfigCommand;
import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand;
import org.apache.cloudstack.agent.api.CreateNsxTier1GatewayCommand;
import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand;
@ -75,6 +78,7 @@ public class NsxResource implements ServerResource {
private static final Logger LOGGER = Logger.getLogger(NsxResource.class);
private static final String TIER_0_GATEWAY_PATH_PREFIX = "/infra/tier-0s/";
private static final String TIER_1_GATEWAY_PATH_PREFIX = "/infra/tier-1s/";
private static final String DHCP_RELAY_CONFIGS_PATH_PREFIX = "/infra/dhcp-relay-configs";
private static final String Tier_1_LOCALE_SERVICE_ID = "default";
private static final String TIER_1_RESOURCE_TYPE = "Tier1";
@ -128,6 +132,8 @@ public class NsxResource implements ServerResource {
return executeRequest((CreateNsxSegmentCommand) cmd);
} else if (cmd instanceof CreateNsxTier1GatewayCommand) {
return executeRequest((CreateNsxTier1GatewayCommand) cmd);
} else if (cmd instanceof CreateNsxDhcpRelayConfigCommand) {
return executeRequest((CreateNsxDhcpRelayConfigCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
@ -235,6 +241,56 @@ public class NsxResource implements ServerResource {
return true;
}
private String getDhcpRelayConfig(String zoneName, String accountName, String vpcName, String networkName) {
return String.format("%s-%s-%s-%s-Relay", zoneName, accountName, vpcName, networkName);
}
private Answer executeRequest(CreateNsxDhcpRelayConfigCommand cmd) {
String zoneName = cmd.getZoneName();
String accountName = cmd.getAccountName();
String vpcName = cmd.getVpcName();
String networkName = cmd.getNetworkName();
List<String> addresses = cmd.getAddresses();
String dhcpRelayConfigName = getDhcpRelayConfig(zoneName, accountName, vpcName, networkName);
String msg = String.format("Creating DHCP relay config with name %s on network %s of VPC %s",
dhcpRelayConfigName, networkName, vpcName);
LOGGER.debug(msg);
try {
DhcpRelayConfigs service = (DhcpRelayConfigs) nsxService.apply(DhcpRelayConfigs.class);
DhcpRelayConfig config = new DhcpRelayConfig.Builder()
.setServerAddresses(addresses)
.setId(dhcpRelayConfigName)
.setDisplayName(dhcpRelayConfigName)
.build();
service.patch(dhcpRelayConfigName, config);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
msg = String.format("Error creating the DHCP relay config with name %s: %s", dhcpRelayConfigName, ae.getErrorMessage());
LOGGER.error(msg);
return new NsxAnswer(cmd, new CloudRuntimeException(ae.getErrorMessage()));
}
String segmentName = String.format("%s-%s-%s", accountName, vpcName, networkName);
String dhcpConfigPath = String.format("%s/%s", DHCP_RELAY_CONFIGS_PATH_PREFIX, dhcpRelayConfigName);
try {
LOGGER.debug(String.format("Adding the creating DHCP relay config %s to the segment %s", dhcpConfigPath, segmentName));
Segments segmentService = (Segments) nsxService.apply(Segments.class);
Segment segment = segmentService.get(segmentName);
segment.setDhcpConfigPath(dhcpConfigPath);
segmentService.patch(segmentName, segment);
} catch (Error error) {
ApiError ae = error.getData()._convertTo(ApiError.class);
msg = String.format("Error adding the DHCP relay config with name %s to the segment %s: %s", dhcpRelayConfigName, segmentName, ae.getErrorMessage());
LOGGER.error(msg);
return new NsxAnswer(cmd, new CloudRuntimeException(ae.getErrorMessage()));
}
return new NsxAnswer(cmd, true, "");
}
private Answer executeRequest(ReadyCommand cmd) {
return new ReadyAnswer(cmd);
}

View File

@ -43,12 +43,16 @@ import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.NsxAnswer;
import org.apache.cloudstack.agent.api.CreateNsxDhcpRelayConfigCommand;
import org.apache.cloudstack.agent.api.CreateNsxSegmentCommand;
import org.apache.log4j.Logger;
import javax.inject.Inject;
import java.util.List;
import java.util.Objects;
public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigrationResponder {
private static final Logger LOGGER = Logger.getLogger(NsxGuestNetworkGuru.class);
@ -182,6 +186,47 @@ public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr
return implemented;
}
@Override
public NicProfile allocate(Network network, NicProfile nic, VirtualMachineProfile vm) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
NicProfile nicProfile = super.allocate(network, nic, vm);
if (vm.getType() == VirtualMachine.Type.DomainRouter) {
final DataCenter zone = _dcDao.findById(network.getDataCenterId());
long zoneId = network.getDataCenterId();
if (Objects.isNull(zone)) {
String msg = String.format("Unable to find zone with id: %s", zoneId);
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
Account account = accountDao.findById(network.getAccountId());
if (Objects.isNull(account)) {
String msg = String.format("Unable to find account with id: %s", network.getAccountId());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
VpcVO vpc = _vpcDao.findById(network.getVpcId());
if (Objects.isNull(vpc)) {
String msg = String.format("Unable to find VPC with id: %s", network.getVpcId());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
// Create the DHCP relay config for the segment
String iPv4Address = nicProfile.getIPv4Address();
List<String> addresses = List.of(iPv4Address);
CreateNsxDhcpRelayConfigCommand command = new CreateNsxDhcpRelayConfigCommand(zone.getName(), zone.getId(),
account.getAccountName(), network.getAccountId(),
vpc.getName(), network.getName(), addresses);
NsxAnswer answer = nsxControllerUtils.sendNsxCommand(command, zone.getId());
if (!answer.getResult()) {
String msg = String.format("Error creating DHCP relay config for network %s and nic %s: %s", network.getName(), nic.getName(), answer.getDetails());
LOGGER.error(msg);
throw new CloudRuntimeException(msg);
}
}
return nicProfile;
}
@Override
public void reserve(final NicProfile nic, final Network network, final VirtualMachineProfile vm,
final DeployDestination dest, final ReservationContext context)

View File

@ -116,7 +116,7 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur
@Inject
ConfigurationServer _configServer;
@Inject
IpAddressManager _ipAddrMgr;
protected IpAddressManager _ipAddrMgr;
@Inject
NetworkOfferingDao networkOfferingDao;
@Inject