mirror of https://github.com/apache/cloudstack.git
286 lines
11 KiB
Java
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|