Support for local data disk (part 2)

- Zone level config to enable/disable local storage usage for service and disk offerings.
- Local storage gets discovered when a host is added/reconnected if zone level config is enabled. When disabled existing local storages are not removed but any new local storage is not added.
- Deploy VM command validates service and disk offerings based on local storage config.
- Upgrade uses the global config 'use.local.storage' to set the zone level config for local storage.

Reviewed-by: Abhi, Nitin
This commit is contained in:
Koushik Das 2012-07-30 13:59:14 +05:30
parent ddcb3d7b30
commit bb17d09e01
17 changed files with 95 additions and 17 deletions

View File

@ -288,6 +288,7 @@ public class ApiConstants {
public static final String DHCP_RANGE = "dhcprange";
public static final String UUID = "uuid";
public static final String SECURITY_GROUP_EANBLED = "securitygroupenabled";
public static final String LOCAL_STORAGE_EANBLED = "localstorageenabled";
public static final String GUEST_IP_TYPE = "guestiptype";
public static final String XEN_NETWORK_LABEL = "xennetworklabel";
public static final String KVM_NETWORK_LABEL = "kvmnetworklabel";

View File

@ -69,6 +69,9 @@ public class CreateZoneCmd extends BaseCmd {
@Parameter(name=ApiConstants.SECURITY_GROUP_EANBLED, type=CommandType.BOOLEAN, description="true if network is security group enabled, false otherwise")
private Boolean securitygroupenabled;
@Parameter(name=ApiConstants.LOCAL_STORAGE_EANBLED, type=CommandType.BOOLEAN, description="true if local storage offering enabled, false otherwise")
private Boolean localStorageEnabled;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -119,8 +122,14 @@ public class CreateZoneCmd extends BaseCmd {
}
return securitygroupenabled;
}
public Boolean getLocalStorageEnabled() {
if (localStorageEnabled == null) {
return false;
}
return localStorageEnabled;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
@Override

View File

@ -372,13 +372,23 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
throw new InvalidParameterValueException("Unable to use template " + templateId, null);
}
DiskOffering diskOffering = null;
if (diskOfferingId != null) {
DiskOffering diskOffering = _configService.getDiskOffering(diskOfferingId);
diskOffering = _configService.getDiskOffering(diskOfferingId);
if (diskOffering == null) {
throw new InvalidParameterValueException("Unable to find disk offering by id", null);
}
}
if (!zone.isLocalStorageEnabled()) {
if (serviceOffering.getUseLocalStorage()) {
throw new InvalidParameterValueException("Zone is not configured to use local storage but service offering " + serviceOffering.getName() + " uses it", null);
}
if (diskOffering != null && diskOffering.getUseLocalStorage()) {
throw new InvalidParameterValueException("Zone is not configured to use local storage but disk offering " + diskOffering.getName() + " uses it", null);
}
}
UserVm vm = null;
if (getHypervisor() == HypervisorType.BareMetal) {
vm = _bareMetalVmService.createVirtualMachine(this);

View File

@ -23,6 +23,7 @@ import com.cloud.api.IdentityMapper;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.response.ZoneResponse;
import com.cloud.dc.DataCenter;
import com.cloud.user.Account;
@ -77,7 +78,10 @@ public class UpdateZoneCmd extends BaseCmd {
@Parameter(name=ApiConstants.DNS_SEARCH_ORDER, type=CommandType.LIST, collectionType = CommandType.STRING, description="the dns search order list")
private List<String> dnsSearchOrder;
@Parameter(name=ApiConstants.LOCAL_STORAGE_EANBLED, type=CommandType.BOOLEAN, description="true if local storage offering enabled, false otherwise")
private Boolean localStorageEnabled;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -133,6 +137,14 @@ public class UpdateZoneCmd extends BaseCmd {
public List<String> getDnsSearchOrder() {
return dnsSearchOrder;
}
public Boolean getLocalStorageEnabled() {
if (localStorageEnabled == null) {
return false;
}
return localStorageEnabled;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -82,6 +82,9 @@ public class ZoneResponse extends BaseResponse {
@SerializedName("capacity") @Param(description="the capacity of the Zone", responseObject = CapacityResponse.class)
private List<CapacityResponse> capacitites;
@SerializedName(ApiConstants.LOCAL_STORAGE_EANBLED) @Param(description="true if local storage offering enabled, false otherwise")
private boolean localStorageEnabled;
public void setId(Long id) {
this.id.setValue(id);
}
@ -161,4 +164,8 @@ public class ZoneResponse extends BaseResponse {
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public void setLocalStorageEnabled(boolean localStorageEnabled) {
this.localStorageEnabled = localStorageEnabled;
}
}

View File

@ -71,4 +71,5 @@ public interface DataCenter extends Grouping {
String getZoneToken();
boolean isLocalStorageEnabled();
}

View File

@ -1017,6 +1017,7 @@ label.linklocal.ip=Link Local IP Adddress
label.load.balancer=Load Balancer
label.loading=Loading
label.local=Local
label.local.storage.enabled=Local Storage Enabled
label.login=Login
label.logout=Logout
label.lun=LUN

View File

@ -946,6 +946,7 @@ public class ApiResponseHelper implements ResponseGenerator {
zoneResponse.setId(dataCenter.getId());
zoneResponse.setName(dataCenter.getName());
zoneResponse.setSecurityGroupsEnabled(ApiDBUtils.isSecurityGroupEnabledInZone(dataCenter.getId()));
zoneResponse.setLocalStorageEnabled(dataCenter.isLocalStorageEnabled());
if ((dataCenter.getDescription() != null) && !dataCenter.getDescription().equalsIgnoreCase("null")) {
zoneResponse.setDescription(dataCenter.getDescription());

View File

@ -129,7 +129,7 @@ public interface ConfigurationManager extends ConfigurationService, Manager {
* @throws
*/
DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String guestCidr, String domain, Long domainId, NetworkType zoneType, String allocationState,
String networkDomain, boolean isSecurityGroupEnabled);
String networkDomain, boolean isSecurityGroupEnabled, boolean isLocalStorageEnabled);
/**
* Deletes a VLAN from the database, along with all of its IP addresses. Will not delete VLANs that have allocated

View File

@ -1360,6 +1360,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
String dhcpProvider = cmd.getDhcpProvider();
Map<?, ?> detailsMap = cmd.getDetails();
String networkDomain = cmd.getDomain();
Boolean localStorageEnabled = cmd.getLocalStorageEnabled();
Map<String, String> newDetails = new HashMap<String, String>();
if (detailsMap != null) {
@ -1466,6 +1467,9 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
zone.setInternalDns1(internalDns1);
zone.setInternalDns2(internalDns2);
zone.setGuestNetworkCidr(guestCidr);
if (localStorageEnabled != null) {
zone.setLocalStorageEnabled(localStorageEnabled.booleanValue());
}
if (networkDomain != null) {
if (networkDomain.isEmpty()) {
@ -1539,7 +1543,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
@Override
@DB
public DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String guestCidr, String domain, Long domainId,
NetworkType zoneType, String allocationStateStr, String networkDomain, boolean isSecurityGroupEnabled) {
NetworkType zoneType, String allocationStateStr, String networkDomain, boolean isSecurityGroupEnabled, boolean isLocalStorageEnabled) {
// checking the following params outside checkzoneparams method as we do
// not use these params for updatezone
@ -1565,7 +1569,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
try {
txn.start();
// Create the new zone in the database
DataCenterVO zone = new DataCenterVO(zoneName, null, dns1, dns2, internalDns1, internalDns2, guestCidr, domain, domainId, zoneType, zoneToken, networkDomain, isSecurityGroupEnabled);
DataCenterVO zone = new DataCenterVO(zoneName, null, dns1, dns2, internalDns1, internalDns2, guestCidr, domain, domainId, zoneType, zoneToken, networkDomain, isSecurityGroupEnabled, isLocalStorageEnabled);
if (allocationStateStr != null && !allocationStateStr.isEmpty()) {
Grouping.AllocationState allocationState = Grouping.AllocationState.valueOf(allocationStateStr);
zone.setAllocationState(allocationState);
@ -1645,6 +1649,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
String allocationState = cmd.getAllocationState();
String networkDomain = cmd.getDomain();
boolean isSecurityGroupEnabled = cmd.getSecuritygroupenabled();
boolean isLocalStorageEnabled = cmd.getLocalStorageEnabled();
if (allocationState == null) {
allocationState = Grouping.AllocationState.Disabled.toString();
@ -1678,7 +1683,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
}
return createZone(userId, zoneName, dns1, dns2, internalDns1, internalDns2, guestCidr, domainVO != null ? domainVO.getName() : null, domainId, zoneType, allocationState, networkDomain,
isSecurityGroupEnabled);
isSecurityGroupEnabled, isLocalStorageEnabled);
}
@Override

View File

@ -123,6 +123,9 @@ public class DataCenterVO implements DataCenter, Identity {
@Column(name="is_security_group_enabled")
boolean securityGroupEnabled;
@Column(name="is_local_storage_enabled")
boolean localStorageEnabled;
@Override
public String getDnsProvider() {
return dnsProvider;
@ -168,14 +171,14 @@ public class DataCenterVO implements DataCenter, Identity {
this.firewallProvider = firewallProvider;
}
public DataCenterVO(long id, String name, String description, String dns1, String dns2, String dns3, String dns4,String guestCidr, String domain, Long domainId, NetworkType zoneType, String zoneToken, String domainSuffix) {
this(name, description, dns1, dns2, dns3, dns4, guestCidr, domain, domainId, zoneType, zoneToken, domainSuffix, false);
public DataCenterVO(long id, String name, String description, String dns1, String dns2, String dns3, String dns4, String guestCidr, String domain, Long domainId, NetworkType zoneType, String zoneToken, String domainSuffix) {
this(name, description, dns1, dns2, dns3, dns4, guestCidr, domain, domainId, zoneType, zoneToken, domainSuffix, false, false);
this.id = id;
this.allocationState = Grouping.AllocationState.Enabled;
this.uuid = UUID.randomUUID().toString();
}
public DataCenterVO(String name, String description, String dns1, String dns2, String dns3, String dns4, String guestCidr, String domain, Long domainId, NetworkType zoneType, String zoneToken, String domainSuffix, boolean securityGroupEnabled) {
public DataCenterVO(String name, String description, String dns1, String dns2, String dns3, String dns4, String guestCidr, String domain, Long domainId, NetworkType zoneType, String zoneToken, String domainSuffix, boolean securityGroupEnabled, boolean localStorageEnabled) {
this.name = name;
this.description = description;
this.dns1 = dns1;
@ -188,7 +191,7 @@ public class DataCenterVO implements DataCenter, Identity {
this.networkType = zoneType;
this.allocationState = Grouping.AllocationState.Enabled;
this.securityGroupEnabled = securityGroupEnabled;
this.localStorageEnabled = localStorageEnabled;
if (zoneType == NetworkType.Advanced) {
loadBalancerProvider = Provider.VirtualRouter.getName();
@ -341,6 +344,15 @@ public class DataCenterVO implements DataCenter, Identity {
this.securityGroupEnabled = enabled;
}
@Override
public boolean isLocalStorageEnabled() {
return localStorageEnabled;
}
public void setLocalStorageEnabled(boolean enabled) {
this.localStorageEnabled = enabled;
}
@Override
public Map<String, String> getDetails() {
return details;

View File

@ -27,6 +27,8 @@ import com.cloud.agent.api.StoragePoolInfo;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.ConnectionException;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
@ -43,6 +45,7 @@ public class LocalStoragePoolListener implements Listener {
@Inject StoragePoolDao _storagePoolDao;
@Inject StoragePoolHostDao _storagePoolHostDao;
@Inject CapacityDao _capacityDao;
@Inject DataCenterDao _dcDao;
@Inject StorageManager _storageMgr;
@Override
@ -83,6 +86,11 @@ public class LocalStoragePoolListener implements Listener {
return;
}
DataCenterVO dc = _dcDao.findById(host.getDataCenterId());
if (dc == null || !dc.isLocalStorageEnabled()) {
return;
}
try {
StoragePoolVO pool = _storagePoolDao.findPoolByHostPath(host.getDataCenterId(), host.getPodId(), pInfo.getHost(), pInfo.getHostPath(), pInfo.getUuid());
if(pool == null && host.getHypervisorType() == HypervisorType.VMware) {

View File

@ -959,10 +959,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
int wrks = NumbersUtil.parseInt(workers, 10);
_executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("StorageManager-Scavenger"));
boolean localStorage = Boolean.parseBoolean(configs.get(Config.UseLocalStorage.key()));
if (localStorage) {
_agentMgr.registerForHostEvents(ComponentLocator.inject(LocalStoragePoolListener.class), true, false, false);
}
_agentMgr.registerForHostEvents(ComponentLocator.inject(LocalStoragePoolListener.class), true, false, false);
String maxVolumeSizeInGbString = configDao.getValue("storage.max.volume.size");
_maxVolumeSizeInGb = NumbersUtil.parseLong(maxVolumeSizeInGbString, 2000);

View File

@ -549,6 +549,7 @@ CREATE TABLE `cloud`.`data_center` (
`allocation_state` varchar(32) NOT NULL DEFAULT 'Enabled' COMMENT 'Is this data center enabled for allocation for new resources',
`zone_token` varchar(255),
`is_security_group_enabled` tinyint NOT NULL DEFAULT 0 COMMENT '1: enabled, 0: not',
`is_local_storage_enabled` tinyint NOT NULL DEFAULT 0 COMMENT 'Is local storage offering enabled for this data center; 1: enabled, 0: not',
`removed` datetime COMMENT 'date removed if not null',
PRIMARY KEY (`id`),
CONSTRAINT `fk_data_center__domain_id` FOREIGN KEY (`domain_id`) REFERENCES `domain`(`id`),

View File

@ -340,4 +340,5 @@ CREATE TABLE `cloud`.`s2s_vpn_connection` (
CONSTRAINT `uc_s2s_vpn_connection__uuid` UNIQUE (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `cloud`.`data_center` ADD COLUMN `is_local_storage_enabled` tinyint NOT NULL DEFAULT 0 COMMENT 'Is local storage offering enabled for this data center; 1: enabled, 0: not';
UPDATE `cloud`.`data_center` SET `is_local_storage_enabled` = IF ((SELECT `value` FROM `cloud`.`configuration` WHERE `name`='use.local.storage')='true', 1, 0) WHERE `removed` IS NULL;

View File

@ -2430,6 +2430,7 @@ dictionary = {
'label.load.balancer': '<fmt:message key="label.load.balancer" />',
'label.loading': '<fmt:message key="label.loading" />',
'label.local': '<fmt:message key="label.local" />',
'label.local.storage.enabled': '<fmt:message key="label.local.storage.enabled" />',
'label.login': '<fmt:message key="label.login" />',
'label.logout': '<fmt:message key="label.logout" />',
'label.lun': '<fmt:message key="label.lun" />',

View File

@ -3832,6 +3832,7 @@
array1.push("&internaldns1=" + todb(args.data.internaldns1));
array1.push("&internaldns2=" + todb(args.data.internaldns2)); //internaldns2 can be empty ("") when passed to API
array1.push("&domain=" + todb(args.data.domain));
array1.push("&localstorageenabled=" + todb(args.data.localstorageenabled));
$.ajax({
url: createURL("updateZone&id=" + args.context.physicalResources[0].id + array1.join("")),
dataType: "json",
@ -3875,6 +3876,16 @@
domain: {
label: 'label.network.domain',
isEditable: true
},
localstorageenabled: {
label: 'label.local.storage.enabled',
converter: function(args) {
if(args)
return "true";
else
return "false";
},
isEditable: true
}
}
],