blob: c3379ad316bbf6c3aeee779af2441e12a20afebb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.storage.volume.datastore;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
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.hypervisor.Hypervisor.HypervisorType;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ScopeType;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
@Component
public class PrimaryDataStoreHelper {
private static final Logger s_logger = Logger.getLogger(PrimaryDataStoreHelper.class);
@Inject
private PrimaryDataStoreDao dataStoreDao;
@Inject
DataStoreManager dataStoreMgr;
@Inject
StorageManager storageMgr;
@Inject
protected CapacityDao _capacityDao;
@Inject
protected StoragePoolHostDao storagePoolHostDao;
@Inject
private AnnotationDao annotationDao;
public DataStore createPrimaryDataStore(PrimaryDataStoreParameters params) {
if(params == null)
{
throw new InvalidParameterValueException("createPrimaryDataStore: Input params is null, please check");
}
StoragePoolVO dataStoreVO = dataStoreDao.findPoolByUUID(params.getUuid());
if (dataStoreVO != null) {
throw new CloudRuntimeException("duplicate uuid: " + params.getUuid());
}
dataStoreVO = new StoragePoolVO();
dataStoreVO.setStorageProviderName(params.getProviderName());
dataStoreVO.setHostAddress(params.getHost());
dataStoreVO.setPoolType(params.getType());
dataStoreVO.setPath(params.getPath());
dataStoreVO.setPort(params.getPort());
dataStoreVO.setName(params.getName());
dataStoreVO.setUuid(params.getUuid());
dataStoreVO.setDataCenterId(params.getZoneId());
dataStoreVO.setPodId(params.getPodId());
dataStoreVO.setClusterId(params.getClusterId());
dataStoreVO.setStatus(StoragePoolStatus.Initialized);
dataStoreVO.setUserInfo(params.getUserInfo());
dataStoreVO.setManaged(params.isManaged());
dataStoreVO.setCapacityIops(params.getCapacityIops());
dataStoreVO.setCapacityBytes(params.getCapacityBytes());
dataStoreVO.setUsedBytes(params.getUsedBytes());
dataStoreVO.setHypervisor(params.getHypervisorType());
Map<String, String> details = params.getDetails();
if (params.getType() == StoragePoolType.SMB && details != null) {
String user = details.get("user");
String password = details.get("password");
String domain = details.get("domain");
String updatedPath = params.getPath();
if (user == null || password == null) {
String errMsg = "Missing cifs user and password details. Add them as details parameter.";
s_logger.warn(errMsg);
throw new InvalidParameterValueException(errMsg);
} else {
try {
password = DBEncryptionUtil.encrypt(URLEncoder.encode(password, "UTF-8"));
details.put("password", password);
updatedPath += "?user=" + user + "&password=" + password + "&domain=" + domain;
} catch (UnsupportedEncodingException e) {
throw new CloudRuntimeException("Error while generating the cifs url. " + e.getMessage());
}
}
dataStoreVO.setPath(updatedPath);
}
String tags = params.getTags();
List<String> storageTags = new ArrayList<String>();
if (tags != null) {
String[] tokens = tags.split(",");
for (String tag : tokens) {
tag = tag.trim();
if (tag.length() == 0) {
continue;
}
storageTags.add(tag);
}
}
dataStoreVO = dataStoreDao.persist(dataStoreVO, details, storageTags);
return dataStoreMgr.getDataStore(dataStoreVO.getId(), DataStoreRole.Primary);
}
public DataStore attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) {
StoragePoolHostVO poolHost = storagePoolHostDao.findByPoolHost(store.getId(), scope.getScopeId());
if (poolHost == null) {
poolHost = new StoragePoolHostVO(store.getId(), scope.getScopeId(), existingInfo.getLocalPath());
storagePoolHostDao.persist(poolHost);
}
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
pool.setScope(scope.getScopeType());
pool.setUsedBytes(existingInfo.getCapacityBytes() - existingInfo.getAvailableBytes());
pool.setCapacityBytes(existingInfo.getCapacityBytes());
pool.setStatus(StoragePoolStatus.Up);
this.dataStoreDao.update(pool.getId(), pool);
this.storageMgr.createCapacityEntry(pool, Capacity.CAPACITY_TYPE_LOCAL_STORAGE, pool.getUsedBytes());
return dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
}
public DataStore attachCluster(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
storageMgr.createCapacityEntry(pool.getId());
pool.setScope(ScopeType.CLUSTER);
pool.setStatus(StoragePoolStatus.Up);
this.dataStoreDao.update(pool.getId(), pool);
if(pool.getPoolType() == StoragePoolType.DatastoreCluster && pool.getParent() == 0) {
List<StoragePoolVO> childDatastores = dataStoreDao.listChildStoragePoolsInDatastoreCluster(pool.getId());
for (StoragePoolVO child : childDatastores) {
child.setScope(ScopeType.CLUSTER);
this.dataStoreDao.update(child.getId(), child);
}
}
return dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary);
}
public DataStore attachZone(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
storageMgr.createCapacityEntry(pool.getId());
pool.setScope(ScopeType.ZONE);
pool.setStatus(StoragePoolStatus.Up);
this.dataStoreDao.update(pool.getId(), pool);
return dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary);
}
public DataStore attachZone(DataStore store, HypervisorType hypervisor) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
storageMgr.createCapacityEntry(pool.getId());
pool.setScope(ScopeType.ZONE);
pool.setHypervisor(hypervisor);
pool.setStatus(StoragePoolStatus.Up);
this.dataStoreDao.update(pool.getId(), pool);
if(pool.getPoolType() == StoragePoolType.DatastoreCluster && pool.getParent() == 0) {
List<StoragePoolVO> childDatastores = dataStoreDao.listChildStoragePoolsInDatastoreCluster(pool.getId());
for (StoragePoolVO child : childDatastores) {
child.setScope(ScopeType.ZONE);
this.dataStoreDao.update(child.getId(), child);
}
}
return dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary);
}
public boolean maintain(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
pool.setStatus(StoragePoolStatus.Maintenance);
this.dataStoreDao.update(pool.getId(), pool);
return true;
}
public boolean cancelMaintain(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
pool.setStatus(StoragePoolStatus.Up);
dataStoreDao.update(store.getId(), pool);
return true;
}
public boolean disable(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
pool.setStatus(StoragePoolStatus.Disabled);
this.dataStoreDao.update(pool.getId(), pool);
return true;
}
public boolean enable(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
pool.setStatus(StoragePoolStatus.Up);
dataStoreDao.update(pool.getId(), pool);
return true;
}
protected boolean deletePoolStats(Long poolId) {
CapacityVO capacity1 = _capacityDao.findByHostIdType(poolId, Capacity.CAPACITY_TYPE_STORAGE);
CapacityVO capacity2 = _capacityDao.findByHostIdType(poolId, Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED);
if (capacity1 != null) {
_capacityDao.remove(capacity1.getId());
}
if (capacity2 != null) {
_capacityDao.remove(capacity2.getId());
}
return true;
}
public boolean deletePrimaryDataStore(DataStore store) {
List<StoragePoolHostVO> hostPoolRecords = this.storagePoolHostDao.listByPoolId(store.getId());
StoragePoolVO poolVO = this.dataStoreDao.findById(store.getId());
TransactionLegacy txn = TransactionLegacy.currentTxn();
txn.start();
for (StoragePoolHostVO host : hostPoolRecords) {
storagePoolHostDao.deleteStoragePoolHostDetails(host.getHostId(), host.getPoolId());
}
poolVO.setUuid(null);
this.dataStoreDao.update(poolVO.getId(), poolVO);
dataStoreDao.remove(poolVO.getId());
dataStoreDao.deletePoolTags(poolVO.getId());
annotationDao.removeByEntityType(AnnotationService.EntityType.PRIMARY_STORAGE.name(), poolVO.getUuid());
deletePoolStats(poolVO.getId());
// Delete op_host_capacity entries
this._capacityDao.removeBy(Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED, null, null, null, poolVO.getId());
txn.commit();
s_logger.debug("Storage pool id=" + poolVO.getId() + " is removed successfully");
return true;
}
}