cloudstack/server/src/com/cloud/storage/secondary/SecondaryStorageDiscoverer....

286 lines
11 KiB
Java

/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.storage.secondary;
import java.io.File;
import java.net.URI;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.host.HostVO;
import com.cloud.host.Status.Event;
import com.cloud.host.dao.HostDao;
import com.cloud.resource.Discoverer;
import com.cloud.resource.DiscovererBase;
import com.cloud.resource.ServerResource;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.resource.DummySecondaryStorageResource;
import com.cloud.storage.resource.NfsSecondaryStorageResource;
import com.cloud.storage.template.TemplateConstants;
import com.cloud.utils.component.Inject;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NfsUtils;
import com.cloud.utils.script.Script;
/**
* SecondaryStorageDiscoverer is used to discover secondary
* storage servers and make sure everything it can do is
* correct.
*/
@Local(value=Discoverer.class)
public class SecondaryStorageDiscoverer extends DiscovererBase implements Discoverer {
private static final Logger s_logger = Logger.getLogger(SecondaryStorageDiscoverer.class);
long _timeout = 2 * 60 * 1000; // 2 minutes
String _mountParent;
boolean _useServiceVM = false;
Random _random = new Random(System.currentTimeMillis());
@Inject
protected HostDao _hostDao = null;
@Inject
protected VMTemplateDao _tmpltDao = null;
@Inject
protected VMTemplateHostDao _vmTemplateHostDao = null;
@Inject
protected VMTemplateZoneDao _vmTemplateZoneDao = null;
@Inject
protected VMTemplateDao _vmTemplateDao = null;
@Inject
protected ConfigurationDao _configDao = null;
protected SecondaryStorageDiscoverer() {
}
@Override
public Map<? extends ServerResource, Map<String, String>> find(long dcId, Long podId, Long clusterId, URI uri, String username, String password) {
if (!uri.getScheme().equalsIgnoreCase("nfs") && !uri.getScheme().equalsIgnoreCase("file")
&& !uri.getScheme().equalsIgnoreCase("iso") && !uri.getScheme().equalsIgnoreCase("dummy")) {
s_logger.debug("It's not NFS or file or ISO, so not a secondary storage server: " + uri.toString());
return null;
}
if (uri.getScheme().equalsIgnoreCase("nfs") || uri.getScheme().equalsIgnoreCase("iso")) {
return createNfsSecondaryStorageResource(dcId, podId, uri);
} else if (uri.getScheme().equalsIgnoreCase("file")) {
return createLocalSecondaryStorageResource(dcId, podId, uri);
} else if (uri.getScheme().equalsIgnoreCase("dummy")) {
return createDummySecondaryStorageResource(dcId, podId, uri);
} else {
return null;
}
}
protected Map<? extends ServerResource, Map<String, String>> createNfsSecondaryStorageResource(long dcId, Long podId, URI uri) {
if (_useServiceVM) {
return createDummySecondaryStorageResource(dcId, podId, uri);
}
String mountStr = NfsUtils.uri2Mount(uri);
Script script = new Script(true, "mount", _timeout, s_logger);
String mntPoint = null;
File file = null;
do {
mntPoint = _mountParent + File.separator + Integer.toHexString(_random.nextInt(Integer.MAX_VALUE));
file = new File(mntPoint);
} while (file.exists());
if (!file.mkdirs()) {
s_logger.warn("Unable to make directory: " + mntPoint);
return null;
}
script.add(mountStr, mntPoint);
String result = script.execute();
if (result != null && !result.contains("already mounted")) {
s_logger.warn("Unable to mount " + uri.toString() + " due to " + result);
file.delete();
return null;
}
script = new Script(true, "umount", 0, s_logger);
script.add(mntPoint);
script.execute();
file.delete();
Map<NfsSecondaryStorageResource, Map<String, String>> srs = new HashMap<NfsSecondaryStorageResource, Map<String, String>>();
NfsSecondaryStorageResource storage = new NfsSecondaryStorageResource();
Map<String, String> details = new HashMap<String, String>();
details.put("mount.path", mountStr);
details.put("orig.url", uri.toString());
details.put("mount.parent", _mountParent);
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(details);
params.put("zone", Long.toString(dcId));
if (podId != null) {
params.put("pod", podId.toString());
}
params.put("guid", uri.toString());
params.put("secondary.storage.vm", "false");
params.put("max.template.iso.size", _configDao.getValue("max.template.iso.size"));
try {
storage.configure("Storage", params);
} catch (ConfigurationException e) {
s_logger.warn("Unable to configure the storage ", e);
return null;
}
srs.put(storage, details);
return srs;
}
protected Map<? extends ServerResource, Map<String, String>> createLocalSecondaryStorageResource(long dcId, Long podId, URI uri) {
Map<LocalSecondaryStorageResource, Map<String, String>> srs = new HashMap<LocalSecondaryStorageResource, Map<String, String>>();
LocalSecondaryStorageResource storage = new LocalSecondaryStorageResource();
Map<String, String> details = new HashMap<String, String>();
File file = new File(uri);
details.put("mount.path", file.getAbsolutePath());
details.put("orig.url", uri.toString());
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(details);
params.put("zone", Long.toString(dcId));
if (podId != null) {
params.put("pod", podId.toString());
}
params.put("guid", uri.toString());
try {
storage.configure("Storage", params);
} catch (ConfigurationException e) {
s_logger.warn("Unable to configure the storage ", e);
return null;
}
srs.put(storage, details);
return srs;
}
protected Map<ServerResource, Map<String, String>> createDummySecondaryStorageResource(long dcId, Long podId, URI uri) {
Map<ServerResource, Map<String, String>> srs = new HashMap<ServerResource, Map<String, String>>();
DummySecondaryStorageResource storage = new DummySecondaryStorageResource(_useServiceVM);
Map<String, String> details = new HashMap<String, String>();
details.put("mount.path", uri.toString());
details.put("orig.url", uri.toString());
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(details);
params.put("zone", Long.toString(dcId));
if (podId != null) {
params.put("pod", podId.toString());
}
params.put("guid", uri.toString());
try {
storage.configure("Storage", params);
} catch (ConfigurationException e) {
s_logger.warn("Unable to configure the storage ", e);
return null;
}
srs.put(storage, details);
return srs;
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
_mountParent = _params.get("mount.parent");
if (_mountParent == null) {
_mountParent = "/mnt";
}
String useServiceVM = _params.get("secondary.storage.vm");
if ("true".equalsIgnoreCase(useServiceVM)){
_useServiceVM = true;
}
return true;
}
@Override
public void postDiscovery(List<HostVO> hosts, long msId) {
if (_useServiceVM) {
for (HostVO h: hosts) {
_hostDao.disconnect(h, Event.AgentDisconnected, msId);
associateSystemVmTemplate(h.getId(), h.getDataCenterId());
}
}
for (HostVO h: hosts) {
associateTemplatesToZone(h.getId(), h.getDataCenterId());
}
}
protected void associateSystemVmTemplate(long hostId, long dcId) {
VMTemplateVO tmplt = _tmpltDao.findById(TemplateConstants.DEFAULT_SYSTEM_VM_DB_ID);
if (tmplt == null) {
throw new CloudRuntimeException("Cannot find routing template in vm_template table. Check your configuration");
}
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(hostId, TemplateConstants.DEFAULT_SYSTEM_VM_DB_ID);
if (tmpltHost == null) {
VMTemplateHostVO vmTemplateHost = new VMTemplateHostVO(hostId, TemplateConstants.DEFAULT_SYSTEM_VM_DB_ID, new Date(), 100, VMTemplateStorageResourceAssoc.Status.DOWNLOADED, null, null, null, TemplateConstants.DEFAULT_SYSTEM_VM_TEMPLATE_PATH, null);
_vmTemplateHostDao.persist(vmTemplateHost);
}
}
private void associateTemplatesToZone(long hostId, long dcId){
VMTemplateZoneVO tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, TemplateConstants.DEFAULT_SYSTEM_VM_DB_ID);
if (tmpltZone == null) {
VMTemplateZoneVO vmTemplateZone = new VMTemplateZoneVO(dcId, TemplateConstants.DEFAULT_SYSTEM_VM_DB_ID, new Date());
_vmTemplateZoneDao.persist(vmTemplateZone);
}
List<VMTemplateVO> allTemplates = _vmTemplateDao.listAll();
for (VMTemplateVO vt: allTemplates){
if (vt.isCrossZones()) {
tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, vt.getId());
if (tmpltZone == null) {
VMTemplateZoneVO vmTemplateZone = new VMTemplateZoneVO(dcId, vt.getId(), new Date());
_vmTemplateZoneDao.persist(vmTemplateZone);
}
}
}
}
}