blob: 91dcb4cbfa9e3fddc77f5178cdec8c3458765ace [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.resource;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
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.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.host.HostVO;
import com.cloud.host.Status.Event;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.resource.Discoverer;
import com.cloud.resource.DiscovererBase;
import com.cloud.resource.ServerResource;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.resource.DummySecondaryStorageResource;
import com.cloud.utils.component.ComponentContext;
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.
*/
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 VMTemplateDao _tmpltDao = null;
@Inject
protected VMTemplateZoneDao _vmTemplateZoneDao = null;
@Inject
protected VMTemplateDao _vmTemplateDao = null;
@Inject
protected AgentManager _agentMgr = null;
protected SecondaryStorageDiscoverer() {
}
@Override
public Map<? extends ServerResource, Map<String, String>>
find(long dcId, Long podId, Long clusterId, URI uri, String username, String password, List<String> hostTags) {
if (!uri.getScheme().equalsIgnoreCase("nfs") && !uri.getScheme().equalsIgnoreCase("cifs") && !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("cifs") || 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;
if (_configDao.isPremium()) {
Class<?> impl;
String name = "com.cloud.storage.resource.PremiumSecondaryStorageResource";
try {
impl = Class.forName(name);
final Constructor<?> constructor = impl.getDeclaredConstructor();
constructor.setAccessible(true);
storage = (NfsSecondaryStorageResource)constructor.newInstance();
} catch (final ClassNotFoundException e) {
s_logger.error("Unable to load com.cloud.storage.resource.PremiumSecondaryStorageResource due to ClassNotFoundException");
return null;
} catch (final SecurityException e) {
s_logger.error("Unable to load com.cloud.storage.resource.PremiumSecondaryStorageResource due to SecurityException");
return null;
} catch (final NoSuchMethodException e) {
s_logger.error("Unable to load com.cloud.storage.resource.PremiumSecondaryStorageResource due to NoSuchMethodException");
return null;
} catch (final IllegalArgumentException e) {
s_logger.error("Unable to load com.cloud.storage.resource.PremiumSecondaryStorageResource due to IllegalArgumentException");
return null;
} catch (final InstantiationException e) {
s_logger.error("Unable to load com.cloud.storage.resource.PremiumSecondaryStorageResource due to InstantiationException");
return null;
} catch (final IllegalAccessException e) {
s_logger.error("Unable to load com.cloud.storage.resource.PremiumSecondaryStorageResource due to IllegalAccessException");
return null;
} catch (final InvocationTargetException e) {
s_logger.error("Unable to load com.cloud.storage.resource.PremiumSecondaryStorageResource due to InvocationTargetException");
return null;
}
} else {
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();
storage = ComponentContext.inject(storage);
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);
storage = ComponentContext.inject(storage);
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 boolean matchHypervisor(String hypervisor) {
if (hypervisor.equals("SecondaryStorage")) {
return true;
} else {
return false;
}
}
@Override
public Hypervisor.HypervisorType getHypervisorType() {
return Hypervisor.HypervisorType.None;
}
@Override
public void postDiscovery(List<HostVO> hosts, long msId) {
if (_useServiceVM) {
for (HostVO h : hosts) {
_agentMgr.agentStatusTransitTo(h, Event.AgentDisconnected, msId);
}
}
for (HostVO h : hosts) {
associateTemplatesToZone(h.getId(), h.getDataCenterId());
}
}
private void associateTemplatesToZone(long hostId, long dcId) {
VMTemplateZoneVO tmpltZone;
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);
}
}
}
}
}