Added ability to list network offerings availabe for network upgrade using listNetworkOfferings command with "networkId" parameter.

Limitations:

* can't upgrade to the network offering with lesser number of services
* can upgrade only when the service provider of the original offering is not external (domR, dhcp, elb) to the external type of the provider
This commit is contained in:
alena 2011-10-21 15:33:57 -07:00
parent aa808f5685
commit abca3dda9d
13 changed files with 206 additions and 88 deletions

View File

@ -27,6 +27,7 @@ import com.cloud.api.ApiConstants;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.NetworkOfferingResponse;
import com.cloud.offering.NetworkOffering;
@ -75,6 +76,9 @@ public class ListNetworkOfferingsCmd extends BaseListCmd {
@Parameter(name=ApiConstants.STATE, type=CommandType.STRING, description="list network offerings by state")
private String state;
@Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, description="the ID of the network. Pass this in if you want to see the available network offering that a network can be changed to.")
private Long networkId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -128,6 +132,10 @@ public class ListNetworkOfferingsCmd extends BaseListCmd {
return state;
}
public Long getNetworkId() {
return networkId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -26,7 +26,6 @@ import com.cloud.api.ApiConstants;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.ServiceOfferingResponse;
import com.cloud.offering.ServiceOffering;

View File

@ -113,35 +113,35 @@ public class UpdateNetworkOfferingCmd extends BaseCmd {
}
public Boolean getDhcpService() {
return dhcpService;
return dhcpService == null ? false : dhcpService;
}
public Boolean getDnsService() {
return dnsService;
return dnsService == null ? false : dnsService;
}
public Boolean getGatewayService() {
return gatewayService;
return gatewayService == null ? false : gatewayService;
}
public Boolean getFirewallService() {
return firewallService;
return firewallService == null ? false : firewallService;
}
public Boolean getLbService() {
return lbService;
return lbService == null ? false : lbService;
}
public Boolean getUserdataService() {
return userdataService;
return userdataService == null ? false : userdataService;
}
public Boolean getSourceNatService() {
return sourceNatService;
return sourceNatService == null ? false : sourceNatService;
}
public Boolean getVpnService() {
return vpnService;
return vpnService == null ? false : vpnService;
}
public Map<String, List<String>> getServiceProviders() {

View File

@ -111,22 +111,25 @@ public interface Network extends ControlledEntity {
public static class Provider {
private static List<Provider> supportedProviders = new ArrayList<Provider>();
public static final Provider VirtualRouter = new Provider("VirtualRouter");
public static final Provider DhcpServer = new Provider("DhcpServer");
public static final Provider JuniperSRX = new Provider("JuniperSRX");
public static final Provider F5BigIp = new Provider("F5BigIp");
public static final Provider NetscalerMPX = new Provider("NetscalerMPX");
public static final Provider ExternalDhcpServer = new Provider("ExternalDhcpServer");
public static final Provider ExternalGateWay = new Provider("ExternalGateWay");
public static final Provider ElasticLoadBalancerVm = new Provider("ElasticLoadBalancerVm");
public static final Provider VirtualRouter = new Provider("VirtualRouter", false);
public static final Provider DhcpServer = new Provider("DhcpServer", false);
public static final Provider JuniperSRX = new Provider("JuniperSRX", true);
public static final Provider F5BigIp = new Provider("F5BigIp", true);
public static final Provider NetscalerMPX = new Provider("NetscalerMPX", true);
public static final Provider ExternalDhcpServer = new Provider("ExternalDhcpServer", true);
public static final Provider ExternalGateWay = new Provider("ExternalGateWay", true);
public static final Provider ElasticLoadBalancerVm = new Provider("ElasticLoadBalancerVm", false);
public static final Provider defaultProvider = VirtualRouter;
public static final Provider None = new Provider("None");
public static final Provider None = new Provider("None", false);
private String name;
private boolean isExternal;
public Provider(String name) {
public Provider(String name, boolean isExternal) {
this.name = name;
this.isExternal = isExternal;
supportedProviders.add(this);
}
@ -134,6 +137,10 @@ public interface Network extends ControlledEntity {
return name;
}
public boolean isExternal() {
return isExternal;
}
public static Provider getProvider(String providerName) {
for (Provider provider : supportedProviders) {
if (provider.getName().equalsIgnoreCase(providerName)) {

View File

@ -139,7 +139,6 @@ import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.ConsoleProxyDao;
import com.cloud.vm.dao.DomainRouterDao;
@ -2874,10 +2873,11 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
@Override
public List<? extends NetworkOffering> searchForNetworkOfferings(ListNetworkOfferingsCmd cmd) {
Account caller = UserContext.current().getCaller();
Filter searchFilter = new Filter(NetworkOfferingVO.class, "created", false, cmd.getStartIndex(), cmd.getPageSizeVal());
SearchCriteria<NetworkOfferingVO> sc = _networkOfferingDao.createSearchCriteria();
Object id = cmd.getId();
Long id = cmd.getId();
Object name = cmd.getNetworkOfferingName();
Object displayText = cmd.getDisplayText();
Object trafficType = cmd.getTrafficType();
@ -2890,6 +2890,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
Object state = cmd.getState();
Long zoneId = cmd.getZoneId();
DataCenter zone = null;
Long networkId = cmd.getNetworkId();
if (zoneId != null) {
zone = getZone(zoneId);
@ -2905,10 +2906,6 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
if (guestIpType != null) {
sc.addAnd("guestType", SearchCriteria.Op.EQ, guestIpType);
}
@ -2956,9 +2953,37 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
sc.addAnd("guestType", SearchCriteria.Op.EQ, GuestIpType.Direct);
}
}
// Don't return system network offerings to the user
sc.addAnd("systemOnly", SearchCriteria.Op.EQ, false);
//list offerings available for upgrade only
if (networkId != null) {
//check if network exists and the caller can operate with it
Network network = _networkMgr.getNetwork(networkId);
if (network == null) {
throw new InvalidParameterValueException("Unable to find the network by id=" + networkId);
}
// Don't allow to update system network
NetworkOffering offering = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId());
if (offering.isSystemOnly()) {
throw new InvalidParameterValueException("Can't update system networks");
}
_accountMgr.checkAccess(caller, null, network);
List<Long> offeringIds = _networkMgr.listNetworkOfferingsForUpgrade(networkId);
if (!offeringIds.isEmpty()) {
sc.addAnd("id", SearchCriteria.Op.IN, offeringIds.toArray());
} else {
return new ArrayList<NetworkOffering>();
}
}
if (id != null) {
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
return _networkOfferingDao.search(sc, searchFilter);
}

View File

@ -222,5 +222,7 @@ public interface NetworkManager extends NetworkService {
Long getPodIdForVlan(long vlanDbId);
boolean isProviderSupported(long networkOfferingId, Service service, Provider provider);
List<Long> listNetworkOfferingsForUpgrade(long networkId);
}

View File

@ -1787,36 +1787,38 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
// If networkDomain is not specified, take it from the global configuration
Map<Network.Capability, String> dnsCapabilities = getServiceCapabilities(zoneId, networkOfferingId, Service.Dns);
String isUpdateDnsSupported = dnsCapabilities.get(Capability.AllowDnsSuffixModification);
if (isUpdateDnsSupported == null || !Boolean.valueOf(isUpdateDnsSupported)) {
if (networkDomain != null) {
throw new InvalidParameterValueException("Domain name change is not supported by network offering id=" + networkOfferingId + " in zone id=" + zoneId);
}
} else {
if (networkDomain == null) {
//1) Get networkDomain from the corresponding account/domain/zone
if (isShared) {
if (domainId != null) {
networkDomain = getDomainNetworkDomain(domainId, zoneId);
} else {
networkDomain = getZoneNetworkDomain(zoneId);
}
} else {
networkDomain = getAccountNetworkDomain(owner.getId(), zoneId);
if (isServiceSupported(networkOfferingId, Service.Dns)) {
Map<Network.Capability, String> dnsCapabilities = getServiceCapabilities(zoneId, networkOfferingId, Service.Dns);
String isUpdateDnsSupported = dnsCapabilities.get(Capability.AllowDnsSuffixModification);
if (isUpdateDnsSupported == null || !Boolean.valueOf(isUpdateDnsSupported)) {
if (networkDomain != null) {
throw new InvalidParameterValueException("Domain name change is not supported by network offering id=" + networkOfferingId + " in zone id=" + zoneId);
}
//2) If null, generate networkDomain using domain suffix from the global config variables
if (networkDomain == null) {
networkDomain = "cs" + Long.toHexString(owner.getId()) + _networkDomain;
}
} else {
// validate network domain
if (!NetUtils.verifyDomainName(networkDomain)) {
throw new InvalidParameterValueException(
"Invalid network domain. Total length shouldn't exceed 190 chars. Each domain label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
+ "and the hyphen ('-'); can't start or end with \"-\"");
if (networkDomain == null) {
//1) Get networkDomain from the corresponding account/domain/zone
if (isShared) {
if (domainId != null) {
networkDomain = getDomainNetworkDomain(domainId, zoneId);
} else {
networkDomain = getZoneNetworkDomain(zoneId);
}
} else {
networkDomain = getAccountNetworkDomain(owner.getId(), zoneId);
}
//2) If null, generate networkDomain using domain suffix from the global config variables
if (networkDomain == null) {
networkDomain = "cs" + Long.toHexString(owner.getId()) + _networkDomain;
}
} else {
// validate network domain
if (!NetUtils.verifyDomainName(networkDomain)) {
throw new InvalidParameterValueException(
"Invalid network domain. Total length shouldn't exceed 190 chars. Each domain label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
+ "and the hyphen ('-'); can't start or end with \"-\"");
}
}
}
}
@ -2661,7 +2663,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
public Map<Capability, String> getServiceCapabilities(long zoneId, Long networkOfferingId, Service service) {
if (!isServiceSupported(networkOfferingId, service)) {
throw new UnsupportedServiceException("Service " + service.getName() + " is not by the network offering id=" + networkOfferingId);
throw new UnsupportedServiceException("Service " + service.getName() + " is not supported by the network offering id=" + networkOfferingId);
}
Map<Service, Map<Capability, String>> networkCapabilities = getZoneCapabilities(zoneId);
@ -3156,6 +3158,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
if (networkOffering == null || networkOffering.isSystemOnly()) {
throw new InvalidParameterValueException("Unable to find network offering by id " + networkOfferingId);
}
//network offering should be in Enabled state
if (networkOffering.getState() != NetworkOffering.State.Enabled) {
throw new InvalidParameterValueException("Network offering " + networkOffering + " is not in " + NetworkOffering.State.Enabled + " state, can't upgrade to it");
}
if (networkOffering.getAvailability() == Availability.Unavailable || networkOffering.getState() == NetworkOffering.State.Disabled || networkOffering.getState() == NetworkOffering.State.Inactive) {
throw new InvalidParameterValueException("Can't update network; network offering id=" + networkOfferingId + " is " + networkOffering.getAvailability() + " and " + networkOffering.getState());
}
@ -3410,31 +3418,47 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return false;
}
// //list of services and providers should be the same
// Map<String, Set<String>> newServices = listNetworkOfferingServices(newNetworkOfferingId);
// Map<String, Set<String>> oldServices = listNetworkOfferingServices(oldNetworkOfferingId);
//
// if (newServices.size() != oldServices.size()) {
// s_logger.debug("Number of supported services is not the same for offering " + newNetworkOfferingId + " and " + oldNetworkOfferingId);
// return false;
// }
//
// for (String service : newServices.keySet()) {
// Set<String> newProviders = newServices.get(service);
// Set<String> oldProviders = oldServices.get(service);
// if (newProviders.size() != oldProviders.size()) {
// s_logger.debug("Number of providers for the service " + service + " is not the same for offering " + newNetworkOfferingId + " and " + oldNetworkOfferingId);
// return false;
// }
//
// for (String provider : newProviders) {
// if (!oldProviders.contains(provider)) {
// s_logger.debug("Providers are different for the " + service + " is not the same for offering " + newNetworkOfferingId + " and " + oldNetworkOfferingId);
// return false;
// }
// }
// }
//compare providers
return canUpgradeProviders(oldNetworkOfferingId, newNetworkOfferingId);
}
protected boolean canUpgradeProviders(long oldNetworkOfferingId, long newNetworkOfferingId) {
//list of services and providers should be the same
Map<String, Set<String>> newServices = listNetworkOfferingServices(newNetworkOfferingId);
Map<String, Set<String>> oldServices = listNetworkOfferingServices(oldNetworkOfferingId);
if (newServices.size() < oldServices.size()) {
s_logger.debug("Network offering downgrade is not allowed: number of supported services for the new offering " + newNetworkOfferingId + " is less than the old offering " + oldNetworkOfferingId);
return false;
}
for (String service : oldServices.keySet()) {
//1)check that all old services are present in the new network offering
if (!newServices.containsKey(service)) {
s_logger.debug("New service offering doesn't have " + service + " service present in the old service offering, downgrade is not allowed");
return false;
}
Set<String> newProviders = newServices.get(service);
Set<String> oldProviders = oldServices.get(service);
//2) Can upgrade only from internal provider to external provider. Any other combinations are not allowed
for (String oldProvider : oldProviders) {
if (newProviders.contains(oldProvider)) {
s_logger.trace("New list of providers contains provider " + oldProvider);
continue;
}
//iterate through new providers and check that the old provider can upgrade
for (String newProvider : newProviders) {
if (!(!Provider.getProvider(oldProvider).isExternal() && Provider.getProvider(newProvider).isExternal())) {
s_logger.debug("Can't downgrade from network offering " + oldNetworkOfferingId + " to the new networkOffering " + newNetworkOfferingId);
return false;
}
}
}
}
return true;
}
@ -3489,7 +3513,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
throw new InvalidParameterValueException("Unable to resolve broadcastDomainRange '" + broadcastDomainRangeStr + "' to a supported value {Pod or Zone}");
}
}
Transaction txn = Transaction.currentTxn();
try {
@ -3940,5 +3963,23 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return pNtwks.get(0).getId();
}
@Override
public List<Long> listNetworkOfferingsForUpgrade(long networkId) {
List<Long> offeringIdsToReturn = new ArrayList<Long>();
NetworkOffering originalOffering = _configMgr.getNetworkOffering(getNetwork(networkId).getNetworkOfferingId());
List<Long> offerings = _networkOfferingDao.getOfferingIdsToUpgradeFrom(originalOffering);
//check if providers are upgradable
for (Long offering : offerings) {
if (canUpgradeProviders(originalOffering.getId(), offering.longValue())) {
offeringIdsToReturn.add(offering);
}
}
return offeringIdsToReturn;
}
}

View File

@ -338,7 +338,7 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
@Override
public Long getNetworkCountByOfferingId(long offeringId) {
SearchCriteria<Long> sc = CountByOfferingId.create();
sc.setParameters("offering", offeringId);
sc.setParameters("offeringId", offeringId);
List<Long> results = customSearch(sc, null);
return results.get(0);
}

View File

@ -79,7 +79,7 @@ public class DirectPodBasedNetworkGuru extends DirectNetworkGuru {
@Override
protected boolean canHandle(NetworkOffering offering, DataCenter dc) {
// this guru handles system Direct pod based network
if (dc.getNetworkType() == NetworkType.Basic && offering.getTrafficType() == TrafficType.Guest && offering.isSecurityGroupEnabled()) {
if (dc.getNetworkType() == NetworkType.Basic && offering.getTrafficType() == TrafficType.Guest) {
return true;
} else {
s_logger.trace("We only take care of Guest Direct Pod based networks");

View File

@ -686,7 +686,6 @@ public class ElasticLoadBalancerManagerImpl implements
s_logger.warn("Failed to deploy a new ELB vm for ip " + ipAddr + " in network " + network + "lb name=" + lb.getName());
if (newIp)
releaseIp(ipId, UserContext.current().getCallerUserId(), account);
}
}

View File

@ -25,6 +25,7 @@ import java.util.List;
import com.cloud.network.Network.GuestIpType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.Availability;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.utils.db.GenericDao;
@ -59,5 +60,7 @@ public interface NetworkOfferingDao extends GenericDao<NetworkOfferingVO, Long>
List<NetworkOfferingVO> listByAvailability(Availability availability, boolean isSystem);
List<NetworkOfferingVO> listByTrafficTypeAndGuestType(boolean isSystem, TrafficType trafficType, GuestIpType guestType);
List<Long> getOfferingIdsToUpgradeFrom(NetworkOffering originalOffering);
}

View File

@ -29,12 +29,15 @@ import javax.persistence.EntityExistsException;
import com.cloud.network.Network.GuestIpType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.Availability;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
@Local(value=NetworkOfferingDao.class) @DB(txn=false)
public class NetworkOfferingDaoImpl extends GenericDaoBase<NetworkOfferingVO, Long> implements NetworkOfferingDao {
@ -42,6 +45,7 @@ public class NetworkOfferingDaoImpl extends GenericDaoBase<NetworkOfferingVO, Lo
final SearchBuilder<NetworkOfferingVO> SystemOfferingSearch;
final SearchBuilder<NetworkOfferingVO> AvailabilitySearch;
final SearchBuilder<NetworkOfferingVO> TrafficTypeGuestTypeSearch;
private final GenericSearchBuilder<NetworkOfferingVO, Long> UpgradeSearch;
protected NetworkOfferingDaoImpl() {
super();
@ -65,6 +69,16 @@ public class NetworkOfferingDaoImpl extends GenericDaoBase<NetworkOfferingVO, Lo
TrafficTypeGuestTypeSearch.and("guestType", TrafficTypeGuestTypeSearch.entity().getGuestType(), SearchCriteria.Op.EQ);
TrafficTypeGuestTypeSearch.and("isSystem", TrafficTypeGuestTypeSearch.entity().isSystemOnly(), SearchCriteria.Op.EQ);
TrafficTypeGuestTypeSearch.done();
UpgradeSearch = createSearchBuilder(Long.class);
UpgradeSearch.selectField(UpgradeSearch.entity().getId());
UpgradeSearch.and("physicalNetworkId", UpgradeSearch.entity().getId(), Op.NEQ);
UpgradeSearch.and("physicalNetworkId", UpgradeSearch.entity().isSystemOnly(), Op.EQ);
UpgradeSearch.and("trafficType", UpgradeSearch.entity().getTrafficType(), Op.EQ);
UpgradeSearch.and("type", UpgradeSearch.entity().getType(), Op.EQ);
UpgradeSearch.and("state", UpgradeSearch.entity().getState(), Op.EQ);
UpgradeSearch.and("securityGroupEnabled", UpgradeSearch.entity().isSecurityGroupEnabled(), Op.EQ);
UpgradeSearch.done();
}
@Override
@ -131,4 +145,27 @@ public class NetworkOfferingDaoImpl extends GenericDaoBase<NetworkOfferingVO, Lo
update(networkOfferingId, offering);
return super.remove(networkOfferingId);
}
@Override
public List<Long> getOfferingIdsToUpgradeFrom(NetworkOffering originalOffering) {
SearchCriteria<Long> sc = UpgradeSearch.create();
//exclude original offering
sc.addAnd("id", SearchCriteria.Op.NEQ, originalOffering.getId());
//list only non-system offerings
sc.addAnd("systemOnly", SearchCriteria.Op.EQ, false);
//security group property should be the same
sc.addAnd("securityGroupEnabled", SearchCriteria.Op.EQ, originalOffering.isSecurityGroupEnabled());
//Type of the network should be the same
sc.addAnd("type", SearchCriteria.Op.EQ, originalOffering.getType());
//Traffic types should be the same
sc.addAnd("trafficType", SearchCriteria.Op.EQ, originalOffering.getTrafficType());
sc.addAnd("state", SearchCriteria.Op.EQ, NetworkOffering.State.Enabled);
return customSearch(sc, null);
}
}

View File

@ -768,11 +768,8 @@ public class ManagementServerImpl implements ManagementServer {
if ((vmInstance == null) || (vmInstance.getRemoved() != null)) {
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
}
if ((caller != null) && !isAdmin(caller.getType())) {
if (caller.getId() != vmInstance.getAccountId()) {
throw new PermissionDeniedException("unable to find a virtual machine with id " + vmId + " for this account");
}
}
_accountMgr.checkAccess(caller, null, vmInstance);
ServiceOfferingVO offering = _offeringsDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId());
sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId());