diff --git a/api/src/com/cloud/api/ApiConstants.java b/api/src/com/cloud/api/ApiConstants.java index 5fd0c8ba88d..bfd201fc43c 100755 --- a/api/src/com/cloud/api/ApiConstants.java +++ b/api/src/com/cloud/api/ApiConstants.java @@ -289,5 +289,7 @@ public class ApiConstants { public static final String VMWARE_NETWORK_LABEL = "vmwarenetworklabel"; public static final String NETWORK_SERVICE_PROVIDER_ID = "nspid"; public static final String SECURITY_GROUP_SERVICE = "securitygroupservice"; + public static final String SERVICE_LIST = "servicelist"; + public static final String CAN_ENABLE_INDIVIDUAL_SERVICE = "canEnableIndividualService"; } diff --git a/api/src/com/cloud/api/commands/AddNetworkServiceProviderCmd.java b/api/src/com/cloud/api/commands/AddNetworkServiceProviderCmd.java index 0b78f9c83e0..8e4176ffcbc 100644 --- a/api/src/com/cloud/api/commands/AddNetworkServiceProviderCmd.java +++ b/api/src/com/cloud/api/commands/AddNetworkServiceProviderCmd.java @@ -18,6 +18,8 @@ package com.cloud.api.commands; +import java.util.List; + import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; @@ -51,6 +53,9 @@ public class AddNetworkServiceProviderCmd extends BaseAsyncCreateCmd { @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="the name for the physical network service provider") private String name; + + @Parameter(name=ApiConstants.SERVICE_LIST, type=CommandType.LIST, collectionType = CommandType.STRING, description="the list of services to be enabled for this physical network service provider") + private List enabledServices; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -67,7 +72,11 @@ public class AddNetworkServiceProviderCmd extends BaseAsyncCreateCmd { public Long getDestinationPhysicalNetworkId() { return destinationPhysicalNetworkId; } - + + public List getEnabledServices() { + return enabledServices; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -97,7 +106,7 @@ public class AddNetworkServiceProviderCmd extends BaseAsyncCreateCmd { @Override public void create() throws ResourceAllocationException { - PhysicalNetworkServiceProvider result = _networkService.addProviderToPhysicalNetwork(getPhysicalNetworkId(), getProviderName(), getDestinationPhysicalNetworkId()); + PhysicalNetworkServiceProvider result = _networkService.addProviderToPhysicalNetwork(getPhysicalNetworkId(), getProviderName(), getDestinationPhysicalNetworkId(), getEnabledServices()); if (result != null) { setEntityId(result.getId()); } else { diff --git a/api/src/com/cloud/api/commands/ListNetworkServicesCmd.java b/api/src/com/cloud/api/commands/ListNetworkServicesCmd.java index aaf260fa861..3d83c741ea7 100644 --- a/api/src/com/cloud/api/commands/ListNetworkServicesCmd.java +++ b/api/src/com/cloud/api/commands/ListNetworkServicesCmd.java @@ -23,18 +23,23 @@ import java.util.List; import org.apache.log4j.Logger; +import com.cloud.api.ApiConstants; import com.cloud.api.BaseListCmd; import com.cloud.api.Implementation; +import com.cloud.api.Parameter; import com.cloud.api.response.ListResponse; import com.cloud.api.response.ServiceResponse; import com.cloud.network.Network; import com.cloud.user.Account; -@Implementation(description="Lists all network services provided by CloudStack.", responseObject=ServiceResponse.class) +@Implementation(description="Lists all network services provided by CloudStack or for the given Provider.", responseObject=ServiceResponse.class) public class ListNetworkServicesCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListNetworkServicesCmd.class.getName()); private static final String _name = "listnetworkservicesresponse"; + + @Parameter(name=ApiConstants.PROVIDER, type=CommandType.STRING, description="network service provider name") + private String providerName; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -45,6 +50,14 @@ public class ListNetworkServicesCmd extends BaseListCmd { ///////////////////////////////////////////////////// + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public String getProviderName() { + return providerName; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -60,7 +73,7 @@ public class ListNetworkServicesCmd extends BaseListCmd { @Override public void execute(){ - List services = _networkService.listNetworkServices(); + List services = _networkService.listNetworkServices(getProviderName()); ListResponse response = new ListResponse(); List servicesResponses = new ArrayList(); for (Network.Service service : services) { diff --git a/api/src/com/cloud/api/commands/ListSupportedNetworkServiceProvidersCmd.java b/api/src/com/cloud/api/commands/ListSupportedNetworkServiceProvidersCmd.java index b061997a60d..fd64e217237 100644 --- a/api/src/com/cloud/api/commands/ListSupportedNetworkServiceProvidersCmd.java +++ b/api/src/com/cloud/api/commands/ListSupportedNetworkServiceProvidersCmd.java @@ -33,7 +33,7 @@ import com.cloud.network.Network; import com.cloud.user.Account; -@Implementation(description="Lists all network serviceproviders supported by CloudStack.", responseObject=ProviderResponse.class) +@Implementation(description="Lists all network serviceproviders supported by CloudStack or for the given service.", responseObject=ProviderResponse.class) public class ListSupportedNetworkServiceProvidersCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListSupportedNetworkServiceProvidersCmd.class.getName()); private static final String _name = "listsupportednetworkserviceprovidersresponse"; diff --git a/api/src/com/cloud/api/commands/UpdateNetworkServiceProviderCmd.java b/api/src/com/cloud/api/commands/UpdateNetworkServiceProviderCmd.java index bb17b19cdd3..a4be1038102 100644 --- a/api/src/com/cloud/api/commands/UpdateNetworkServiceProviderCmd.java +++ b/api/src/com/cloud/api/commands/UpdateNetworkServiceProviderCmd.java @@ -18,6 +18,8 @@ package com.cloud.api.commands; +import java.util.List; + import org.apache.log4j.Logger; import com.cloud.api.ApiConstants; @@ -50,6 +52,10 @@ public class UpdateNetworkServiceProviderCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.FORCED, type=CommandType.BOOLEAN, required=false, description="Force shutdown the service provider.") private Boolean forcedShutdown; + + @Parameter(name=ApiConstants.SERVICE_LIST, type=CommandType.LIST, collectionType = CommandType.STRING, description="the list of services to be enabled for this physical network service provider") + private List enabledServices; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -65,6 +71,10 @@ public class UpdateNetworkServiceProviderCmd extends BaseAsyncCmd { public boolean isForcedShutdown() { return (forcedShutdown != null) ? forcedShutdown : false; } + + public List getEnabledServices() { + return enabledServices; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -83,7 +93,7 @@ public class UpdateNetworkServiceProviderCmd extends BaseAsyncCmd { public void execute(){ PhysicalNetworkServiceProvider result; try { - result = _networkService.updateNetworkServiceProvider(getId(), getState(), isForcedShutdown()); + result = _networkService.updateNetworkServiceProvider(getId(), getState(), isForcedShutdown(), getEnabledServices()); if (result != null) { ProviderResponse response = _responseGenerator.createNetworkServiceProviderResponse(result); response.setResponseName(getCommandName()); diff --git a/api/src/com/cloud/api/response/ProviderResponse.java b/api/src/com/cloud/api/response/ProviderResponse.java index caf9686d0f4..de7986b11ae 100644 --- a/api/src/com/cloud/api/response/ProviderResponse.java +++ b/api/src/com/cloud/api/response/ProviderResponse.java @@ -17,6 +17,8 @@ */ package com.cloud.api.response; +import java.util.List; + import com.cloud.api.ApiConstants; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; @@ -39,11 +41,20 @@ public class ProviderResponse extends BaseResponse { @SerializedName(ApiConstants.ID) @Param(description="id of the network provider") private Long id; + @SerializedName(ApiConstants.SERVICE_LIST) @Param(description="services for this provider") + private List services; + + @SerializedName(ApiConstants.CAN_ENABLE_INDIVIDUAL_SERVICE) @Param(description="true if individual services can be enabled/disabled") + private Boolean canEnableIndividualServices; public void setName(String name) { this.name = name; } + public String getName() { + return name; + } + public void setPhysicalNetworkId(long physicalNetworkId) { this.physicalNetworkId = physicalNetworkId; } @@ -76,4 +87,19 @@ public class ProviderResponse extends BaseResponse { return this.id; } + public void setServices(List services) { + this.services = services; + } + + public List getServices() { + return services; + } + + public Boolean getCanEnableIndividualServices() { + return canEnableIndividualServices; + } + + public void setCanEnableIndividualServices(Boolean canEnableIndividualServices) { + this.canEnableIndividualServices = canEnableIndividualServices; + } } diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index a6d1c7a9881..22fe6561750 100644 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -93,15 +93,15 @@ public interface NetworkService { boolean deletePhysicalNetwork(Long id); - List listNetworkServices(); + List listNetworkServices(String providerName); List listSupportedNetworkServiceProviders(String serviceName); - PhysicalNetworkServiceProvider addProviderToPhysicalNetwork(Long physicalNetworkId, String providerName, Long destinationPhysicalNetworkId); + PhysicalNetworkServiceProvider addProviderToPhysicalNetwork(Long physicalNetworkId, String providerName, Long destinationPhysicalNetworkId, List enabledServices); List listNetworkServiceProviders(Long physicalNetworkId); - PhysicalNetworkServiceProvider updateNetworkServiceProvider(Long id, String state, boolean forcedShutdown) throws ConcurrentOperationException, ResourceUnavailableException; + PhysicalNetworkServiceProvider updateNetworkServiceProvider(Long id, String state, boolean forcedShutdown, List enabledServices) throws ConcurrentOperationException, ResourceUnavailableException; boolean deleteNetworkServiceProvider(Long id); diff --git a/api/src/com/cloud/network/PhysicalNetworkServiceProvider.java b/api/src/com/cloud/network/PhysicalNetworkServiceProvider.java index b687e5a2b1d..b043aae3b8b 100644 --- a/api/src/com/cloud/network/PhysicalNetworkServiceProvider.java +++ b/api/src/com/cloud/network/PhysicalNetworkServiceProvider.java @@ -21,6 +21,10 @@ */ package com.cloud.network; +import java.util.List; + +import com.cloud.network.Network.Service; + /** @@ -46,4 +50,24 @@ public interface PhysicalNetworkServiceProvider { long getDestinationPhysicalNetworkId(); void setState(State state); + + boolean isLbServiceProvided(); + + boolean isVpnServiceProvided(); + + boolean isDhcpServiceProvided(); + + boolean isDnsServiceProvided(); + + boolean isGatewayServiceProvided(); + + boolean isFirewallServiceProvided(); + + boolean isSourcenatServiceProvided(); + + boolean isUserdataServiceProvided(); + + boolean isSecuritygroupServiceProvided(); + + List getEnabledServices(); } diff --git a/api/src/com/cloud/network/element/NetworkElement.java b/api/src/com/cloud/network/element/NetworkElement.java index 3ddf02056ca..c890a86cac5 100644 --- a/api/src/com/cloud/network/element/NetworkElement.java +++ b/api/src/com/cloud/network/element/NetworkElement.java @@ -123,5 +123,11 @@ public interface NetworkElement extends Adapter { * @throws ConcurrentOperationException * @throws ResourceUnavailableException */ - boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context, boolean forceShutdown) throws ConcurrentOperationException, ResourceUnavailableException; + boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context, boolean forceShutdown) throws ConcurrentOperationException, ResourceUnavailableException; + + /** + * This should return true if out of multiple services provided by this element, only some can be enabled. If all the services MUST be provided, this should return false. + * @return true/false + */ + boolean canEnableIndividualServices(); } diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 979ed3dba13..b5fc70b574d 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -55,6 +55,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.IPAddressVO; import com.cloud.network.LoadBalancerVO; import com.cloud.network.Network.Capability; +import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkProfile; @@ -653,4 +654,13 @@ public class ApiDBUtils { public static Map> listNetworkOfferingServices(long networkOfferingId) { return _networkMgr.listNetworkOfferingServices(networkOfferingId); } + + public static List getElementServices(Provider provider) { + return _networkMgr.getElementServices(provider); + } + + public static boolean canElementEnableIndividualServices(Provider serviceProvider) { + return _networkMgr.canElementEnableIndividualServices(serviceProvider); + } + } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index ec6cd4abc70..97ab122d2ff 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -2578,6 +2578,17 @@ public class ApiResponseHelper implements ResponseGenerator { public ProviderResponse createNetworkServiceProviderResponse(Provider serviceProvider) { ProviderResponse response = new ProviderResponse(); response.setName(serviceProvider.getName()); + + //set details from network element + List supportedServices = ApiDBUtils.getElementServices(serviceProvider); + List services = new ArrayList(); + for (Service service: supportedServices){ + services.add(service.getName()); + } + response.setServices(services); + boolean canEnableIndividualServices = ApiDBUtils.canElementEnableIndividualServices(serviceProvider); + response.setCanEnableIndividualServices(canEnableIndividualServices); + response.setObjectName("networkserviceprovider"); return response; } @@ -2590,6 +2601,14 @@ public class ApiResponseHelper implements ResponseGenerator { response.setPhysicalNetworkId(result.getPhysicalNetworkId()); response.setDestinationPhysicalNetworkId(result.getDestinationPhysicalNetworkId()); response.setState(result.getState().toString()); + + //set enabled services + List services = new ArrayList(); + for (Service service: result.getEnabledServices()){ + services.add(service.getName()); + } + response.setServices(services); + response.setObjectName("networkserviceprovider"); return response; } diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index fe913fa7d74..9e718a81746 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1355,6 +1355,9 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura if (allocationStateStr != null && !allocationStateStr.isEmpty()) { Grouping.AllocationState allocationState = Grouping.AllocationState.valueOf(allocationStateStr); zone.setAllocationState(allocationState); + }else{ + //Zone will be disabled since 3.0. Admin shoul enable it after physical network and providers setup. + zone.setAllocationState(Grouping.AllocationState.Disabled); } zone = _zoneDao.persist(zone); diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index f2394892a02..dda6bf5a62c 100644 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -231,4 +231,8 @@ public interface NetworkManager extends NetworkService { List getNetworkTags(HypervisorType hType, Network network); + List getElementServices(Provider provider); + + boolean canElementEnableIndividualServices(Provider provider); + } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 095c11a643a..f5263418c28 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -42,6 +42,13 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import com.cloud.agent.AgentManager; +import com.cloud.agent.Listener; +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.agent.api.to.NicTO; import com.cloud.alert.AlertManager; import com.cloud.api.commands.AssociateIPAddrCmd; @@ -79,6 +86,7 @@ import com.cloud.event.dao.EventDao; import com.cloud.event.dao.UsageEventDao; import com.cloud.exception.AccountLimitException; import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.ConnectionException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; @@ -86,6 +94,8 @@ import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.UnsupportedServiceException; +import com.cloud.host.HostVO; +import com.cloud.host.Status; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.IpAddress.State; import com.cloud.network.Network.Capability; @@ -186,7 +196,7 @@ import edu.emory.mathcs.backport.java.util.Collections; * NetworkManagerImpl implements NetworkManager. */ @Local(value = { NetworkManager.class, NetworkService.class }) -public class NetworkManagerImpl implements NetworkManager, NetworkService, Manager { +public class NetworkManagerImpl implements NetworkManager, NetworkService, Manager, Listener { private static final Logger s_logger = Logger.getLogger(NetworkManagerImpl.class); String _name; @@ -259,7 +269,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Inject PortForwardingRulesDao _portForwardingRulesDao; @Inject LoadBalancerDao _lbDao; @Inject PhysicalNetworkTrafficTypeDao _pNTrafficTypeDao; - + @Inject AgentManager _agentMgr; + private final HashMap _systemNetworks = new HashMap(5); ScheduledExecutorService _executor; @@ -290,6 +301,24 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return element; } + @Override + public List getElementServices(Provider provider){ + NetworkElement element = getElementImplementingProvider(provider.getName()); + if(element == null){ + throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + provider.getName() + "'"); + } + return new ArrayList(element.getCapabilities().keySet()); + } + + @Override + public boolean canElementEnableIndividualServices(Provider provider){ + NetworkElement element = getElementImplementingProvider(provider.getName()); + if(element == null){ + throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + provider.getName() + "'"); + } + return element.canEnableIndividualServices(); + } + @Override public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp) throws InsufficientAddressCapacityException { return fetchNewPublicIp(dcId, podId, null, owner, type, networkId, false, true, requestedIp); @@ -929,6 +958,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag _allowSubdomainNetworkAccess = Boolean.valueOf(_configs.get(Config.SubDomainNetworkAccess.key())); + _agentMgr.registerForHostEvents(this, true, false, true); + s_logger.info("Network Manager is configured."); return true; @@ -3747,9 +3778,18 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (pNetwork == null) { throw new InvalidParameterValueException("Network id=" + physicalNetworkId + "doesn't exist in the system"); } + Transaction txn = Transaction.currentTxn(); checkIfPhysicalNetworkIsDeletable(physicalNetworkId); + txn.start(); + + // delete vlans for this zone + List vlans = _vlanDao.listVlansByPhysicalNetworkId(physicalNetworkId); + for (VlanVO vlan : vlans) { + _vlanDao.remove(vlan.getId()); + } + // Delete networks List networks = _networksDao.listByPhysicalNetworkIncludingRemoved(physicalNetworkId); if (networks != null && !networks.isEmpty()) { @@ -3764,7 +3804,11 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag //delete service providers _pNSPDao.deleteProviders(physicalNetworkId); - return _physicalNetworkDao.remove(physicalNetworkId); + boolean success = _physicalNetworkDao.remove(physicalNetworkId); + + txn.commit(); + + return success; } @DB @@ -3787,14 +3831,14 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag privateIP.add(0, "op_dc_ip_address_alloc"); privateIP.add(1, "data_center_id"); privateIP.add(2, "there are private IP addresses allocated for this zone"); - tablesToCheck.add(privateIP); + tablesToCheck.add(privateIP);*/ List publicIP = new ArrayList(); publicIP.add(0, "user_ip_address"); - publicIP.add(1, "data_center_id"); - publicIP.add(2, "there are public IP addresses allocated for this zone"); + publicIP.add(1, "physical_network_id"); + publicIP.add(2, "there are public IP addresses allocated for this physical network"); tablesToCheck.add(publicIP); - */ + for (List table : tablesToCheck) { @@ -3838,8 +3882,25 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } @Override - public List listNetworkServices(){ - return Service.listAllServices(); + public List listNetworkServices(String providerName){ + + Provider provider = null; + if(providerName != null){ + provider = Network.Provider.getProvider(providerName); + if(provider == null){ + throw new InvalidParameterValueException("Invalid Network Service Provider=" + providerName); + } + } + + if(provider != null){ + NetworkElement element = getElementImplementingProvider(providerName); + if(element == null){ + throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + providerName + "'"); + } + return new ArrayList(element.getCapabilities().keySet()); + }else{ + return Service.listAllServices(); + } } @Override @@ -3868,7 +3929,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override @DB @ActionEvent(eventType = EventTypes.EVENT_SERVICE_PROVIDER_CREATE, eventDescription = "Creating Physical Network ServiceProvider", create = true) - public PhysicalNetworkServiceProvider addProviderToPhysicalNetwork(Long physicalNetworkId, String providerName, Long destinationPhysicalNetworkId) { + public PhysicalNetworkServiceProvider addProviderToPhysicalNetwork(Long physicalNetworkId, String providerName, Long destinationPhysicalNetworkId, List enabledServices) { // verify input parameters PhysicalNetworkVO network = _physicalNetworkDao.findById(physicalNetworkId); @@ -3890,12 +3951,43 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new InvalidParameterValueException("Invalid Network Service Provider=" + providerName); } } + + //check if services can be turned off + NetworkElement element = getElementImplementingProvider(providerName); + if(element == null){ + throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + providerName + "'"); + } + List services = new ArrayList(); + + if(enabledServices != null){ + if(!element.canEnableIndividualServices()){ + if(enabledServices.size() != element.getCapabilities().keySet().size()){ + throw new InvalidParameterValueException("Cannot enable subset of Services, Please specify the complete list of Services for this Service Provider '" + providerName + "'"); + } + } + + //validate Services + for(String serviceName : enabledServices){ + Network.Service service = Network.Service.getService(serviceName); + if(service == null){ + throw new InvalidParameterValueException("Invalid Network Service specified=" + serviceName); + } + services.add(service); + } + }else{ + //enable all the default services supported by this element. + services = new ArrayList(element.getCapabilities().keySet()); + + } Transaction txn = Transaction.currentTxn(); try { txn.start(); // Create the new physical network in the database PhysicalNetworkServiceProviderVO nsp = new PhysicalNetworkServiceProviderVO(physicalNetworkId, providerName); + //set enabled services + nsp.setEnabledServices(services); + if(destinationPhysicalNetworkId != null){ nsp.setDestinationPhysicalNetworkId(destinationPhysicalNetworkId); } @@ -3925,14 +4017,18 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag @Override @ActionEvent(eventType = EventTypes.EVENT_SERVICE_PROVIDER_UPDATE, eventDescription = "Updating physical network ServiceProvider", async = true) - public PhysicalNetworkServiceProvider updateNetworkServiceProvider(Long id, String stateStr, boolean forcedShutdown) throws ConcurrentOperationException, ResourceUnavailableException { + public PhysicalNetworkServiceProvider updateNetworkServiceProvider(Long id, String stateStr, boolean forcedShutdown, List enabledServices) throws ConcurrentOperationException, ResourceUnavailableException { PhysicalNetworkServiceProviderVO provider = _pNSPDao.findById(id); - if(provider == null){ throw new InvalidParameterValueException("Network Service Provider id=" + id + "doesn't exist in the system"); } + NetworkElement element = getElementImplementingProvider(provider.getProviderName()); + if(element == null){ + throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + provider.getProviderName() + "'"); + } + PhysicalNetworkServiceProvider.State state = null; if (stateStr != null && !stateStr.isEmpty()) { try { @@ -3942,25 +4038,23 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } } + boolean update = false; + if(state != null){ if(s_logger.isDebugEnabled()){ s_logger.debug("updating state of the service provider id=" + id + " on physical network: "+provider.getPhysicalNetworkId() + " to state: "+stateStr); } - NetworkElement element = getElementImplementingProvider(provider.getProviderName()); - if(element == null){ - throw new InvalidParameterValueException("Unable to find the Network Element implementing the Service Provider '" + provider.getProviderName() + "'"); - } switch(state) { case Enabled: if(element != null && element.isReady(provider)){ provider.setState(PhysicalNetworkServiceProvider.State.Enabled); - _pNSPDao.update(id, provider); + update = true; } break; case Disabled: //do we need to do anything for the provider instances before disabling? provider.setState(PhysicalNetworkServiceProvider.State.Disabled); - _pNSPDao.update(id, provider); + update = true; break; case Shutdown: User callerUser = _accountMgr.getActiveUser(UserContext.current().getCallerUserId()); @@ -3972,13 +4066,35 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } if(element != null && element.shutdownProviderInstances(provider, context, forcedShutdown)){ provider.setState(PhysicalNetworkServiceProvider.State.Shutdown); - _pNSPDao.update(id, provider); + update = true; } break; } } + if(enabledServices != null){ + //check if services can be turned of + if(!element.canEnableIndividualServices()){ + throw new InvalidParameterValueException("Cannot update set of Services for this Service Provider '" + provider.getProviderName() + "'"); + } + + //validate Services + List services = new ArrayList(); + for(String serviceName : enabledServices){ + Network.Service service = Network.Service.getService(serviceName); + if(service == null){ + throw new InvalidParameterValueException("Invalid Network Service specified=" + serviceName); + } + services.add(service); + } + //set enabled services + provider.setEnabledServices(services); + update = true; + } + if(update){ + _pNSPDao.update(id, provider); + } return provider; } @@ -4407,6 +4523,54 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } return networkList.get(0); + } + + @Override + public boolean processAnswers(long agentId, long seq, Answer[] answers) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean processCommands(long agentId, long seq, Command[] commands) { + // TODO Auto-generated method stub + return false; + } + + @Override + public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException { + // TODO Auto-generated method stub + + } + + @Override + public boolean processDisconnect(long agentId, Status state) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRecurring() { + // TODO Auto-generated method stub + return false; + } + + @Override + public int getTimeout() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean processTimeout(long agentId, long seq) { + // TODO Auto-generated method stub + return false; } diff --git a/server/src/com/cloud/network/dao/PhysicalNetworkServiceProviderVO.java b/server/src/com/cloud/network/dao/PhysicalNetworkServiceProviderVO.java index a731596be2a..df8837ed484 100644 --- a/server/src/com/cloud/network/dao/PhysicalNetworkServiceProviderVO.java +++ b/server/src/com/cloud/network/dao/PhysicalNetworkServiceProviderVO.java @@ -17,6 +17,9 @@ */ package com.cloud.network.dao; +import java.util.ArrayList; +import java.util.List; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; @@ -26,6 +29,7 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; +import com.cloud.network.Network.Service; import com.cloud.network.PhysicalNetworkServiceProvider; @Entity @@ -40,8 +44,7 @@ public class PhysicalNetworkServiceProviderVO implements PhysicalNetworkServiceP private long physicalNetworkId; @Column(name = "destination_physical_network_id") - private long destPhysicalNetworkId; - + private long destPhysicalNetworkId; @Column(name = "provider_name") private String providerName; @@ -50,6 +53,34 @@ public class PhysicalNetworkServiceProviderVO implements PhysicalNetworkServiceP @Enumerated(value=EnumType.STRING) State state; + @Column(name = "vpn_service_provided") + boolean vpnServiceProvided; + + @Column(name = "dhcp_service_provided") + boolean dhcpServiceProvided; + + @Column(name = "dns_service_provided") + boolean dnsServiceProvided; + + @Column(name = "gateway_service_provided") + boolean gatewayServiceProvided; + + @Column(name = "firewall_service_provided") + boolean firewallServiceProvided; + + @Column(name = "source_nat_service_provided") + boolean sourcenatServiceProvided; + + @Column(name = "load_balance_service_provided") + boolean lbServiceProvided; + + @Column(name = "user_data_service_provided") + boolean userdataServiceProvided; + + @Column(name = "security_group_service_provided") + boolean securitygroupServiceProvided; + + public PhysicalNetworkServiceProviderVO() { } @@ -93,4 +124,130 @@ public class PhysicalNetworkServiceProviderVO implements PhysicalNetworkServiceP public long getDestinationPhysicalNetworkId() { return destPhysicalNetworkId; } + + @Override + public boolean isVpnServiceProvided() { + return vpnServiceProvided; + } + + public void setVpnServiceProvided(boolean vpnServiceProvided) { + this.vpnServiceProvided = vpnServiceProvided; + } + + @Override + public boolean isDhcpServiceProvided() { + return dhcpServiceProvided; + } + + public void setDhcpServiceProvided(boolean dhcpServiceProvided) { + this.dhcpServiceProvided = dhcpServiceProvided; + } + + @Override + public boolean isDnsServiceProvided() { + return dnsServiceProvided; + } + + public void setDnsServiceProvided(boolean dnsServiceProvided) { + this.dnsServiceProvided = dnsServiceProvided; + } + + @Override + public boolean isGatewayServiceProvided() { + return gatewayServiceProvided; + } + + public void setGatewayServiceProvided(boolean gatewayServiceProvided) { + this.gatewayServiceProvided = gatewayServiceProvided; + } + + @Override + public boolean isFirewallServiceProvided() { + return firewallServiceProvided; + } + + public void setFirewallServiceProvided(boolean firewallServiceProvided) { + this.firewallServiceProvided = firewallServiceProvided; + } + + @Override + public boolean isSourcenatServiceProvided() { + return sourcenatServiceProvided; + } + + public void setSourcenatServiceProvided(boolean sourcenatServiceProvided) { + this.sourcenatServiceProvided = sourcenatServiceProvided; + } + + @Override + public boolean isLbServiceProvided() { + return lbServiceProvided; + } + + public void setLbServiceProvided(boolean lbServiceProvided) { + this.lbServiceProvided = lbServiceProvided; + } + + @Override + public boolean isUserdataServiceProvided() { + return userdataServiceProvided; + } + + public void setUserdataServiceProvided(boolean userdataServiceProvided) { + this.userdataServiceProvided = userdataServiceProvided; + } + + @Override + public boolean isSecuritygroupServiceProvided() { + return securitygroupServiceProvided; + } + + public void setSecuritygroupServiceProvided(boolean securitygroupServiceProvided) { + this.securitygroupServiceProvided = securitygroupServiceProvided; + } + + public void setEnabledServices(List services){ + this.setVpnServiceProvided(services.contains(Service.Vpn)); + this.setDhcpServiceProvided(services.contains(Service.Dhcp)); + this.setDnsServiceProvided(services.contains(Service.Dns)); + this.setGatewayServiceProvided(services.contains(Service.Gateway)); + this.setFirewallServiceProvided(services.contains(Service.Firewall)); + this.setLbServiceProvided(services.contains(Service.Lb)); + this.setSourcenatServiceProvided(services.contains(Service.SourceNat)); + this.setUserdataServiceProvided(services.contains(Service.UserData)); + this.setSecuritygroupServiceProvided(services.contains(Service.SecurityGroup)); + } + + @Override + public List getEnabledServices(){ + List services = new ArrayList(); + if(this.isVpnServiceProvided()){ + services.add(Service.Vpn); + } + if(this.isDhcpServiceProvided()){ + services.add(Service.Dhcp); + } + if(this.isDnsServiceProvided()){ + services.add(Service.Dns); + } + if(this.isGatewayServiceProvided()){ + services.add(Service.Gateway); + } + if(this.isFirewallServiceProvided()){ + services.add(Service.Firewall); + } + if(this.isLbServiceProvided()){ + services.add(Service.Lb); + } + if(this.sourcenatServiceProvided){ + services.add(Service.SourceNat); + } + if(this.isUserdataServiceProvided()){ + services.add(Service.UserData); + } + if(this.isSecuritygroupServiceProvided()){ + services.add(Service.SecurityGroup); + } + return services; + } } diff --git a/server/src/com/cloud/network/element/BareMetalElement.java b/server/src/com/cloud/network/element/BareMetalElement.java index a8d2c4c3f50..08b1bbbc7ad 100644 --- a/server/src/com/cloud/network/element/BareMetalElement.java +++ b/server/src/com/cloud/network/element/BareMetalElement.java @@ -117,4 +117,9 @@ public class BareMetalElement extends AdapterBase implements NetworkElement { public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context, boolean forceShutdown) throws ConcurrentOperationException, ResourceUnavailableException { return true; } + + @Override + public boolean canEnableIndividualServices() { + return false; + } } diff --git a/server/src/com/cloud/network/element/CloudZonesNetworkElement.java b/server/src/com/cloud/network/element/CloudZonesNetworkElement.java index 1cac85b6dd7..6751b5bf5e5 100644 --- a/server/src/com/cloud/network/element/CloudZonesNetworkElement.java +++ b/server/src/com/cloud/network/element/CloudZonesNetworkElement.java @@ -225,4 +225,9 @@ public class CloudZonesNetworkElement extends AdapterBase implements NetworkElem // TODO Auto-generated method stub return true; } + + @Override + public boolean canEnableIndividualServices() { + return false; + } } diff --git a/server/src/com/cloud/network/element/DhcpElement.java b/server/src/com/cloud/network/element/DhcpElement.java index df247a398f3..513b31b9064 100644 --- a/server/src/com/cloud/network/element/DhcpElement.java +++ b/server/src/com/cloud/network/element/DhcpElement.java @@ -268,4 +268,9 @@ public class DhcpElement extends AdapterBase implements DhcpElementService, User // TODO Auto-generated method stub return true; } + + @Override + public boolean canEnableIndividualServices() { + return false; + } } diff --git a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java index 030072478f0..99310597edd 100644 --- a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java @@ -168,4 +168,9 @@ public class ElasticLoadBalancerElement extends AdapterBase implements LoadBalan // TODO Auto-generated method stub return true; } + + @Override + public boolean canEnableIndividualServices() { + return false; + } } diff --git a/server/src/com/cloud/network/element/ExternalDhcpElement.java b/server/src/com/cloud/network/element/ExternalDhcpElement.java index 72f6db22b98..31d6e3d97d5 100644 --- a/server/src/com/cloud/network/element/ExternalDhcpElement.java +++ b/server/src/com/cloud/network/element/ExternalDhcpElement.java @@ -135,4 +135,9 @@ public class ExternalDhcpElement extends AdapterBase implements NetworkElement { // TODO Auto-generated method stub return true; } + + @Override + public boolean canEnableIndividualServices() { + return false; + } } diff --git a/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index eabb3c37af0..8af4efff350 100644 --- a/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -156,5 +156,10 @@ public class F5ExternalLoadBalancerElement extends AdapterBase implements LoadBa // TODO Auto-generated method stub return true; } + + @Override + public boolean canEnableIndividualServices() { + return false; + } } diff --git a/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index 7fa471fc37c..de1a8d55a8a 100644 --- a/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -256,6 +256,11 @@ public class JuniperSRXExternalFirewallElement extends AdapterBase implements So // TODO Auto-generated method stub return true; } + + @Override + public boolean canEnableIndividualServices() { + return false; + } } diff --git a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java index aaa941c4a31..e0b4519ae9f 100644 --- a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java @@ -156,4 +156,9 @@ public class NetscalerExternalLoadBalancerElement extends AdapterBase implements // TODO Auto-generated method stub return true; } + + @Override + public boolean canEnableIndividualServices() { + return false; + } } diff --git a/server/src/com/cloud/network/element/OvsElement.java b/server/src/com/cloud/network/element/OvsElement.java index 00e95a60234..2ca17783d1a 100644 --- a/server/src/com/cloud/network/element/OvsElement.java +++ b/server/src/com/cloud/network/element/OvsElement.java @@ -130,4 +130,9 @@ public class OvsElement extends AdapterBase implements NetworkElement { throws ConcurrentOperationException, ResourceUnavailableException { return true; } + + @Override + public boolean canEnableIndividualServices() { + return false; + } } diff --git a/server/src/com/cloud/network/element/SecurityGroupElement.java b/server/src/com/cloud/network/element/SecurityGroupElement.java index 18bd3db09bb..ac77ab8eacf 100644 --- a/server/src/com/cloud/network/element/SecurityGroupElement.java +++ b/server/src/com/cloud/network/element/SecurityGroupElement.java @@ -100,4 +100,9 @@ public class SecurityGroupElement extends AdapterBase implements NetworkElement public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context, boolean forceShutdown) throws ConcurrentOperationException, ResourceUnavailableException { return true; } + + @Override + public boolean canEnableIndividualServices() { + return false; + } } diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index e87e13e7f2e..be4967b2596 100644 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -460,6 +460,11 @@ public class VirtualRouterElement extends DhcpElement implements VirtualRouterEl ResourceUnavailableException { // TODO Auto-generated method stub return true; + } + + @Override + public boolean canEnableIndividualServices() { + return true; } @Override diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 1cd90d05255..cf912d30338 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -1782,6 +1782,15 @@ CREATE TABLE `cloud`.`physical_network_service_providers` ( `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name', `state` varchar(32) NOT NULL DEFAULT 'Disabled' COMMENT 'provider state', `destination_physical_network_id` bigint unsigned COMMENT 'id of the physical network to bridge to', + `vpn_service_provided` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is VPN service provided', + `dhcp_service_provided` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is DHCP service provided', + `dns_service_provided` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is DNS service provided', + `gateway_service_provided` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is Gateway service provided', + `firewall_service_provided` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is Firewall service provided', + `source_nat_service_provided` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is SNAT service provided', + `load_balance_service_provided` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is LB service provided', + `user_data_service_provided` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is UserData service provided', + `security_group_service_provided` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT 'Is SG service provided', PRIMARY KEY (`id`), CONSTRAINT `fk_pnetwork_service_providers__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;