diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql b/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql index ce63fe81345..d0e0df38301 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41810to41900.sql @@ -278,4 +278,4 @@ FROM LEFT JOIN `cloud`.`network_offering_details` AS `offering_details` ON `offering_details`.`network_offering_id` = `network_offerings`.`id` AND `offering_details`.`name`='internetProtocol' GROUP BY - `network_offerings`.`id`; \ No newline at end of file + `network_offerings`.`id`; diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/NsxAnswer.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/NsxAnswer.java index 310e69dff01..0820465a6b6 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/NsxAnswer.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/NsxAnswer.java @@ -27,4 +27,5 @@ public class NsxAnswer extends Answer { public NsxAnswer(final Command command, final Exception e) { super(command, e); } + } diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java index 44cdb211902..cc3bdfd563a 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java @@ -50,6 +50,7 @@ import org.apache.log4j.Logger; import javax.naming.ConfigurationException; import java.util.List; import java.util.Map; +import java.util.function.Function; public class NsxResource implements ServerResource { private static final Logger LOGGER = Logger.getLogger(NsxResource.class); @@ -204,12 +205,12 @@ public class NsxResource implements ServerResource { return new ReadyAnswer(cmd); } - private Service getService(Class serviceClass) { - return nsxApi.getApiClient().createStub(serviceClass); + private Function nsxService = svcClass -> { return nsxApi.getApiClient().createStub(svcClass); }; + private Service getService(Class svcClass) { + return nsxApi.getApiClient().createStub(svcClass); } - private Answer executeRequest(CreateNsxTier1GatewayCommand cmd) { - String name = getVpcName(cmd); + String name = getTier1GatewayName(cmd); Tier1 tier1 = getTier1Gateway(name); if (tier1 != null) { throw new InvalidParameterValueException(String.format("VPC network with name %s exists in NSX zone: %s and account %s", name, cmd.getZoneName(), cmd.getAccountName())); @@ -217,7 +218,7 @@ public class NsxResource implements ServerResource { List localeServices = getTier0LocalServices(tier0Gateway); String tier0GatewayPath = TIER_0_GATEWAY_PATH_PREFIX + tier0Gateway; - Tier1s tier1service = (Tier1s) getService(Tier1s.class); + Tier1s tier1service = (Tier1s) nsxService.apply(Tier1s.class); tier1 = new Tier1.Builder() .setTier0Path(tier0GatewayPath) .setResourceType(TIER_1_RESOURCE_TYPE) @@ -230,6 +231,7 @@ public class NsxResource implements ServerResource { .setLocaleServices( new com.vmware.nsx_policy.model.LocaleServices.Builder() .setEdgeClusterPath(localeServices.get(0).getEdgeClusterPath()) + .setId(localeServices.get(0).getId()) .setResourceType("LocaleServices") .build() ).build())).build(); @@ -244,17 +246,17 @@ public class NsxResource implements ServerResource { private Answer executeRequest(DeleteNsxTier1GatewayCommand cmd) { try { - Tier1s tier1service = (Tier1s) getService(Tier1s.class); - tier1service.delete(cmd.getVpcName()); + Tier1s tier1service = (Tier1s) nsxService.apply(Tier1s.class); + tier1service.delete(getTier1GatewayName(cmd)); } catch (Exception e) { - return new Answer(cmd, new CloudRuntimeException(e.getMessage())); + return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage())); } - return new Answer(cmd, true, null); + return new NsxAnswer(cmd, true, null); } private List getTier0LocalServices(String tier0Gateway) { try { - LocaleServices tier0LocaleServices = (LocaleServices) getService(LocaleServices.class); + LocaleServices tier0LocaleServices = (LocaleServices) nsxService.apply(LocaleServices.class); LocaleServicesListResult result =tier0LocaleServices.list(tier0Gateway, null, false, null, null, null, null); return result.getResults(); } catch (Exception e) { @@ -264,7 +266,7 @@ public class NsxResource implements ServerResource { private Tier1 getTier1Gateway(String tier1GatewayId) { try { - Tier1s tier1service = (Tier1s) getService(Tier1s.class); + Tier1s tier1service = (Tier1s) nsxService.apply(Tier1s.class); return tier1service.get(tier1GatewayId); } catch (Exception e) { LOGGER.debug(String.format("NSX Tier-1 gateway with name: %s not found", tier1GatewayId)); @@ -272,7 +274,7 @@ public class NsxResource implements ServerResource { return null; } - private String getVpcName(CreateNsxTier1GatewayCommand cmd) { + private String getTier1GatewayName(CreateNsxTier1GatewayCommand cmd) { return cmd.getZoneName() + "-" + cmd.getAccountName() + "-" + cmd.getVpcName(); } diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxControllerUtils.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxControllerUtils.java index 944d33e3c42..944d663c5df 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxControllerUtils.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxControllerUtils.java @@ -44,8 +44,6 @@ public class NsxControllerUtils { s_logger.error("No NSX controller was found!"); throw new InvalidParameterValueException("Failed to find an NSX controller"); } - - //Answer answer = agentMgr.sendTo(zoneId, Hypervisor.HypervisorType.VMware, cmd); Answer answer = agentMgr.easySend(nsxProviderVO.getHostId(), cmd); if (answer == null || !answer.getResult()) { diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java index e462d40f1eb..e030991d499 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java @@ -16,26 +16,30 @@ // under the License. package org.apache.cloudstack.service; +import com.amazonaws.util.CollectionUtils; import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; -import com.cloud.agent.api.StartupCommand; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; import com.cloud.agent.api.AgentControlAnswer; import com.cloud.agent.api.AgentControlCommand; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.StartupCommand; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.deploy.DeployDestination; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ConnectionException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.network.Network; +import com.cloud.network.Networks; import com.cloud.network.PhysicalNetworkServiceProvider; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.network.element.DhcpServiceProvider; import com.cloud.network.element.DnsServiceProvider; import com.cloud.network.element.VpcProvider; @@ -50,21 +54,24 @@ import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; import com.cloud.user.Account; import com.cloud.user.AccountManager; +import com.cloud.utils.Pair; import com.cloud.utils.component.AdapterBase; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachineProfile; +import net.sf.ehcache.config.InvalidConfigurationException; import org.apache.cloudstack.StartupNsxCommand; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import javax.inject.Inject; import javax.naming.ConfigurationException; -import java.util.Map; import java.util.HashMap; import java.util.List; -import java.util.Set; +import java.util.Map; import java.util.Objects; +import java.util.Set; +import java.util.function.Function; @Component public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsServiceProvider, VpcProvider, @@ -80,6 +87,8 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS AgentManager agentManager; @Inject ResourceManager resourceManager; + @Inject + PhysicalNetworkDao physicalNetworkDao; private static final Logger LOGGER = Logger.getLogger(NsxElement.class); @@ -229,34 +238,48 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS @Override public boolean implementVpc(Vpc vpc, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { - DataCenterVO zone = dataCenterDao.findById(vpc.getZoneId()); - if (Network.Provider.Nsx.getName().equalsIgnoreCase(zone.getDhcpProvider())) { - if (Objects.isNull(zone)) { - throw new InvalidParameterValueException(String.format("Failed to find zone with id %s", vpc.getZoneId())); - } - Account account = accountMgr.getAccount(vpc.getAccountId()); - if (Objects.isNull(account)) { - throw new InvalidParameterValueException(String.format("Failed to find account with id %s", vpc.getAccountId())); - } - return nsxService.createVpcNetwork(vpc.getZoneId(), zone.getName(), account.getAccountId(), account.getName(), vpc.getName()); + DataCenterVO zone = zoneFunction.apply(vpc.getZoneId()); + Pair isNsxAndAccount = validateVpcConfigurationAndGetAccount(zone, vpc); + if (!isNsxAndAccount.first()) { + return true; } - return true; + if (isNsxAndAccount.first() && Objects.isNull(isNsxAndAccount.second())) { + throw new InvalidParameterValueException(String.format("Failed to find account with id %s", vpc.getAccountId())); + } + Account account = isNsxAndAccount.second(); + return nsxService.createVpcNetwork(vpc.getZoneId(), zone.getName(), account.getAccountId(), account.getName(), vpc.getName()); } @Override public boolean shutdownVpc(Vpc vpc, ReservationContext context) throws ConcurrentOperationException { - DataCenterVO zone = dataCenterDao.findById(vpc.getZoneId()); - if (Network.Provider.Nsx.getName().equalsIgnoreCase(zone.getDhcpProvider())) { - if (Objects.isNull(zone)) { - throw new InvalidParameterValueException(String.format("Failed to find zone with id %s", vpc.getZoneId())); - } - Account account = accountMgr.getAccount(vpc.getAccountId()); - if (Objects.isNull(account)) { - throw new InvalidParameterValueException(String.format("Failed to find account with id %s", vpc.getAccountId())); - } - return nsxService.deleteVpcNetwork(vpc.getZoneId(), zone.getName(), account.getAccountId(), account.getName(), vpc.getName()); + DataCenterVO zone = zoneFunction.apply(vpc.getZoneId()); + Pair isNsxAndAccount = validateVpcConfigurationAndGetAccount(zone, vpc); + if (!isNsxAndAccount.first()) { + return true; } - return true; + if (isNsxAndAccount.first() && Objects.isNull(isNsxAndAccount.second())) { + throw new InvalidParameterValueException(String.format("Failed to find account with id %s", vpc.getAccountId())); + } + Account account = isNsxAndAccount.second(); + + return nsxService.deleteVpcNetwork(vpc.getZoneId(), zone.getName(), account.getAccountId(), account.getName(), vpc.getName()); + } + + private Pair validateVpcConfigurationAndGetAccount(DataCenterVO zone, Vpc vpc) { + if (Objects.isNull(zone)) { + throw new InvalidParameterValueException(String.format("Failed to find zone with id %s", vpc.getZoneId())); + } + Account account = null; + boolean forNsx = false; + List physicalNetworks = physicalNetworkDao.listByZoneAndTrafficType(zone.getId(), Networks.TrafficType.Guest); + if (CollectionUtils.isNullOrEmpty(physicalNetworks) || physicalNetworks.size() > 1 ) { + throw new InvalidConfigurationException(String.format("Desired number of physical networks is not present in the zone %s for traffic type %s. ", zone.getName(), Networks.TrafficType.Guest.name())); + } + if (physicalNetworks.get(0).getIsolationMethods().contains(Network.Provider.Nsx.getName())) { + account = accountMgr.getAccount(vpc.getAccountId()); + forNsx = true; + } + return new Pair<>(forNsx, account); } @Override @@ -333,4 +356,6 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, DnsS public boolean processTimeout(long agentId, long seq) { return false; } + + private final Function zoneFunction = zoneId -> { return dataCenterDao.findById(zoneId); }; } diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxGuestNetworkGuru.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxGuestNetworkGuru.java index 3e523562bf7..1984e188a04 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxGuestNetworkGuru.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxGuestNetworkGuru.java @@ -18,13 +18,19 @@ package org.apache.cloudstack.service; import com.cloud.dc.DataCenter; import com.cloud.deploy.DeployDestination; +import com.cloud.deploy.DeploymentPlan; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InsufficientVirtualNetworkCapacityException; import com.cloud.network.Network; import com.cloud.network.NetworkMigrationResponder; +import com.cloud.network.NetworkProfile; import com.cloud.network.Networks; import com.cloud.network.PhysicalNetwork; import com.cloud.network.guru.GuestNetworkGuru; import com.cloud.offering.NetworkOffering; import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; +import com.cloud.user.Account; +import com.cloud.utils.db.DB; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachineProfile; @@ -45,6 +51,52 @@ public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr _isolationMethods = new PhysicalNetwork.IsolationMethod[] {new PhysicalNetwork.IsolationMethod("NSX")}; } + @Override + public boolean canHandle(NetworkOffering offering, DataCenter.NetworkType networkType, + PhysicalNetwork physicalNetwork) { + return networkType == DataCenter.NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) + && isMyIsolationMethod(physicalNetwork) && networkOfferingServiceMapDao.isProviderForNetworkOffering( + offering.getId(), Network.Provider.Tungsten); + } + + @Override + public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) { + return null; + } + + @Override + @DB + public void deallocate(Network config, NicProfile nic, VirtualMachineProfile vm) { + + } + + @Override + public Network implement(Network network, NetworkOffering offering, DeployDestination dest, + ReservationContext context) { + return null; + } + + @Override + public void reserve(final NicProfile nic, final Network network, final VirtualMachineProfile vm, + final DeployDestination dest, final ReservationContext context) + throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException { + + } + + @Override + public boolean release(final NicProfile nic, final VirtualMachineProfile vm, final String reservationId) { + return true; + } + + @Override + public void shutdown(final NetworkProfile profile, final NetworkOffering offering) { + + } + + @Override + public boolean trash(Network network, NetworkOffering offering) { + return true; + } @Override public boolean prepareMigration(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) { @@ -60,12 +112,4 @@ public class NsxGuestNetworkGuru extends GuestNetworkGuru implements NetworkMigr public void commitMigration(NicProfile nic, Network network, VirtualMachineProfile vm, ReservationContext src, ReservationContext dst) { } - - @Override - public boolean canHandle(NetworkOffering offering, DataCenter.NetworkType networkType, - PhysicalNetwork physicalNetwork) { - return networkType == DataCenter.NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) - && isMyIsolationMethod(physicalNetwork) && networkOfferingServiceMapDao.isProviderForNetworkOffering( - offering.getId(), Network.Provider.Tungsten); - } } diff --git a/plugins/network-elements/nsx/src/main/resources/META-INF/cloudstack/nsx/module.properties b/plugins/network-elements/nsx/src/main/resources/META-INF/cloudstack/nsx/module.properties index 0126f2e007f..1630826d102 100644 --- a/plugins/network-elements/nsx/src/main/resources/META-INF/cloudstack/nsx/module.properties +++ b/plugins/network-elements/nsx/src/main/resources/META-INF/cloudstack/nsx/module.properties @@ -18,4 +18,4 @@ # name=nsx -parent=network \ No newline at end of file +parent=network