initial checkin for multiple secondary storage

This commit is contained in:
anthony 2011-05-13 21:19:39 -07:00
parent a84678cca0
commit ba6b2ca670
40 changed files with 1475 additions and 530 deletions

View File

@ -18,22 +18,15 @@
package com.cloud.agent.api;
public class SecStorageSetupCommand extends Command {
private Long dcId;
String [] allowedInternalSites = new String[0];
String copyUserName;
String copyPassword;
private String secUrl;
public SecStorageSetupCommand() {
super();
}
public SecStorageSetupCommand(Long dcId) {
public SecStorageSetupCommand(String secUrl) {
super();
this.dcId = dcId;
}
public Long getDataCenterId() {
return dcId;
this.secUrl = secUrl;
}
@Override
@ -41,28 +34,11 @@ public class SecStorageSetupCommand extends Command {
return true;
}
public String[] getAllowedInternalSites() {
return allowedInternalSites;
}
public void setAllowedInternalSites(String[] allowedInternalSites) {
this.allowedInternalSites = allowedInternalSites;
}
public String getCopyUserName() {
return copyUserName;
}
public void setCopyUserName(String copyUserName) {
this.copyUserName = copyUserName;
}
public String getCopyPassword() {
return copyPassword;
}
public void setCopyPassword(String copyPassword) {
this.copyPassword = copyPassword;
}
public String getSecUrl() {
return secUrl;
}
public void setSecUrl(String secUrl) {
this.secUrl = secUrl;
}
}

View File

@ -0,0 +1,58 @@
/**
* 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.agent.api;
public class SecStorageVMSetupCommand extends Command {
String [] allowedInternalSites = new String[0];
String copyUserName;
String copyPassword;
public SecStorageVMSetupCommand() {
super();
}
@Override
public boolean executeInSequence() {
return true;
}
public String[] getAllowedInternalSites() {
return allowedInternalSites;
}
public void setAllowedInternalSites(String[] allowedInternalSites) {
this.allowedInternalSites = allowedInternalSites;
}
public String getCopyUserName() {
return copyUserName;
}
public void setCopyUserName(String copyUserName) {
this.copyUserName = copyUserName;
}
public String getCopyPassword() {
return copyPassword;
}
public void setCopyPassword(String copyPassword) {
this.copyPassword = copyPassword;
}
}

View File

@ -0,0 +1,33 @@
/**
* 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.agent.api;
import com.cloud.host.Host;
public class StartupSecondaryStorageCommand extends StartupCommand {
public StartupSecondaryStorageCommand() {
super(Host.Type.ConsoleProxy);
setIqn("NoIqn");
}
@Override
public boolean executeInSequence() {
return true;
}
}

View File

@ -64,7 +64,11 @@ public class StartupStorageCommand extends StartupCommand {
return parent;
}
public void setNfsShare(String nfsShare) {
public void setParent(String parent) {
this.parent = parent;
}
public void setNfsShare(String nfsShare) {
this.nfsShare = nfsShare;
}

View File

@ -19,7 +19,7 @@ package com.cloud.agent.api.storage;
import com.cloud.storage.Storage.ImageFormat;
public abstract class AbstractDownloadCommand extends StorageCommand {
public abstract class AbstractDownloadCommand extends ssCommand {
private String url;
private ImageFormat format;
@ -40,7 +40,13 @@ public abstract class AbstractDownloadCommand extends StorageCommand {
}
protected AbstractDownloadCommand(AbstractDownloadCommand that) {
this(that.name, that.url, that.format, that.accountId);
super(that);
assert(that.url != null);
this.url = that.url.replace('\\', '/');
this.format = that.format;
this.accountId = that.accountId;
this.name = that.name;
}
public String getUrl() {

View File

@ -18,16 +18,16 @@
package com.cloud.agent.api.storage;
import com.cloud.agent.api.Command;
public class DeleteTemplateCommand extends Command {
String templatePath;
public class DeleteTemplateCommand extends ssCommand {
private String templatePath;
public DeleteTemplateCommand() {
}
public DeleteTemplateCommand(String templatePath) {
public DeleteTemplateCommand(String secUrl, String templatePath) {
this.setSecUrl(secUrl);
this.templatePath = templatePath;
}
@ -39,5 +39,4 @@ public class DeleteTemplateCommand extends Command {
public String getTemplatePath() {
return templatePath;
}
}

View File

@ -64,23 +64,20 @@ public class DownloadCommand extends AbstractDownloadCommand {
this.maxDownloadSizeInBytes = that.getMaxDownloadSizeInBytes();
}
public DownloadCommand(VirtualMachineTemplate template, Long maxDownloadSizeInBytes) {
public DownloadCommand(String secUrl, VirtualMachineTemplate template, Long maxDownloadSizeInBytes) {
super(template.getUniqueName(), template.getUrl(), template.getFormat(), template.getAccountId());
this.hvm = template.isRequiresHvm();
this.checksum = template.getChecksum();
this.id = template.getId();
this.description = template.getDisplayText();
this.setSecUrl(secUrl);
this.maxDownloadSizeInBytes = maxDownloadSizeInBytes;
}
public DownloadCommand(String url, String name, ImageFormat format, boolean isHvm, Long accountId, Long templateId, String descr, String cksum, String user, String passwd, Long maxDownloadSizeInBytes) {
super(name, url, format, accountId);
this.setHvm(isHvm);
this.description = descr;
this.checksum = cksum;
this.id = templateId;
public DownloadCommand(String secUrl, String url, VirtualMachineTemplate template, String user, String passwd, Long maxDownloadSizeInBytes) {
this(secUrl, template, maxDownloadSizeInBytes);
this.setUrl(url);
auth = new PasswordAuth(user, passwd);
this.maxDownloadSizeInBytes = maxDownloadSizeInBytes;
}
public long getId() {
@ -103,7 +100,7 @@ public class DownloadCommand extends AbstractDownloadCommand {
return checksum;
}
public void setDescription(String description) {
public void setDescription(String description) {
this.description = description;
}

View File

@ -0,0 +1,55 @@
/**
* 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.agent.api.storage;
import java.util.Map;
import com.cloud.agent.api.Answer;
import com.cloud.storage.template.TemplateInfo;
public class ListTemplateAnswer extends Answer {
private String secUrl;
private Map<String, TemplateInfo> templateInfos;
public ListTemplateAnswer() {
}
public ListTemplateAnswer(String secUrl, Map<String, TemplateInfo> templateInfos) {
super(null, true, "success");
this.setSecUrl(secUrl);
this.templateInfos = templateInfos;
}
public Map<String, TemplateInfo> getTemplateInfo() {
return templateInfos;
}
public void setTemplateInfo(Map<String, TemplateInfo> templateInfos) {
this.templateInfos = templateInfos;
}
public void setSecUrl(String secUrl) {
this.secUrl = secUrl;
}
public String getSecUrl() {
return secUrl;
}
}

View File

@ -0,0 +1,43 @@
/**
* 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.agent.api.storage;
public class ListTemplateCommand extends StorageCommand {
private String secUrl;
public ListTemplateCommand() {
}
public ListTemplateCommand(String secUrl) {
this.secUrl = secUrl;
}
@Override
public boolean executeInSequence() {
return false;
}
public String getSecUrl() {
return secUrl;
}
public void setSecUrl(String secUrl) {
this.secUrl = secUrl;
}
}

View File

@ -0,0 +1,50 @@
/**
* 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.agent.api.storage;
import com.cloud.agent.api.Command;
public abstract class ssCommand extends Command {
private String secUrl;
public ssCommand() {
}
protected ssCommand(ssCommand that) {
this.secUrl = that.secUrl;
}
public ssCommand(String secUrl) {
this.secUrl = secUrl;
}
@Override
public boolean executeInSequence() {
return true;
}
public String getSecUrl() {
return secUrl;
}
public void setSecUrl(String secUrl) {
this.secUrl = secUrl;
}
}

View File

@ -36,8 +36,10 @@ public interface Host {
ExternalLoadBalancer(false),
PxeServer(false),
TrafficMonitor(false),
ExternalDhcp(false);
ExternalDhcp(false),
SecondaryStorageVM(true),
LocalSecondaryStorage(false);
boolean _virtual;
private Type(boolean virtual) {
_virtual = virtual;

View File

@ -110,5 +110,5 @@ public class Storage {
}
}
public static enum StorageResourceType {STORAGE_POOL, STORAGE_HOST, SECONDARY_STORAGE}
public static enum StorageResourceType {STORAGE_POOL, STORAGE_HOST, SECONDARY_STORAGE, LOCAL_SECONDARY_STORAGE}
}

View File

@ -91,6 +91,9 @@ public class SnapshotVO implements Snapshot {
@Column(name="swift_id")
long swiftId;
@Column(name="sechost_id")
Long secHostId;
@Column(name="swift_name")
String swiftName;
@ -121,7 +124,8 @@ public class SnapshotVO implements Snapshot {
this.status = Status.Creating;
this.prevSnapshotId = 0;
this.hypervisorType = hypervisorType;
this.version = "2.2";
this.version = "2.2";
this.secHostId = null;
}
@ -190,6 +194,14 @@ public class SnapshotVO implements Snapshot {
this.swiftId = swiftId;
}
public Long getSecHostId() {
return secHostId;
}
public void setSecHostId(Long secHostId) {
this.secHostId = secHostId;
}
public String getSwiftName() {
return swiftName;
}

View File

@ -32,13 +32,14 @@ import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingStorageCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.SecStorageSetupCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.storage.ssCommand;
import com.cloud.agent.api.storage.DownloadCommand;
import com.cloud.agent.api.storage.DownloadProgressCommand;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
import com.cloud.resource.ServerResourceBase;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
@ -48,7 +49,7 @@ import com.cloud.storage.template.DownloadManagerImpl;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.utils.component.ComponentLocator;
public class LocalSecondaryStorageResource extends ServerResourceBase implements ServerResource {
public class LocalSecondaryStorageResource extends ServerResourceBase implements SecondaryStorageResource {
private static final Logger s_logger = Logger.getLogger(LocalSecondaryStorageResource.class);
int _timeout;
@ -70,11 +71,13 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof DownloadProgressCommand) {
return _dlMgr.handleDownloadCommand((DownloadProgressCommand)cmd);
return _dlMgr.handleDownloadCommand(this, (DownloadProgressCommand)cmd);
} else if (cmd instanceof DownloadCommand) {
return _dlMgr.handleDownloadCommand((DownloadCommand)cmd);
return _dlMgr.handleDownloadCommand(this, (DownloadCommand)cmd);
} else if (cmd instanceof CheckHealthCommand) {
return new CheckHealthAnswer((CheckHealthCommand)cmd, true);
} else if (cmd instanceof SecStorageSetupCommand){
return new Answer(cmd, true, "success");
} else if (cmd instanceof ReadyCommand) {
return new ReadyAnswer((ReadyCommand)cmd);
} else {
@ -84,7 +87,7 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements
@Override
public Type getType() {
return Host.Type.SecondaryStorage;
return Host.Type.LocalSecondaryStorage;
}
@Override
@ -92,6 +95,12 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements
return new PingStorageCommand(Host.Type.Storage, id, new HashMap<String, Boolean>());
}
@Override
public String getRootDir(ssCommand cmd){
return null;
}
@Override
@SuppressWarnings("unchecked")
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
@ -159,8 +168,8 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements
@Override
public StartupCommand[] initialize() {
final StartupStorageCommand cmd = new StartupStorageCommand(_parent, StoragePoolType.Filesystem, 1024l*1024l*1024l*1024l, _dlMgr.gatherTemplateInfo());
cmd.setResourceType(Storage.StorageResourceType.SECONDARY_STORAGE);
final StartupStorageCommand cmd = new StartupStorageCommand(_parent, StoragePoolType.Filesystem, 1024l*1024l*1024l*1024l, _dlMgr.gatherTemplateInfo(_parent));
cmd.setResourceType(Storage.StorageResourceType.LOCAL_SECONDARY_STORAGE);
cmd.setIqn("local://");
fillNetworkInformation(cmd);
cmd.setDataCenter(_dc);
@ -168,11 +177,7 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements
cmd.setGuid(_guid);
cmd.setName(_guid);
cmd.setVersion(LocalSecondaryStorageResource.class.getPackage().getImplementationVersion());
/* gather TemplateInfo in second storage */
final Map<String, TemplateInfo> tInfo = _dlMgr.gatherTemplateInfo();
cmd.setTemplateInfo(tInfo);
return new StartupCommand [] {cmd};
}

View File

@ -26,11 +26,13 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import javax.naming.ConfigurationException;
@ -48,28 +50,30 @@ import com.cloud.agent.api.PingStorageCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig;
import com.cloud.agent.api.SecStorageSetupCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig;
import com.cloud.agent.api.SecStorageVMSetupCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand;
import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand;
import com.cloud.agent.api.storage.DeleteTemplateCommand;
import com.cloud.agent.api.storage.ListTemplateAnswer;
import com.cloud.agent.api.storage.ListTemplateCommand;
import com.cloud.agent.api.storage.ssCommand;
import com.cloud.agent.api.storage.DownloadCommand;
import com.cloud.agent.api.storage.DownloadProgressCommand;
import com.cloud.agent.api.storage.UploadCommand;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
import com.cloud.resource.ServerResourceBase;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.template.DownloadManager;
import com.cloud.storage.template.DownloadManagerImpl;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.UploadManager;
import com.cloud.storage.template.UploadManagerImpl;
import com.cloud.storage.template.DownloadManagerImpl.ZfsPathParser;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.exception.CloudRuntimeException;
@ -78,18 +82,14 @@ import com.cloud.utils.net.NfsUtils;
import com.cloud.utils.script.Script;
import com.cloud.vm.SecondaryStorageVm;
public class NfsSecondaryStorageResource extends ServerResourceBase implements ServerResource {
public class NfsSecondaryStorageResource extends ServerResourceBase implements SecondaryStorageResource {
private static final Logger s_logger = Logger.getLogger(NfsSecondaryStorageResource.class);
int _timeout;
String _instance;
String _parent;
String _instance;
String _dc;
String _pod;
String _guid;
String _nfsPath;
String _mountParent;
String _role;
Map<String, Object> _params;
StorageLayer _storage;
@ -111,24 +111,16 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
@Override
public void disconnected() {
if (_parent != null && !_inSystemVM) {
Script script = new Script(!_inSystemVM, "umount", _timeout, s_logger);
script.add(_parent);
script.execute();
File file = new File(_parent);
file.delete();
}
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof DownloadProgressCommand) {
return _dlMgr.handleDownloadCommand((DownloadProgressCommand)cmd);
return _dlMgr.handleDownloadCommand(this, (DownloadProgressCommand)cmd);
} else if (cmd instanceof DownloadCommand) {
return _dlMgr.handleDownloadCommand((DownloadCommand)cmd);
return _dlMgr.handleDownloadCommand(this, (DownloadCommand)cmd);
} else if (cmd instanceof UploadCommand) {
return _upldMgr.handleUploadCommand((UploadCommand)cmd);
return _upldMgr.handleUploadCommand(this, (UploadCommand)cmd);
} else if (cmd instanceof CreateEntityDownloadURLCommand){
return _upldMgr.handleCreateEntityURLCommand((CreateEntityDownloadURLCommand)cmd);
} else if(cmd instanceof DeleteEntityDownloadURLCommand){
@ -143,10 +135,14 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return new ReadyAnswer((ReadyCommand)cmd);
} else if (cmd instanceof SecStorageFirewallCfgCommand){
return execute((SecStorageFirewallCfgCommand)cmd);
} else if (cmd instanceof SecStorageVMSetupCommand){
return execute((SecStorageVMSetupCommand)cmd);
} else if (cmd instanceof SecStorageSetupCommand){
return execute((SecStorageSetupCommand)cmd);
return execute((SecStorageSetupCommand)cmd);
} else if (cmd instanceof ComputeChecksumCommand){
return execute((ComputeChecksumCommand)cmd);
} else if (cmd instanceof ListTemplateCommand){
return execute((ListTemplateCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
@ -210,7 +206,40 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return new Answer(cmd, true, checksum);
}
private Answer execute(SecStorageSetupCommand cmd) {
if (!_inSystemVM){
return new Answer(cmd, true, null);
}
String secUrl = cmd.getSecUrl();
try {
URI uri = new URI(secUrl);
String nfsHost = uri.getHost();
InetAddress nfsHostAddr = InetAddress.getByName(nfsHost);
String nfsHostIp = nfsHostAddr.getHostAddress();
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, nfsHostIp);
return new Answer(cmd, true, "success");
} catch (Exception e) {
String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString();
s_logger.error(msg);
return new Answer(cmd, false, msg);
}
}
private Answer execute(ListTemplateCommand cmd) {
if (!_inSystemVM){
return new Answer(cmd, true, null);
}
String root = getRootDir(cmd.getSecUrl());
Map<String, TemplateInfo> templateInfos = _dlMgr.gatherTemplateInfo(root);
return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos);
}
private Answer execute(SecStorageVMSetupCommand cmd) {
if (!_inSystemVM){
return new Answer(cmd, true, null);
}
@ -274,8 +303,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
}
protected GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) {
final long usedSize = getUsedSize();
final long totalSize = getTotalSize();
String rootDir = getRootDir(cmd.getLocalPath());
final long usedSize = getUsedSize(rootDir);
final long totalSize = getTotalSize(rootDir);
if (usedSize == -1 || totalSize == -1) {
return new GetStorageStatsAnswer(cmd, "Unable to get storage stats");
} else {
@ -285,7 +315,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
protected Answer execute(final DeleteTemplateCommand cmd) {
String relativeTemplatePath = cmd.getTemplatePath();
String parent = _parent;
String parent = getRootDir(cmd);
if (relativeTemplatePath.startsWith(File.separator)) {
relativeTemplatePath = relativeTemplatePath.substring(1);
@ -331,12 +361,39 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return new Answer(cmd, true, null);
}
protected long getUsedSize() {
return _storage.getUsedSpace(_parent);
public String getRootDir(String secUrl) {
try {
URI uri = new URI(secUrl);
String nfsHost = uri.getHost();
InetAddress nfsHostAddr = InetAddress.getByName(nfsHost);
String nfsHostIp = nfsHostAddr.getHostAddress();
String nfsPath = nfsHostIp + ":" + uri.getPath();
String dir = UUID.nameUUIDFromBytes(nfsPath.getBytes()).toString();
String root = "/mnt/SecStorage/" + dir;
mount(root, nfsPath);
return root;
} catch (Exception e) {
String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString();
s_logger.error(msg, e);
throw new CloudRuntimeException(msg);
}
}
protected long getTotalSize() {
return _storage.getTotalSpace(_parent);
@Override
public String getRootDir(ssCommand cmd){
return getRootDir(cmd.getSecUrl());
}
protected long getUsedSize(String rootDir) {
return _storage.getUsedSpace(rootDir);
}
protected long getTotalSize(String rootDir) {
return _storage.getTotalSpace(rootDir);
}
protected long convertFilesystemSize(final String size) {
@ -440,22 +497,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
_pod = (String)params.get("pod");
_instance = (String)params.get("instance");
_mountParent = (String)params.get("mount.parent");
if (_mountParent == null) {
_mountParent = File.separator + "mnt";
}
if (_instance != null) {
_mountParent = _mountParent + File.separator + _instance;
}
_nfsPath = (String)params.get("mount.path");
if (_nfsPath == null) {
throw new ConfigurationException("Unable to find mount.path");
}
String inSystemVM = (String)params.get("secondary.storage.vm");
if (inSystemVM == null || "true".equalsIgnoreCase(inSystemVM)) {
@ -473,19 +515,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
}
String mgmtHost = (String)params.get("host");
String nfsHost = NfsUtils.getHostPart(_nfsPath);
if (nfsHost == null) {
s_logger.error("Invalid or corrupt nfs url " + _nfsPath);
throw new CloudRuntimeException("Unable to determine host part of nfs path");
}
try {
InetAddress nfsHostAddr = InetAddress.getByName(nfsHost);
nfsHost = nfsHostAddr.getHostAddress();
} catch (UnknownHostException uhe) {
s_logger.error("Unable to resolve nfs host " + nfsHost);
throw new CloudRuntimeException("Unable to resolve nfs host to an ip address " + nfsHost);
}
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, nfsHost);
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, mgmtHost);
if (internalDns2 != null) {
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, internalDns2);
@ -503,16 +533,8 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
_params.put("install.numthreads", "50");
_params.put("secondary.storage.vm", "true");
}
_parent = mount(_nfsPath, _mountParent);
if (_parent == null) {
throw new ConfigurationException("Unable to create mount point");
}
s_logger.info("Mount point established at " + _parent);
try {
_params.put("template.parent", _parent);
_params.put(StorageLayer.InstanceConfigKey, _storage);
_dlMgr = new DownloadManagerImpl();
_dlMgr.configure("DownloadManager", _params);
@ -615,67 +637,58 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
return result;
}
protected String mount(String path, String parent) {
String mountPoint = null;
for (int i = 0; i < 10; i++) {
String mntPt = parent + File.separator + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE));
File file = new File(mntPt);
if (!file.exists()) {
if (_storage.mkdir(mntPt)) {
mountPoint = mntPt;
break;
}
protected String mount(String root, String nfsPath) {
File file = new File(root);
if (!file.exists()) {
if (!_storage.mkdir(root)) {
s_logger.debug("create mount point: " + root);
} else {
s_logger.debug("Unable to create mount point: " + root);
return null;
}
s_logger.debug("Unable to create mount: " + mntPt);
}
if (mountPoint == null) {
s_logger.warn("Unable to create a mount point");
return null;
}
}
Script script = null;
String result = null;
script = new Script(!_inSystemVM, "umount", _timeout, s_logger);
script.add(path);
result = script.execute();
if( _parent != null ) {
script = new Script("rmdir", _timeout, s_logger);
script.add(_parent);
result = script.execute();
script = new Script(!_inSystemVM, "mount", _timeout, s_logger);
List<String> res = new ArrayList<String>();
ZfsPathParser parser = new ZfsPathParser(root);
script.execute(parser);
res.addAll(parser.getPaths());
for( String s : res ) {
if ( s.contains(root)) {
return root;
}
}
Script command = new Script(!_inSystemVM, "mount", _timeout, s_logger);
command.add("-t", "nfs");
if (_inSystemVM) {
//Fedora Core 12 errors out with any -o option executed from java
command.add("-o", "soft,timeo=133,retrans=2147483647,tcp,acdirmax=0,acdirmin=0");
}
command.add(path);
command.add(mountPoint);
command.add(nfsPath);
command.add(root);
result = command.execute();
if (result != null) {
s_logger.warn("Unable to mount " + path + " due to " + result);
File file = new File(mountPoint);
s_logger.warn("Unable to mount " + nfsPath + " due to " + result);
file = new File(root);
if (file.exists())
file.delete();
return null;
}
// XXX: Adding the check for creation of snapshots dir here. Might have to move it somewhere more logical later.
if (!checkForSnapshotsDir(mountPoint)) {
if (!checkForSnapshotsDir(root)) {
return null;
}
// Create the volumes dir
if (!checkForVolumesDir(mountPoint)) {
if (!checkForVolumesDir(root)) {
return null;
}
return mountPoint;
return root;
}
@Override
@ -690,62 +703,12 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
@Override
public StartupCommand[] initialize() {
/*disconnected();
_parent = mount(_nfsPath, _mountParent);
if( _parent == null ) {
s_logger.warn("Unable to mount the nfs server");
return null;
}
try {
_params.put("template.parent", _parent);
_params.put(StorageLayer.InstanceConfigKey, _storage);
_dlMgr = new DownloadManagerImpl();
_dlMgr.configure("DownloadManager", _params);
} catch (ConfigurationException e) {
s_logger.warn("Caught problem while configuring folers", e);
return null;
}*/
final StartupStorageCommand cmd = new StartupStorageCommand(_parent, StoragePoolType.NetworkFilesystem, getTotalSize(), new HashMap<String, TemplateInfo>());
cmd.setHostType(getType());
cmd.setResourceType(Storage.StorageResourceType.SECONDARY_STORAGE);
cmd.setIqn(null);
final StartupSecondaryStorageCommand cmd = new StartupSecondaryStorageCommand();
fillNetworkInformation(cmd);
cmd.setDataCenter(_dc);
cmd.setPod(_pod);
cmd.setGuid(_guid);
cmd.setName(_guid);
cmd.setVersion(NfsSecondaryStorageResource.class.getPackage().getImplementationVersion());
/* gather TemplateInfo in second storage */
Map<String, TemplateInfo> tInfo = new HashMap<String, TemplateInfo>();
if(SecondaryStorageVm.Role.templateProcessor.toString().equals(_role))
tInfo = _dlMgr.gatherTemplateInfo();
cmd.setTemplateInfo(tInfo);
cmd.getHostDetails().put("mount.parent", _mountParent);
cmd.getHostDetails().put("mount.path", _nfsPath);
String tok[] = _nfsPath.split(":");
cmd.setNfsShare("nfs://" + tok[0] + tok[1]);
if (cmd.getHostDetails().get("orig.url") == null) {
if (tok.length != 2) {
throw new CloudRuntimeException("Not valid NFS path" + _nfsPath);
}
String nfsUrl = "nfs://" + tok[0] + tok[1];
cmd.getHostDetails().put("orig.url", nfsUrl);
}
InetAddress addr;
try {
addr = InetAddress.getByName(tok[0]);
cmd.setPrivateIpAddress(addr.getHostAddress());
} catch (UnknownHostException e) {
cmd.setPrivateIpAddress(tok[0]);
}
return new StartupCommand [] {cmd};
if(_publicIp != null)
cmd.setPublicIpAddress(_publicIp);
return new StartupCommand[] {cmd};
}
protected boolean checkForSnapshotsDir(String mountPoint) {

View File

@ -0,0 +1,30 @@
/**
* 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.resource;
import com.cloud.agent.api.storage.ssCommand;
import com.cloud.resource.ServerResource;
/**
*
* SecondaryStorageServerResource is a generic container to execute commands sent
* to the agent.
*/
public interface SecondaryStorageResource extends ServerResource {
public String getRootDir(ssCommand cmd);
}

View File

@ -24,6 +24,7 @@ import com.cloud.agent.api.storage.DownloadAnswer;
import com.cloud.agent.api.storage.DownloadCommand;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.resource.SecondaryStorageResource;
import com.cloud.utils.component.Manager;
/**
@ -90,20 +91,12 @@ public interface DownloadManager extends Manager {
* @param cmd cmd from server
* @return answer representing status of download.
*/
public DownloadAnswer handleDownloadCommand(DownloadCommand cmd);
public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, DownloadCommand cmd);
/**
* List the paths of the public templates successfully installed in the public templates location
* @return
*/
public List<String> listPublicTemplates();
/**
/**
* @return list of template info for installed templates
*/
public Map<String, TemplateInfo> gatherTemplateInfo();
public String getPublicTemplateRepo();
public Map<String, TemplateInfo> gatherTemplateInfo(String templateDir);
}

View File

@ -47,6 +47,7 @@ import com.cloud.exception.InternalErrorException;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.resource.SecondaryStorageResource;
import com.cloud.storage.template.Processor.FormatInfo;
import com.cloud.storage.template.TemplateDownloader.DownloadCompleteCallback;
import com.cloud.storage.template.TemplateDownloader.Status;
@ -125,14 +126,6 @@ public class DownloadManagerImpl implements DownloadManager {
return checksum;
}
public DownloadJob(TemplateDownloader td, String jobId, DownloadCommand cmd) {
this.td = td;
this.jobId = jobId;
this.tmpltName = cmd.getName();
this.format = cmd.getFormat();
this.hvm = cmd.isHvm();
}
public TemplateDownloader getTemplateDownloader() {
return td;
}
@ -205,8 +198,7 @@ public class DownloadManagerImpl implements DownloadManager {
}
public static final Logger s_logger = Logger.getLogger(DownloadManagerImpl.class);
private String parentDir;
private String publicTemplateRepo;
private String _templateDir;
private String createTmpltScr;
private Adapters<Processor> processors;
@ -284,7 +276,7 @@ public class DownloadManagerImpl implements DownloadManager {
_storage.mkdirs(templatePath);
// once template path is set, remove the parent dir so that the template is installed with a relative path
String finalTemplatePath = templatePath.substring(parentDir.length());
String finalTemplatePath = _templateDir + File.separator + dnld.getAccountId() + File.separator + dnld.getId() + File.separator;
dnld.setTmpltPath(finalTemplatePath);
int imgSizeGigs = (int) Math.ceil(_storage.getSize(td.getDownloadLocalPath()) * 1.0d / (1024 * 1024 * 1024));
@ -438,11 +430,6 @@ public class DownloadManagerImpl implements DownloadManager {
}
}
@Override
public String getPublicTemplateRepo() {
return publicTemplateRepo;
}
@Override
public String getDownloadError(String jobId) {
DownloadJob dj = jobs.get(jobId);
@ -515,9 +502,9 @@ public class DownloadManagerImpl implements DownloadManager {
}
@Override
public DownloadAnswer handleDownloadCommand(DownloadCommand cmd) {
public DownloadAnswer handleDownloadCommand(SecondaryStorageResource resource, DownloadCommand cmd) {
if (cmd instanceof DownloadProgressCommand) {
return handleDownloadProgressCmd((DownloadProgressCommand) cmd);
return handleDownloadProgressCmd( resource, (DownloadProgressCommand) cmd);
}
if (cmd.getUrl() == null) {
@ -527,9 +514,9 @@ public class DownloadManagerImpl implements DownloadManager {
if (cmd.getName() == null) {
return new DownloadAnswer("Invalid Name", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR);
}
String installPathPrefix = null;
installPathPrefix = publicTemplateRepo;
installPathPrefix = resource.getRootDir(cmd) + File.separator + _templateDir;
String user = null;
String password = null;
@ -556,7 +543,7 @@ public class DownloadManagerImpl implements DownloadManager {
}
}
private DownloadAnswer handleDownloadProgressCmd(DownloadProgressCommand cmd) {
private DownloadAnswer handleDownloadProgressCmd(SecondaryStorageResource resource, DownloadProgressCommand cmd) {
String jobId = cmd.getJobId();
DownloadAnswer answer;
DownloadJob dj = null;
@ -565,7 +552,7 @@ public class DownloadManagerImpl implements DownloadManager {
if (dj == null) {
if (cmd.getRequest() == RequestType.GET_OR_RESTART) {
DownloadCommand dcmd = new DownloadCommand(cmd);
return handleDownloadCommand(dcmd);
return handleDownloadCommand(resource, dcmd);
} else {
return new DownloadAnswer("Cannot find job", VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR.UNKNOWN);
}
@ -614,11 +601,6 @@ public class DownloadManagerImpl implements DownloadManager {
}
@Override
public List<String> listPublicTemplates() {
return listTemplates(publicTemplateRepo);
}
private List<String> listTemplates(String rootdir) {
List<String> result = new ArrayList<String>();
Script script = new Script(listTmpltScr, s_logger);
@ -631,9 +613,10 @@ public class DownloadManagerImpl implements DownloadManager {
}
@Override
public Map<String, TemplateInfo> gatherTemplateInfo() {
public Map<String, TemplateInfo> gatherTemplateInfo(String rootDir) {
Map<String, TemplateInfo> result = new HashMap<String, TemplateInfo>();
List<String> publicTmplts = listPublicTemplates();
String templateDir = rootDir + File.separator + _templateDir;
List<String> publicTmplts = listTemplates(templateDir);
for (String tmplt : publicTmplts) {
String path = tmplt.substring(0, tmplt.lastIndexOf(File.separator));
TemplateLocation loc = new TemplateLocation(_storage, path);
@ -641,14 +624,14 @@ public class DownloadManagerImpl implements DownloadManager {
if (!loc.load()) {
s_logger.warn("Post download installation was not completed for " + path);
loc.purge();
_storage.cleanup(path, publicTemplateRepo);
_storage.cleanup(path, templateDir);
continue;
}
} catch (IOException e) {
s_logger.warn("Unable to load template location " + path, e);
loc.purge();
try {
_storage.cleanup(path, publicTemplateRepo);
_storage.cleanup(path, templateDir);
} catch (IOException e1) {
s_logger.warn("Unable to cleanup " + path, e1);
}
@ -747,7 +730,6 @@ public class DownloadManagerImpl implements DownloadManager {
_sslCopy = Boolean.parseBoolean(useSsl);
}
configureFolders(name, params);
String inSystemVM = (String)params.get("secondary.storage.vm");
if (inSystemVM != null && "true".equalsIgnoreCase(inSystemVM)) {
s_logger.info("DownloadManager: starting additional services since we are inside system vm");
@ -797,6 +779,12 @@ public class DownloadManagerImpl implements DownloadManager {
processors.add(new ComponentInfo<Adapter>("VMDK Processor", VmdkProcessor.class, processor));
_processors = new Adapters<Processor>("processors", processors);
_templateDir = (String) params.get("public.templates.root.dir");
if (_templateDir == null) {
_templateDir = TemplateConstants.DEFAULT_TMPLT_ROOT_DIR;
}
_templateDir += File.separator + TemplateConstants.DEFAULT_TMPLT_FIRST_LEVEL_DIR;
// Add more processors here.
threadPool = Executors.newFixedThreadPool(numInstallThreads);
return true;
@ -816,34 +804,6 @@ public class DownloadManagerImpl implements DownloadManager {
}
}
protected void configureFolders(String name, Map<String, Object> params) throws ConfigurationException {
parentDir = (String) params.get("template.parent");
if (parentDir == null) {
throw new ConfigurationException("Unable to find the parent root for the templates");
}
String value = (String) params.get("public.templates.root.dir");
if (value == null) {
value = TemplateConstants.DEFAULT_TMPLT_ROOT_DIR;
}
if (value.startsWith(File.separator)) {
publicTemplateRepo = value;
} else {
publicTemplateRepo = parentDir + File.separator + value;
}
if (!publicTemplateRepo.endsWith(File.separator)) {
publicTemplateRepo += File.separator;
}
publicTemplateRepo += TemplateConstants.DEFAULT_TMPLT_FIRST_LEVEL_DIR;
if (!_storage.mkdirs(publicTemplateRepo)) {
throw new ConfigurationException("Unable to create public templates directory");
}
}
@Override
public String getName() {
return _name;
@ -898,14 +858,5 @@ public class DownloadManagerImpl implements DownloadManager {
s_logger.warn("Error in creating directory =" + result );
return;
}
command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("ln -sf " + publicTemplateRepo + " /var/www/html/copy/template");
result = command.execute();
if (result != null) {
s_logger.warn("Error in linking err=" + result );
return;
}
}
}

View File

@ -26,6 +26,7 @@ import com.cloud.agent.api.storage.UploadAnswer;
import com.cloud.agent.api.storage.UploadCommand;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Upload.Status;
import com.cloud.storage.resource.SecondaryStorageResource;
import com.cloud.utils.component.Manager;
public interface UploadManager extends Manager {
@ -70,7 +71,7 @@ public interface UploadManager extends Manager {
* @param cmd cmd from server
* @return answer representing status of upload.
*/
public UploadAnswer handleUploadCommand(UploadCommand cmd);
public UploadAnswer handleUploadCommand(SecondaryStorageResource resource, UploadCommand cmd);
public String getPublicTemplateRepo();

View File

@ -44,6 +44,7 @@ import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.Upload;
import com.cloud.storage.UploadVO;
import com.cloud.storage.resource.SecondaryStorageResource;
import com.cloud.storage.template.TemplateUploader.Status;
import com.cloud.storage.template.TemplateUploader.UploadCompleteCallback;
import com.cloud.utils.NumbersUtil;
@ -319,7 +320,7 @@ public class UploadManagerImpl implements UploadManager {
}
@Override
public UploadAnswer handleUploadCommand(UploadCommand cmd) {
public UploadAnswer handleUploadCommand(SecondaryStorageResource resource, UploadCommand cmd) {
s_logger.warn("Handling the upload " +cmd.getInstallPath() + " " + cmd.getId());
if (cmd instanceof UploadProgressCommand) {
return handleUploadProgressCmd((UploadProgressCommand) cmd);

View File

@ -264,4 +264,7 @@ public interface AgentManager extends Manager {
boolean updateHostPassword(UpdateHostPasswordCmd upasscmd);
long sendToSecStorage(HostVO ssHost, Command cmd, Listener listener);
Answer sendToSecStorage(HostVO ssHost, Command cmd);
}

View File

@ -65,6 +65,7 @@ import com.cloud.agent.api.StartupExternalLoadBalancerCommand;
import com.cloud.agent.api.StartupProxyCommand;
import com.cloud.agent.api.StartupPxeServerCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.StartupTrafficMonitorCommand;
import com.cloud.agent.api.UnsupportedAnswer;
@ -501,6 +502,549 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
return attache;
}
@Override
public List<? extends Cluster> discoverCluster(AddClusterCmd cmd) throws IllegalArgumentException, DiscoveryException {
Long dcId = cmd.getZoneId();
Long podId = cmd.getPodId();
String clusterName = cmd.getClusterName();
String url = cmd.getUrl();
String username = cmd.getUsername();
String password = cmd.getPassword();
if(url != null) {
url = URLDecoder.decode(url);
}
URI uri = null;
// Check if the zone exists in the system
DataCenterVO zone = _dcDao.findById(dcId);
if (zone == null) {
throw new InvalidParameterValueException("Can't find zone by id " + dcId);
}
Account account = UserContext.current().getCaller();
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) {
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + dcId);
}
// Check if the pod exists in the system
if (podId != null) {
if (_podDao.findById(podId) == null) {
throw new InvalidParameterValueException("Can't find pod by id " + podId);
}
// check if pod belongs to the zone
HostPodVO pod = _podDao.findById(podId);
if (!Long.valueOf(pod.getDataCenterId()).equals(dcId)) {
throw new InvalidParameterValueException("Pod " + podId + " doesn't belong to the zone " + dcId);
}
}
// Verify cluster information and create a new cluster if needed
if (clusterName == null || clusterName.isEmpty()) {
throw new InvalidParameterValueException("Please specify cluster name");
}
if (cmd.getHypervisor() == null || cmd.getHypervisor().isEmpty()) {
throw new InvalidParameterValueException("Please specify a hypervisor");
}
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.getType(cmd.getHypervisor());
if (hypervisorType == null) {
s_logger.error("Unable to resolve " + cmd.getHypervisor() + " to a valid supported hypervisor type");
throw new InvalidParameterValueException("Unable to resolve " + cmd.getHypervisor() + " to a supported ");
}
Cluster.ClusterType clusterType = null;
if (cmd.getClusterType() != null && !cmd.getClusterType().isEmpty()) {
clusterType = Cluster.ClusterType.valueOf(cmd.getClusterType());
}
if (clusterType == null) {
clusterType = Cluster.ClusterType.CloudManaged;
}
Grouping.AllocationState allocationState = null;
if (cmd.getAllocationState() != null && !cmd.getAllocationState().isEmpty()) {
try {
allocationState = Grouping.AllocationState.valueOf(cmd.getAllocationState());
} catch (IllegalArgumentException ex) {
throw new InvalidParameterValueException("Unable to resolve Allocation State '" + cmd.getAllocationState() + "' to a supported state");
}
}
if (allocationState == null) {
allocationState = Grouping.AllocationState.Enabled;
}
Discoverer discoverer = getMatchingDiscover(hypervisorType);
if (discoverer == null) {
throw new InvalidParameterValueException("Could not find corresponding resource manager for " + cmd.getHypervisor());
}
List<ClusterVO> result = new ArrayList<ClusterVO>();
long clusterId = 0;
ClusterVO cluster = new ClusterVO(dcId, podId, clusterName);
cluster.setHypervisorType(cmd.getHypervisor());
cluster.setClusterType(clusterType);
cluster.setAllocationState(allocationState);
try {
cluster = _clusterDao.persist(cluster);
} catch (Exception e) {
// no longer tolerate exception during the cluster creation phase
throw new CloudRuntimeException("Unable to create cluster " + clusterName + " in pod " + podId + " and data center " + dcId, e);
}
clusterId = cluster.getId();
result.add(cluster);
if (clusterType == Cluster.ClusterType.CloudManaged) {
return result;
}
// save cluster details for later cluster/host cross-checking
Map<String, String> details = new HashMap<String, String>();
details.put("url", url);
details.put("username", username);
details.put("password", password);
_clusterDetailsDao.persist(cluster.getId(), details);
boolean success = false;
try {
try {
uri = new URI(UriUtils.encodeURIComponent(url));
if (uri.getScheme() == null) {
throw new InvalidParameterValueException("uri.scheme is null " + url + ", add http:// as a prefix");
} else if (uri.getScheme().equalsIgnoreCase("http")) {
if (uri.getHost() == null || uri.getHost().equalsIgnoreCase("") || uri.getPath() == null || uri.getPath().equalsIgnoreCase("")) {
throw new InvalidParameterValueException("Your host and/or path is wrong. Make sure it's of the format http://hostname/path");
}
}
} catch (URISyntaxException e) {
throw new InvalidParameterValueException(url + " is not a valid uri");
}
List<HostVO> hosts = new ArrayList<HostVO>();
Map<? extends ServerResource, Map<String, String>> resources = null;
try {
resources = discoverer.find(dcId, podId, clusterId, uri, username, password);
} catch (Exception e) {
s_logger.info("Exception in external cluster discovery process with discoverer: " + discoverer.getName());
}
if (resources != null) {
for (Map.Entry<? extends ServerResource, Map<String, String>> entry : resources.entrySet()) {
ServerResource resource = entry.getKey();
// For Hyper-V, we are here means agent have already started and connected to management server
if (hypervisorType == Hypervisor.HypervisorType.Hyperv) {
break;
}
AgentAttache attache = simulateStart(null, resource, entry.getValue(), true, null, null);
if (attache != null) {
hosts.add(_hostDao.findById(attache.getId()));
}
discoverer.postDiscovery(hosts, _nodeId);
}
s_logger.info("External cluster has been successfully discovered by " + discoverer.getName());
success = true;
return result;
}
s_logger.warn("Unable to find the server resources at " + url);
throw new DiscoveryException("Unable to add the external cluster");
} catch (Throwable e) {
s_logger.error("Unexpected exception ", e);
throw new DiscoveryException("Unable to add the external cluster due to unhandled exception");
} finally {
if (!success) {
_clusterDetailsDao.deleteDetails(clusterId);
_clusterDao.remove(clusterId);
}
}
}
private Discoverer getMatchingDiscover(Hypervisor.HypervisorType hypervisorType) {
Enumeration<Discoverer> en = _discoverers.enumeration();
while (en.hasMoreElements()) {
Discoverer discoverer = en.nextElement();
if (discoverer.getHypervisorType() == hypervisorType) {
return discoverer;
}
}
return null;
}
@Override
public List<? extends Host> discoverHosts(AddHostCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException {
Long dcId = cmd.getZoneId();
Long podId = cmd.getPodId();
Long clusterId = cmd.getClusterId();
String clusterName = cmd.getClusterName();
String url = cmd.getUrl();
String username = cmd.getUsername();
String password = cmd.getPassword();
Long memCapacity = cmd.getMemCapacity();
Long cpuSpeed = cmd.getCpuSpeed();
Long cpuNum = cmd.getCpuNum();
String mac = cmd.getMac();
List<String> hostTags = cmd.getHostTags();
Map<String, String> bareMetalParams = new HashMap<String, String>();
dcId = _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), dcId);
// this is for standalone option
if (clusterName == null && clusterId == null) {
clusterName = "Standalone-" + url;
}
if ( clusterId != null ) {
ClusterVO cluster = _clusterDao.findById(clusterId);
if ( cluster == null ) {
throw new InvalidParameterValueException("can not fine cluster for clusterId " + clusterId);
} else {
if ( cluster.getGuid() == null ) {
List<HostVO> hosts = _hostDao.listByCluster(clusterId);
if ( ! hosts.isEmpty() ) {
throw new CloudRuntimeException("Guid is not updated for cluster " + clusterId + " need to wait hosts in this cluster up");
}
}
}
}
if (cmd.getHypervisor().equalsIgnoreCase(Hypervisor.HypervisorType.BareMetal.toString())) {
if (memCapacity == null) {
memCapacity = Long.valueOf(0);
}
if (cpuSpeed == null) {
cpuSpeed = Long.valueOf(0);
}
if (cpuNum == null) {
cpuNum = Long.valueOf(0);
}
if (mac == null) {
mac = "unknown";
}
bareMetalParams.put("cpuNum", cpuNum.toString());
bareMetalParams.put("cpuCapacity", cpuSpeed.toString());
bareMetalParams.put("memCapacity", memCapacity.toString());
bareMetalParams.put("mac", mac);
if (hostTags != null) {
bareMetalParams.put("hostTag", hostTags.get(0));
}
}
String allocationState = cmd.getAllocationState();
if (allocationState == null) {
allocationState = Host.HostAllocationState.Enabled.toString();
}
return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, bareMetalParams, allocationState);
}
@Override
public List<? extends Host> discoverHosts(AddSecondaryStorageCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException {
Long dcId = cmd.getZoneId();
String url = cmd.getUrl();
return discoverHosts(dcId, null, null, null, url, null, null, "SecondaryStorage", null);
}
@Override
public List<HostVO> discoverHosts(Long dcId, Long podId, Long clusterId, String clusterName, String url, String username, String password, String hypervisorType, List<String> hostTags)
throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException {
return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, hypervisorType, hostTags, null, null);
}
private List<HostVO> discoverHostsFull(Long dcId, Long podId, Long clusterId, String clusterName, String url, String username, String password, String hypervisorType, List<String> hostTags,
Map<String, String> params, String allocationState) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException {
URI uri = null;
// Check if the zone exists in the system
DataCenterVO zone = _dcDao.findById(dcId);
if (zone == null) {
throw new InvalidParameterValueException("Can't find zone by id " + dcId);
}
Account account = UserContext.current().getCaller();
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) {
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + dcId);
}
// Check if the pod exists in the system
if (podId != null) {
if (_podDao.findById(podId) == null) {
throw new InvalidParameterValueException("Can't find pod by id " + podId);
}
// check if pod belongs to the zone
HostPodVO pod = _podDao.findById(podId);
if (!Long.valueOf(pod.getDataCenterId()).equals(dcId)) {
throw new InvalidParameterValueException("Pod " + podId + " doesn't belong to the zone " + dcId);
}
}
// Verify cluster information and create a new cluster if needed
if (clusterName != null && clusterId != null) {
throw new InvalidParameterValueException("Can't specify cluster by both id and name");
}
if (hypervisorType == null || hypervisorType.isEmpty()) {
throw new InvalidParameterValueException("Need to specify Hypervisor Type");
}
if ((clusterName != null || clusterId != null) && podId == null) {
throw new InvalidParameterValueException("Can't specify cluster without specifying the pod");
}
if (clusterId != null) {
if (_clusterDao.findById(clusterId) == null) {
throw new InvalidParameterValueException("Can't find cluster by id " + clusterId);
}
}
if (clusterName != null) {
ClusterVO cluster = new ClusterVO(dcId, podId, clusterName);
cluster.setHypervisorType(hypervisorType);
try {
cluster = _clusterDao.persist(cluster);
} catch (Exception e) {
cluster = _clusterDao.findBy(clusterName, podId);
if (cluster == null) {
throw new CloudRuntimeException("Unable to create cluster " + clusterName + " in pod " + podId + " and data center " + dcId, e);
}
}
clusterId = cluster.getId();
}
try {
uri = new URI(UriUtils.encodeURIComponent(url));
if (uri.getScheme() == null) {
throw new InvalidParameterValueException("uri.scheme is null " + url + ", add nfs:// as a prefix");
} else if (uri.getScheme().equalsIgnoreCase("nfs")) {
if (uri.getHost() == null || uri.getHost().equalsIgnoreCase("") || uri.getPath() == null || uri.getPath().equalsIgnoreCase("")) {
throw new InvalidParameterValueException("Your host and/or path is wrong. Make sure it's of the format nfs://hostname/path");
}
}
} catch (URISyntaxException e) {
throw new InvalidParameterValueException(url + " is not a valid uri");
}
List<HostVO> hosts = new ArrayList<HostVO>();
s_logger.info("Trying to add a new host at " + url + " in data center " + dcId);
Enumeration<Discoverer> en = _discoverers.enumeration();
boolean isHypervisorTypeSupported = false;
while (en.hasMoreElements()) {
Discoverer discoverer = en.nextElement();
if (params != null) {
discoverer.putParam(params);
}
if (!discoverer.matchHypervisor(hypervisorType)) {
continue;
}
isHypervisorTypeSupported = true;
Map<? extends ServerResource, Map<String, String>> resources = null;
try {
resources = discoverer.find(dcId, podId, clusterId, uri, username, password);
} catch (DiscoveredWithErrorException e) {
throw e;
} catch (Exception e) {
s_logger.info("Exception in host discovery process with discoverer: " + discoverer.getName() + ", skip to another discoverer if there is any");
}
if (resources != null) {
for (Map.Entry<? extends ServerResource, Map<String, String>> entry : resources.entrySet()) {
ServerResource resource = entry.getKey();
/*
* For KVM, if we go to here, that means kvm agent is already connected to mgt svr.
*/
if (resource instanceof KvmDummyResourceBase) {
Map<String, String> details = entry.getValue();
String guid = details.get("guid");
List<HostVO> kvmHosts = _hostDao.listBy(Host.Type.Routing, clusterId, podId, dcId);
for (HostVO host : kvmHosts) {
if (host.getGuid().equalsIgnoreCase(guid)) {
hosts.add(host);
return hosts;
}
}
return null;
}
AgentAttache attache = simulateStart(null, resource, entry.getValue(), true, hostTags, allocationState);
if (attache != null) {
hosts.add(_hostDao.findById(attache.getId()));
}
discoverer.postDiscovery(hosts, _nodeId);
}
s_logger.info("server resources successfully discovered by " + discoverer.getName());
return hosts;
}
}
if (!isHypervisorTypeSupported) {
String msg = "Do not support HypervisorType " + hypervisorType + " for " + url;
s_logger.warn(msg);
throw new DiscoveryException(msg);
}
s_logger.warn("Unable to find the server resources at " + url);
throw new DiscoveryException("Unable to add the host");
}
@Override
@DB
public boolean deleteCluster(DeleteClusterCmd cmd) {
Transaction txn = Transaction.currentTxn();
try {
txn.start();
ClusterVO cluster = _clusterDao.lockRow(cmd.getId(), true);
if (cluster == null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Cluster: " + cmd.getId() + " does not even exist. Delete call is ignored.");
}
txn.rollback();
return true;
}
List<HostVO> hosts = _hostDao.listByCluster(cmd.getId());
if (hosts.size() > 0) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Cluster: " + cmd.getId() + " still has hosts");
}
txn.rollback();
return false;
}
_clusterDao.remove(cmd.getId());
txn.commit();
return true;
} catch (Throwable t) {
s_logger.error("Unable to delete cluster: " + cmd.getId(), t);
txn.rollback();
return false;
}
}
@Override
@DB
public Cluster updateCluster(Cluster clusterToUpdate, String clusterType, String hypervisor, String allocationState) {
ClusterVO cluster = (ClusterVO) clusterToUpdate;
// Verify cluster information and update the cluster if needed
boolean doUpdate = false;
if (hypervisor != null && !hypervisor.isEmpty()) {
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.getType(hypervisor);
if (hypervisorType == null) {
s_logger.error("Unable to resolve " + hypervisor + " to a valid supported hypervisor type");
throw new InvalidParameterValueException("Unable to resolve " + hypervisor + " to a supported type");
} else {
cluster.setHypervisorType(hypervisor);
doUpdate = true;
}
}
Cluster.ClusterType newClusterType = null;
if (clusterType != null && !clusterType.isEmpty()) {
try {
newClusterType = Cluster.ClusterType.valueOf(clusterType);
} catch (IllegalArgumentException ex) {
throw new InvalidParameterValueException("Unable to resolve " + clusterType + " to a supported type");
}
if (newClusterType == null) {
s_logger.error("Unable to resolve " + clusterType + " to a valid supported cluster type");
throw new InvalidParameterValueException("Unable to resolve " + clusterType + " to a supported type");
} else {
cluster.setClusterType(newClusterType);
doUpdate = true;
}
}
Grouping.AllocationState newAllocationState = null;
if (allocationState != null && !allocationState.isEmpty()) {
try {
newAllocationState = Grouping.AllocationState.valueOf(allocationState);
} catch (IllegalArgumentException ex) {
throw new InvalidParameterValueException("Unable to resolve Allocation State '" + allocationState + "' to a supported state");
}
if (newAllocationState == null) {
s_logger.error("Unable to resolve " + allocationState + " to a valid supported allocation State");
throw new InvalidParameterValueException("Unable to resolve " + allocationState + " to a supported state");
} else {
cluster.setAllocationState(newAllocationState);
doUpdate = true;
}
}
if (doUpdate) {
Transaction txn = Transaction.currentTxn();
try {
txn.start();
_clusterDao.update(cluster.getId(), cluster);
txn.commit();
} catch (Exception e) {
s_logger.error("Unable to update cluster due to " + e.getMessage(), e);
throw new CloudRuntimeException("Failed to update cluster. Please contact Cloud Support.");
}
}
return cluster;
}
@Override
public Cluster getCluster(Long clusterId) {
return _clusterDao.findById(clusterId);
}
@Override
public Answer sendToSecStorage(HostVO ssHost, Command cmd) {
if( ssHost.getType() == Host.Type.LocalSecondaryStorage ) {
return easySend(ssHost.getId(), cmd);
} else if ( ssHost.getType() == Host.Type.SecondaryStorage) {
return sendToSSVM(ssHost.getDataCenterId(), cmd);
} else {
String msg = "do not support Secondary Storage type " + ssHost.getType();
s_logger.warn(msg);
return new Answer(cmd, false, msg);
}
}
@Override
public long sendToSecStorage(HostVO ssHost, Command cmd, Listener listener) {
if( ssHost.getType() == Host.Type.LocalSecondaryStorage ) {
return gatherStats(ssHost.getId(), cmd, listener);
} else if ( ssHost.getType() == Host.Type.SecondaryStorage) {
return sendToSSVM(ssHost.getDataCenterId(), cmd, listener);
} else {
s_logger.warn("do not support Secondary Storage type " + ssHost.getType());
}
return -1;
}
private long sendToSSVM(final long dcId, final Command cmd, final Listener listener) {
List<HostVO> ssAHosts = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorageVM, dcId);
if (ssAHosts == null || ssAHosts.isEmpty() ) {
return -1;
}
int size = ssAHosts.size();
Random rn = new Random(System.currentTimeMillis());
HostVO ssAhost = ssAHosts.get(rn.nextInt(size));
try {
return send(ssAhost.getId(), new Commands(cmd), listener);
} catch (final AgentUnavailableException e) {
return -1;
}
}
private Answer sendToSSVM(final long dcId, final Command cmd) {
List<HostVO> ssAHosts = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorageVM, dcId);
if (ssAHosts == null || ssAHosts.isEmpty() ) {
return new Answer(cmd, false, "can not find secondary storage VM agent for data center " + dcId);
}
int size = ssAHosts.size();
Random rn = new Random(System.currentTimeMillis());
HostVO ssAhost = ssAHosts.get(rn.nextInt(size));
return easySend(ssAhost.getId(), cmd);
}
@Override
public Answer sendTo(Long dcId, HypervisorType type, Command cmd) {
@ -889,6 +1433,9 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
return seq;
}
@Override
public long gatherStats(final Long hostId, final Command cmd, final Listener listener) {
try {
@ -1738,9 +2285,13 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
if (resource != null && resource instanceof DummySecondaryStorageResource) {
resource = null;
}
}else if (ssCmd.getResourceType() == Storage.StorageResourceType.LOCAL_SECONDARY_STORAGE) {
type = Host.Type.LocalSecondaryStorage;
} else {
type = Host.Type.Storage;
}
final Map<String, String> hostDetails = ssCmd.getHostDetails();
if (hostDetails != null) {
if (details != null) {
@ -1761,10 +2312,10 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
details = hostDetails;
}
}
} else if (startup instanceof StartupSecondaryStorageCommand) {
type = Host.Type.SecondaryStorageVM;
} else if (startup instanceof StartupProxyCommand) {
type = Host.Type.ConsoleProxy;
} else if (startup instanceof StartupRoutingCommand) {
type = Host.Type.Routing;
} else if (startup instanceof StartupExternalFirewallCommand) {
type = Host.Type.ExternalFirewall;
} else if (startup instanceof StartupExternalLoadBalancerCommand) {

View File

@ -169,4 +169,8 @@ public interface HostDao extends GenericDao<HostVO, Long> {
boolean directConnect(HostVO host, long msId, boolean secondConnect);
HostVO findTrafficMonitorHost();
List<HostVO> listLocalSecondaryStorageHosts();
List<HostVO> listLocalSecondaryStorageHosts(long dataCenterId);
}

View File

@ -54,6 +54,8 @@ import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.UpdateBuilder;
import com.cloud.utils.exception.CloudRuntimeException;
import edu.emory.mathcs.backport.java.util.Collections;
@Local(value = { HostDao.class }) @DB(txn=false)
@TableGenerator(name="host_req_sq", table="op_host", pkColumnName="id", valueColumnName="sequence", allocationSize=1)
@ -271,28 +273,51 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
}
@Override
public HostVO findSecondaryStorageHost(long dcId) {
SearchCriteria<HostVO> sc = TypeDcSearch.create();
sc.setParameters("type", Host.Type.SecondaryStorage);
sc.setParameters("dc", dcId);
List<HostVO> storageHosts = listBy(sc);
if (storageHosts == null || storageHosts.size() < 1) {
return null;
} else {
return storageHosts.get(0);
}
public HostVO findSecondaryStorageHost(long dcId) {
SearchCriteria<HostVO> sc = TypeDcSearch.create();
sc.setParameters("type", Host.Type.SecondaryStorage);
sc.setParameters("dc", dcId);
List<HostVO> storageHosts = listBy(sc);
if (storageHosts == null || storageHosts.size() < 1) {
return null;
} else {
Collections.shuffle(storageHosts);
return storageHosts.get(0);
}
}
@Override
public List<HostVO> listSecondaryStorageHosts() {
SearchCriteria<HostVO> sc = TypeSearch.create();
sc.setParameters("type", Host.Type.SecondaryStorage);
List<HostVO> secondaryStorageHosts = listIncludingRemovedBy(sc);
return secondaryStorageHosts;
}
SearchCriteria<HostVO> sc = createSearchCriteria();
sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.SecondaryStorage);
return search(sc, null);
}
@Override
public List<HostVO> listSecondaryStorageHosts(long dataCenterId) {
SearchCriteria<HostVO> sc = createSearchCriteria();
sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, dataCenterId);
sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.SecondaryStorage);
return search(sc, null);
}
@Override
public List<HostVO> listLocalSecondaryStorageHosts() {
SearchCriteria<HostVO> sc = createSearchCriteria();
sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.LocalSecondaryStorage);
return search(sc, null);
}
@Override
public List<HostVO> listLocalSecondaryStorageHosts(long dataCenterId) {
SearchCriteria<HostVO> sc = createSearchCriteria();
sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, dataCenterId);
sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.LocalSecondaryStorage);
return search(sc, null);
}
@Override
public List<HostVO> findDirectlyConnectedHosts() {
SearchCriteria<HostVO> sc = DirectlyConnectedSearch.create();

View File

@ -248,17 +248,11 @@ public class StatsCollector {
class StorageCollector implements Runnable {
@Override
public void run() {
try {
SearchCriteria<HostVO> sc = _hostDao.createSearchCriteria();
ConcurrentHashMap<Long, StorageStats> storageStats = new ConcurrentHashMap<Long, StorageStats>();
List<HostVO> hosts = _hostDao.search(sc, null);
sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString());
sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.SecondaryStorage.toString());
hosts = _hostDao.search(sc, null);
try {
List<HostVO> hosts = _hostDao.listSecondaryStorageHosts();
ConcurrentHashMap<Long, StorageStats> storageStats = new ConcurrentHashMap<Long, StorageStats>();
for (HostVO host : hosts) {
GetStorageStatsCommand command = new GetStorageStatsCommand(host.getGuid());
GetStorageStatsCommand command = new GetStorageStatsCommand(host.getStorageUrl());
long hostId = host.getId();
Answer answer = _agentMgr.easySend(hostId, command);
if (answer != null && answer.getResult()) {

View File

@ -182,6 +182,7 @@ import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import java.util.Random;
@Local(value = { StorageManager.class, StorageService.class })
public class StorageManagerImpl implements StorageManager, StorageService, Manager, ClusterManagerListener {
@ -221,6 +222,8 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
@Inject
protected SnapshotDao _snapshotDao;
@Inject
protected SnapshotManager _snapMgr;
@Inject
protected SnapshotPolicyDao _snapshotPolicyDao;
@Inject
protected StoragePoolHostDao _storagePoolHostDao;
@ -590,7 +593,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
Long volumeId = snapshot.getVolumeId();
String primaryStoragePoolNameLabel = pool.getUuid(); // pool's uuid is actually the namelabel.
Long dcId = snapshot.getDataCenterId();
String secondaryStoragePoolUrl = getSecondaryStorageURL(dcId);
String secondaryStoragePoolUrl = _snapMgr.getSecondaryStorageURL(snapshot);
long accountId = snapshot.getAccountId();
String backedUpSnapshotUuid = snapshot.getBackupSnapshotId();
@ -928,7 +931,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
@Override
public String getSecondaryStorageURL(long zoneId) {
// Determine the secondary storage URL
HostVO secondaryStorageHost = _hostDao.findSecondaryStorageHost(zoneId);
HostVO secondaryStorageHost = getSecondaryStorageHost(zoneId);
if (secondaryStorageHost == null) {
return null;
@ -939,7 +942,15 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
@Override
public HostVO getSecondaryStorageHost(long zoneId) {
return _hostDao.findSecondaryStorageHost(zoneId);
List<HostVO> hosts = _hostDao.listSecondaryStorageHosts(zoneId);
if( hosts == null) {
return null;
}
int size = hosts.size();
Random rn = new Random();
int index = rn.nextInt(size);
return hosts.get(index);
}
@Override
@ -1884,7 +1895,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag
String installPath = destroyedTemplateHostVO.getInstallPath();
if (installPath != null) {
Answer answer = _agentMgr.easySend(hostId, new DeleteTemplateCommand(destroyedTemplateHostVO.getInstallPath()));
Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, new DeleteTemplateCommand(secondaryStorageHost.getStorageUrl(),destroyedTemplateHostVO.getInstallPath()));
if (answer == null || !answer.getResult()) {
s_logger.debug("Failed to delete " + destroyedTemplateHostVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails()));

View File

@ -35,5 +35,6 @@ public interface SnapshotDao extends GenericDao<SnapshotVO, Long> {
List<SnapshotVO> listByBackupUuid(long volumeId, String backupUuid);
long updateSnapshotVersion(long volumeId, String from, String to);
List<SnapshotVO> listByVolumeIdVersion(long volumeId, String version);
Long getSecHostId(long volumeId);
}

View File

@ -39,6 +39,7 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
public static final Logger s_logger = Logger.getLogger(SnapshotDaoImpl.class.getName());
private static final String GET_LAST_SNAPSHOT = "SELECT id FROM snapshots where volume_id = ? AND id != ? AND path IS NOT NULL ORDER BY created DESC";
private static final String UPDATE_SNAPSHOT_VERSION = "UPDATE snapshots SET version = ? WHERE volume_id = ? AND version = ?";
private static final String GET_SECHOST_ID = "SELECT sechost_id FROM snapshots where volume_id = ? AND backup_snap_id IS NOT NULL AND sechost_id IS NOT NULL LIMIT 1";
private final SearchBuilder<SnapshotVO> VolumeIdSearch;
private final SearchBuilder<SnapshotVO> VolumeIdTypeSearch;
@ -129,6 +130,23 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
}
@Override
public Long getSecHostId(long volumeId) {
Transaction txn = Transaction.currentTxn();
PreparedStatement pstmt = null;
String sql = GET_SECHOST_ID;
try {
pstmt = txn.prepareAutoCloseStatement(sql);
pstmt.setLong(1, volumeId);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
return rs.getLong(1);
}
} catch (Exception ex) {
}
return null;
}
@Override
public long getLastSnapshot(long volumeId, long snapId) {
Transaction txn = Transaction.currentTxn();

View File

@ -33,6 +33,7 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
import com.cloud.agent.api.storage.DownloadCommand;
@ -48,6 +49,7 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.download.DownloadState.DownloadEvent;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.utils.exception.CloudRuntimeException;
/**
@ -277,25 +279,16 @@ public class DownloadListener implements Listener {
@Override
public void processConnect(HostVO agent, StartupCommand cmd) throws ConnectionException {
if (!((cmd instanceof StartupStorageCommand) || (cmd instanceof StartupRoutingCommand))) {
return;
}
if (cmd instanceof StartupRoutingCommand) {
downloadMonitor.handleSysTemplateDownload(agent);
} else {
if (cmd.getGuid().startsWith("iso:")) {
//FIXME: do not download template for ISO secondary
return;
}
long agentId = agent.getId();
} else if ( cmd instanceof StartupStorageCommand) {
StartupStorageCommand storage = (StartupStorageCommand)cmd;
if (storage.getResourceType() == Storage.StorageResourceType.STORAGE_HOST ||
storage.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE )
{
downloadMonitor.handleTemplateSync(agentId, storage.getTemplateInfo());
}
if( storage.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE ) {
downloadMonitor.addSystemVMTemplatesToHost(agent, storage.getTemplateInfo());
downloadMonitor.handleTemplateSync(agent.getId());
}
} else if ( cmd instanceof StartupSecondaryStorageCommand ) {
downloadMonitor.handleTemplateSync(agent.getDataCenterId());
}
}

View File

@ -38,7 +38,7 @@ public interface DownloadMonitor extends Manager{
public void cancelAllDownloads(Long templateId);
public void handleTemplateSync(long id, Map<String, TemplateInfo> templateInfo);
public void handleTemplateSync(HostVO host);
public void copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer)
throws StorageUnavailableException;
@ -46,4 +46,8 @@ public interface DownloadMonitor extends Manager{
/*When new host added, take a look at if there are templates needed to be downloaded for the same hypervisor as the host*/
void handleSysTemplateDownload(HostVO hostId);
void handleTemplateSync(long dcId);
void addSystemVMTemplatesToHost(HostVO host, Map<String, TemplateInfo> templateInfos);
}

View File

@ -19,9 +19,11 @@ package com.cloud.storage.download;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
@ -32,10 +34,13 @@ import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.storage.DeleteTemplateCommand;
import com.cloud.agent.api.storage.DownloadCommand;
import com.cloud.agent.api.storage.DownloadProgressCommand;
import com.cloud.agent.api.storage.ListTemplateAnswer;
import com.cloud.agent.api.storage.ListTemplateCommand;
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
import com.cloud.alert.AlertManager;
import com.cloud.configuration.dao.ConfigurationDao;
@ -101,8 +106,6 @@ public class DownloadMonitorImpl implements DownloadMonitor {
@Inject
AlertManager _alertMgr;
@Inject
HostDao _serverDao = null;
@Inject
private final DataCenterDao _dcDao = null;
@Inject
@ -133,7 +136,6 @@ public class DownloadMonitorImpl implements DownloadMonitor {
final Map<VMTemplateHostVO, DownloadListener> _listenerMap = new ConcurrentHashMap<VMTemplateHostVO, DownloadListener>();
public long send(Long hostId, Command cmd, Listener listener) {
return _agentMgr.gatherStats(hostId, cmd, listener);
}
@ -229,7 +231,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
if(destTmpltHost != null) {
start();
DownloadCommand dcmd = new DownloadCommand(url, template.getUniqueName(), template.getFormat(), template.isRequiresHvm(), template.getAccountId(), template.getId(), template.getDisplayText(), template.getChecksum(), TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd, maxTemplateSizeInBytes);
DownloadCommand dcmd = new DownloadCommand(destServer.getStorageUrl(), url, template, TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd, maxTemplateSizeInBytes);
DownloadListener dl = downloadJobExists?_listenerMap.get(destTmpltHost):null;
if (dl == null) {
dl = new DownloadListener(destServer, template, _timer, _vmTemplateHostDao, destTmpltHost.getId(), this, dcmd);
@ -241,7 +243,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
_listenerMap.put(destTmpltHost, dl);
long result = send(destServer.getId(), dcmd, dl);
long result = _agentMgr.sendToSecStorage(destServer, dcmd, dl);
if (result == -1) {
s_logger.warn("Unable to start /resume COPY of template " + template.getUniqueName() + " to " + destServer.getName());
dl.setDisconnected();
@ -294,10 +296,10 @@ public class DownloadMonitorImpl implements DownloadMonitor {
}
Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes();
String url = sserver.getStorageUrl();
if(vmTemplateHost != null) {
start();
DownloadCommand dcmd = new DownloadCommand(template, maxTemplateSizeInBytes);
DownloadCommand dcmd = new DownloadCommand(url, template, maxTemplateSizeInBytes);
dcmd.setUrl(vmTemplateHost.getDownloadUrl());
if (vmTemplateHost.isCopy()) {
dcmd.setCreds(TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd);
@ -310,7 +312,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
_listenerMap.put(vmTemplateHost, dl);
long result = send(sserver.getId(), dcmd, dl);
long result = _agentMgr.sendToSecStorage(sserver, dcmd, dl);
if (result == -1) {
s_logger.warn("Unable to start /resume download of template " + template.getUniqueName() + " to " + sserver.getName());
dl.setDisconnected();
@ -323,32 +325,29 @@ public class DownloadMonitorImpl implements DownloadMonitor {
@Override
public boolean downloadTemplateToStorage(Long templateId, Long zoneId) {
if (isTemplateUpdateable(templateId)) {
List<DataCenterVO> dcs = new ArrayList<DataCenterVO>();
if (zoneId == null) {
dcs.addAll(_dcDao.listAllIncludingRemoved());
} else {
dcs.add(_dcDao.findById(zoneId));
}
for (DataCenterVO dc: dcs) {
initiateTemplateDownload(templateId, dc.getId());
}
return true;
} else {
return false;
}
List<DataCenterVO> dcs = new ArrayList<DataCenterVO>();
if (zoneId == null) {
dcs.addAll(_dcDao.listAll());
} else {
dcs.add(_dcDao.findById(zoneId));
}
for ( DataCenterVO dc : dcs ) {
List<HostVO> ssHosts = _hostDao.listBy(Host.Type.SecondaryStorage, dc.getId());
for ( HostVO ssHost : ssHosts ) {
if (isTemplateUpdateable(ssHost.getId(), templateId)) {
initiateTemplateDownload(templateId, ssHost);
}
}
}
return true;
}
private void initiateTemplateDownload(Long templateId, Long dataCenterId) {
private void initiateTemplateDownload(Long templateId, HostVO ssHost) {
VMTemplateVO template = _templateDao.findById(templateId);
if (template != null && (template.getUrl() != null)) {
//find all storage hosts and tell them to initiate download
List<HostVO> storageServers = _serverDao.listByTypeDataCenter(Host.Type.SecondaryStorage, dataCenterId);
for (HostVO sserver: storageServers) {
downloadTemplateToStorage(template, sserver);
}
downloadTemplateToStorage(template, ssHost);
}
}
@ -428,47 +427,104 @@ public class DownloadMonitorImpl implements DownloadMonitor {
if (ssHosts == null || ssHosts.isEmpty()) {
return;
}
HostVO sshost = ssHosts.get(0);
/*Download all the templates in zone with the same hypervisortype*/
for ( HostVO ssHost : ssHosts) {
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates();
for (VMTemplateVO rtngTmplt : rtngTmplts) {
if (rtngTmplt.getHypervisorType() == hostHyper) {
toBeDownloaded.add(rtngTmplt);
}
}
for (VMTemplateVO builtinTmplt : defaultBuiltin) {
if (builtinTmplt.getHypervisorType() == hostHyper) {
toBeDownloaded.add(builtinTmplt);
}
}
for (VMTemplateVO template: toBeDownloaded) {
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(ssHost.getId(), template.getId());
if (tmpltHost == null || tmpltHost.getDownloadState() != Status.DOWNLOADED) {
downloadTemplateToStorage(template, ssHost);
}
}
}
}
@Override
public void addSystemVMTemplatesToHost(HostVO host, Map<String, TemplateInfo> templateInfos){
if ( templateInfos == null ) {
return;
}
Long hostId = host.getId();
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates();
for (VMTemplateVO rtngTmplt : rtngTmplts) {
if (rtngTmplt.getHypervisorType() == hostHyper) {
toBeDownloaded.add(rtngTmplt);
for ( VMTemplateVO tmplt : rtngTmplts ) {
TemplateInfo tmpltInfo = templateInfos.get(tmplt.getUniqueName());
if ( tmpltInfo == null ) {
continue;
}
}
for (VMTemplateVO builtinTmplt : defaultBuiltin) {
if (builtinTmplt.getHypervisorType() == hostHyper) {
toBeDownloaded.add(builtinTmplt);
}
}
for (VMTemplateVO template: toBeDownloaded) {
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(sshost.getId(), template.getId());
if (tmpltHost == null || tmpltHost.getDownloadState() != Status.DOWNLOADED) {
if (_vmTemplateZoneDao.findByZoneTemplate(sshost.getDataCenterId(), template.getId()) == null) {
_templateDao.addTemplateToZone(template, sshost.getDataCenterId());
}
downloadTemplateToStorage(template, sshost);
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(hostId, tmplt.getId());
if ( tmpltHost == null ) {
tmpltHost = new VMTemplateHostVO(hostId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl());
tmpltHost.setSize(tmpltInfo.getSize());
tmpltHost.setPhysicalSize(tmpltInfo.getPhysicalSize());
_vmTemplateHostDao.persist(tmpltHost);
}
}
}
@Override
public void handleTemplateSync(long dcId) {
List<HostVO> ssHosts = _hostDao.listSecondaryStorageHosts(dcId);
for ( HostVO ssHost : ssHosts ) {
Long hostId = ssHost.getId();
List<VMTemplateHostVO> ths = _vmTemplateHostDao.listByHostId(hostId);
Map<String, TemplateInfo> templateInfos = new HashMap<String, TemplateInfo>();
for ( VMTemplateHostVO th : ths ) {
String tname = _templateDao.findById(th.getTemplateId()).getUniqueName();
templateInfos.put(tname, null);
}
handleTemplateSync(ssHost);
}
}
private Map<String, TemplateInfo> listTemplate(HostVO ssHost) {
ListTemplateCommand cmd = new ListTemplateCommand(ssHost.getStorageUrl());
Answer answer = _agentMgr.sendToSecStorage(ssHost, cmd);
if (answer != null && answer.getResult()) {
ListTemplateAnswer tanswer = (ListTemplateAnswer)answer;
return tanswer.getTemplateInfo();
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("can not list template for secondary storage host " + ssHost.getId());
}
}
return null;
}
@Override
public void handleTemplateSync(long sserverId, Map<String, TemplateInfo> templateInfos) {
HostVO storageHost = _serverDao.findById(sserverId);
if (storageHost == null) {
public void handleTemplateSync(HostVO ssHost) {
Long sserverId = ssHost.getId();
if (ssHost == null) {
s_logger.warn("Huh? Agent id " + sserverId + " does not correspond to a row in hosts table?");
return;
}
long zoneId = storageHost.getDataCenterId();
}
if ( ssHost.getType() != Host.Type.SecondaryStorage ) {
s_logger.warn("Huh? Agent id " + sserverId + " is not secondary storage host");
return;
}
Map<String, TemplateInfo> templateInfos = listTemplate(ssHost);
if( templateInfos == null ) {
return;
}
long zoneId = ssHost.getDataCenterId();
Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>();
List<VMTemplateVO> allTemplates = _templateDao.listAllInZone(storageHost.getDataCenterId());
List<VMTemplateVO> allTemplates = _templateDao.listAllInZone(ssHost.getDataCenterId());
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates();
@ -561,19 +617,15 @@ public class DownloadMonitorImpl implements DownloadMonitor {
}
if (toBeDownloaded.size() > 0) {
HostVO sserver = _serverDao.findById(sserverId);
if (sserver == null) {
throw new CloudRuntimeException("Unable to find host from id");
}
/*Only download templates whose hypervirsor type is in the zone*/
List<HypervisorType> availHypers = _clusterDao.getAvailableHypervisorInZone(sserver.getDataCenterId());
List<HypervisorType> availHypers = _clusterDao.getAvailableHypervisorInZone(ssHost.getDataCenterId());
/* Baremetal need not to download any template */
availHypers.remove(HypervisorType.BareMetal);
availHypers.add(HypervisorType.None); //bug 9809: resume ISO download.
for (VMTemplateVO tmplt: toBeDownloaded) {
if (tmplt.getUrl() == null){ // If url is null we cant initiate the download so mark it as an error.
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(sserver.getId(), tmplt.getId());
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(ssHost.getId(), tmplt.getId());
if(tmpltHost != null){
tmpltHost.setDownloadState(Status.DOWNLOAD_ERROR);
tmpltHost.setDownloadPercent(0);
@ -584,16 +636,16 @@ public class DownloadMonitorImpl implements DownloadMonitor {
}
if (availHypers.contains(tmplt.getHypervisorType())) {
s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + sserver.getName());
downloadTemplateToStorage(tmplt, sserver);
s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + ssHost.getName());
downloadTemplateToStorage(tmplt, ssHost);
}
}
}
for (String uniqueName: templateInfos.keySet()) {
TemplateInfo tInfo = templateInfos.get(uniqueName);
DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(tInfo.getInstallPath());
long result = send(sserverId, dtCommand, null);
DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(ssHost.getStorageUrl(), tInfo.getInstallPath());
long result = _agentMgr.sendToSecStorage(ssHost, dtCommand, null);
if (result == -1 ){
String description = "Failed to delete " + tInfo.getTemplateName() + " on secondary storage " + sserverId + " which isn't in the database";
s_logger.error(description);

View File

@ -35,6 +35,8 @@ import com.cloud.agent.api.GetStorageStatsAnswer;
import com.cloud.agent.api.GetStorageStatsCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingStorageCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
@ -87,7 +89,9 @@ public class DummySecondaryStorageResource extends ServerResourceBase implements
} else if (cmd instanceof GetStorageStatsCommand) {
return execute((GetStorageStatsCommand)cmd);
} else if (cmd instanceof CheckHealthCommand) {
return new CheckHealthAnswer((CheckHealthCommand)cmd, true);
return new CheckHealthAnswer((CheckHealthCommand)cmd, true);
} else if (cmd instanceof ReadyCommand) {
return new ReadyAnswer((ReadyCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}

View File

@ -25,6 +25,7 @@ import com.cloud.agent.api.AgentControlCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
@ -67,17 +68,26 @@ public class SecondaryStorageListener implements Listener {
@Override
public void processConnect(HostVO agent, StartupCommand cmd) {
if (cmd instanceof StartupStorageCommand) {
if(s_logger.isInfoEnabled())
s_logger.info("Received a host startup notification");
StartupStorageCommand ss = (StartupStorageCommand)cmd;
if (ss.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE) {
_ssVmMgr.onAgentConnect(agent.getDataCenterId(), cmd);
_ssVmMgr.generateFirewallConfiguration(agent.getId());
_ssVmMgr.generateSetupCommand(agent.getDataCenterId());
if ((cmd instanceof StartupStorageCommand) ) {
StartupStorageCommand scmd = (StartupStorageCommand)cmd;
if (scmd.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE ) {
_ssVmMgr.generateSetupCommand(agent.getId());
return;
}
}
} else if (cmd instanceof StartupSecondaryStorageCommand) {
if(s_logger.isInfoEnabled()) {
s_logger.info("Received a host startup notification " + cmd);
}
_ssVmMgr.onAgentConnect(agent.getDataCenterId(), cmd);
_ssVmMgr.generateSetupCommand(agent.getId());
_ssVmMgr.generateFirewallConfiguration(agent.getId());
_ssVmMgr.generateVMSetupCommand(agent.getId());
return;
}
return;
}
@Override

View File

@ -35,6 +35,7 @@ import com.cloud.agent.api.Command;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand;
import com.cloud.agent.api.SecStorageSetupCommand;
import com.cloud.agent.api.SecStorageVMSetupCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.check.CheckSshAnswer;
@ -212,38 +213,84 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
}
}
@Override
public boolean generateFirewallConfiguration(Long hostId) {
if (hostId == null) {
return true;
SecondaryStorageVmVO getSSVMfromHost(HostVO ssAHost) {
if( ssAHost.getType() == Host.Type.SecondaryStorageVM ) {
return _secStorageVmDao.findByInstanceName(ssAHost.getName());
}
boolean success = true;
List<DataCenterVO> allZones = _dcDao.listAll();
for (DataCenterVO zone : allZones) {
success = success && generateFirewallConfigurationForZone(zone.getId());
return null;
}
@Override
public boolean generateSetupCommand(Long ssHostId) {
HostVO cssHost = _hostDao.findById(ssHostId);
Long zoneId = cssHost.getDataCenterId();
if( cssHost.getType() == Host.Type.SecondaryStorageVM ) {
SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findByInstanceName(cssHost.getName());
if (secStorageVm == null) {
s_logger.warn("secondary storage VM " + cssHost.getName() + " doesn't exist");
return false;
}
if (secStorageVm.getState() != State.Running) {
s_logger.warn("secondary storage VM " + cssHost.getName() + " is not running");
return false;
}
List<HostVO> ssHosts = _hostDao.listSecondaryStorageHosts(zoneId);
for( HostVO ssHost : ssHosts ) {
String secUrl = ssHost.getStorageUrl();
SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(secUrl);
Answer answer = _agentMgr.easySend(ssHostId, setupCmd);
if (answer != null && answer.getResult()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully programmed secondary storage " + ssHost.getName() + " in secondary storage VM " + secStorageVm.getInstanceName());
}
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully programmed secondary storage " + ssHost.getName() + " in secondary storage VM " + secStorageVm.getInstanceName());
}
return false;
}
}
} else if( cssHost.getType() == Host.Type.SecondaryStorage ) {
List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, zoneId, State.Running);
String secUrl = cssHost.getStorageUrl();
SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(secUrl);
for ( SecondaryStorageVmVO ssVm : alreadyRunning ) {
HostVO host = _hostDao.findByName(ssVm.getInstanceName());
Answer answer = _agentMgr.easySend(host.getId(), setupCmd);
if (answer != null && answer.getResult()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully programmed secondary storage " + host.getName() + " in secondary storage VM " + ssVm.getInstanceName());
}
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully programmed secondary storage " + host.getName() + " in secondary storage VM " + ssVm.getInstanceName());
}
return false;
}
}
}
return true;
}
@Override
public boolean generateSetupCommand(Long zoneId) {
List<SecondaryStorageVmVO> zoneSsvms = _secStorageVmDao.listByZoneId(SecondaryStorageVm.Role.templateProcessor, zoneId);
if (zoneSsvms.size() == 0) {
return true;
public boolean generateVMSetupCommand(Long ssAHostId) {
HostVO ssAHost = _hostDao.findById(ssAHostId);
if( ssAHost.getType() != Host.Type.SecondaryStorageVM ) {
return false;
}
SecondaryStorageVmVO secStorageVm = zoneSsvms.get(0);// FIXME: assumes
// one vm per zone.
if (secStorageVm.getState() != State.Running && secStorageVm.getState() != State.Starting) {
s_logger.warn("No running secondary storage vms found in zone " + zoneId + " , skip programming http auth");
return true;
SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findByInstanceName(ssAHost.getName());
if (secStorageVm == null) {
s_logger.warn("secondary storage VM " + ssAHost.getName() + " doesn't exist");
return false;
}
Host storageHost = _hostDao.findSecondaryStorageHost(zoneId);
if (storageHost == null) {
s_logger.warn("No storage hosts found in zone " + zoneId + " , skip programming http auth");
return true;
if (secStorageVm.getState() != State.Running) {
s_logger.warn("secondary storage VM " + ssAHost.getName() + " is not running");
return false;
}
SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(zoneId);
SecStorageVMSetupCommand setupCmd = new SecStorageVMSetupCommand();
if (_allowedInternalSites != null) {
List<String> allowedCidrs = new ArrayList<String>();
String[] cidrs = _allowedInternalSites.split(",");
@ -265,7 +312,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
String copyPasswd = _configDao.getValue("secstorage.copy.password");
setupCmd.setCopyPassword(copyPasswd);
setupCmd.setCopyUserName(TemplateConstants.DEFAULT_HTTP_AUTH_USER);
Answer answer = _agentMgr.easySend(storageHost.getId(), setupCmd);
Answer answer = _agentMgr.easySend(ssAHostId, setupCmd);
if (answer != null && answer.getResult()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully programmed http auth into " + secStorageVm.getHostName());
@ -284,49 +331,68 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
return null;
}
private boolean generateFirewallConfigurationForZone(Long zoneId) {
List<SecondaryStorageVmVO> zoneSsvms = _secStorageVmDao.listByZoneId(SecondaryStorageVm.Role.templateProcessor, zoneId);
if (zoneSsvms.size() == 0) {
@Override
public boolean generateFirewallConfiguration(Long ssAHostId) {
if ( ssAHostId == null ) {
return true;
}
SecondaryStorageVmVO secStorageVm = zoneSsvms.get(0);// FIXME: assumes
// one vm per zone.
if (secStorageVm.getState() != State.Running && secStorageVm.getState() != State.Starting) {
s_logger.warn("No running secondary storage vms found in zone " + zoneId + " , skip programming firewall rules");
return true;
HostVO ssAHost = _hostDao.findById(ssAHostId);
Long zoneId = ssAHost.getDataCenterId();
SecondaryStorageVmVO thisSecStorageVm = _secStorageVmDao.findByInstanceName(ssAHost.getName());
if (thisSecStorageVm == null) {
s_logger.warn("secondary storage VM " + ssAHost.getName() + " doesn't exist");
return false;
}
Host storageHost = _hostDao.findSecondaryStorageHost(zoneId);
if (storageHost == null) {
s_logger.warn("No storage hosts found in zone " + zoneId + " , skip programming firewall rules");
return true;
if (thisSecStorageVm.getState() != State.Running) {
s_logger.warn("secondary storage VM " + ssAHost.getName() + " is not running");
return false;
}
List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, State.Running, State.Migrating, State.Starting);
String copyPort = Integer.toString(TemplateConstants.DEFAULT_TMPLT_COPY_PORT);
String copyPort = _useSSlCopy? "443" : Integer.toString(TemplateConstants.DEFAULT_TMPLT_COPY_PORT);
SecStorageFirewallCfgCommand cpc = new SecStorageFirewallCfgCommand();
SecStorageFirewallCfgCommand thiscpc = new SecStorageFirewallCfgCommand();
thiscpc.addPortConfig(thisSecStorageVm.getPublicIpAddress(), copyPort, true, TemplateConstants.DEFAULT_TMPLT_COPY_INTF);
for (SecondaryStorageVmVO ssVm : alreadyRunning) {
if ( ssVm.getDataCenterId() == zoneId ) {
continue;
}
if (ssVm.getPublicIpAddress() != null) {
if (ssVm.getId() == secStorageVm.getId()) {
continue;
}
cpc.addPortConfig(ssVm.getPublicIpAddress(), copyPort, true, TemplateConstants.DEFAULT_TMPLT_COPY_INTF);
if (_useSSlCopy) {
cpc.addPortConfig(ssVm.getPublicIpAddress(), "443", true, TemplateConstants.DEFAULT_TMPLT_COPY_INTF);
}
if ( ssVm.getState() != State.Running ) {
continue;
}
String instanceName = ssVm.getInstanceName();
HostVO host = _hostDao.findByName(instanceName);
Answer answer = _agentMgr.easySend(host.getId(), thiscpc);
if (answer != null && answer.getResult()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully programmed firewall rules into " + ssVm.getHostName());
}
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("failed to program firewall rules into secondary storage vm : " + ssVm.getHostName());
}
return false;
}
}
Answer answer = _agentMgr.easySend(storageHost.getId(), cpc);
Answer answer = _agentMgr.easySend(ssAHostId, cpc);
if (answer != null && answer.getResult()) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully programmed firewall rules into " + secStorageVm.getHostName());
s_logger.debug("Successfully programmed firewall rules into " + thisSecStorageVm.getHostName());
}
return true;
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("failed to program firewall rules into secondary storage vm : " + secStorageVm.getHostName());
s_logger.debug("failed to program firewall rules into secondary storage vm : " + thisSecStorageVm.getHostName());
}
return false;
}
return true;
}
@ -500,7 +566,8 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
}
return;
}
boolean secStorageVmFromStoppedPool = false;
SecondaryStorageVmVO secStorageVm = assignSecStorageVmFromStoppedPool(dataCenterId, role);
if (secStorageVm == null) {
@ -685,7 +752,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
_mgmt_port = NumbersUtil.parseInt(value, 8250);
_listener = new SecondaryStorageListener(this);
_agentMgr.registerForHostEvents(_listener, true, true, false);
_agentMgr.registerForHostEvents(_listener, true, false, true);
_itMgr.registerGuru(VirtualMachine.Type.SecondaryStorageVm, this);
@ -851,19 +918,8 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
buf.append(" zone=").append(dest.getDataCenter().getId());
buf.append(" pod=").append(dest.getPod().getId());
if (profile.getVirtualMachine().getRole() == SecondaryStorageVm.Role.templateProcessor) {
buf.append(" guid=").append(secHost.getGuid());
} else {
buf.append(" guid=").append(profile.getVirtualMachine().getHostName());
}
buf.append(" guid=").append(profile.getVirtualMachine().getHostName());
String nfsMountPoint = null;
try {
nfsMountPoint = NfsUtils.url2Mount(secHost.getStorageUrl());
} catch (Exception e) {
}
buf.append(" mount.path=").append(nfsMountPoint);
if (_configDao.isPremium()) {
if (profile.getHypervisorType() == HypervisorType.Hyperv) {
buf.append(" resource=com.cloud.storage.resource.CifsSecondaryStorageResource");
@ -875,7 +931,6 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
}
buf.append(" instance=SecStorage");
buf.append(" sslcopy=").append(Boolean.toString(_useSSlCopy));
buf.append(" role=").append(profile.getVirtualMachine().getRole().toString());
boolean externalDhcp = false;
String externalDhcpStr = _configDao.getValue("direct.attach.network.externalIpAllocator.enabled");
@ -1048,16 +1103,14 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
public Pair<AfterScanAction, Object> scanPool(Long pool) {
long dataCenterId = pool.longValue();
List<SecondaryStorageVmVO> alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running, State.Migrating,
State.Starting);
List<SecondaryStorageVmVO> stopped = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Stopped, State.Stopping);
if (alreadyRunning.size() == 0) {
if (stopped.size() == 0) {
s_logger.info("No secondary storage vms found in datacenter id=" + dataCenterId + ", starting a new one");
return new Pair<AfterScanAction, Object>(AfterScanAction.expand, SecondaryStorageVm.Role.templateProcessor);
} else {
s_logger.warn("Stopped secondary storage vms found in datacenter id=" + dataCenterId + ", not restarting them automatically");
}
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running, State.Migrating,
State.Starting, State.Stopped, State.Stopping );
int vmSize = (ssVms == null)? 0 : ssVms.size();
List<HostVO> ssHosts = _hostDao.listSecondaryStorageHosts(dataCenterId);
int hostSize = (ssHosts == null)? 0 : ssHosts.size();
if ( hostSize > vmSize ) {
s_logger.info("No secondary storage vms found in datacenter id=" + dataCenterId + ", starting a new one");
return new Pair<AfterScanAction, Object>(AfterScanAction.expand, SecondaryStorageVm.Role.templateProcessor);
}
return new Pair<AfterScanAction, Object>(AfterScanAction.nop, SecondaryStorageVm.Role.templateProcessor);

View File

@ -40,7 +40,8 @@ public interface SecondaryStorageVmManager extends Manager {
public boolean destroySecStorageVm(long ssVmVmId);
public void onAgentConnect(Long dcId, StartupCommand cmd);
public boolean generateFirewallConfiguration(Long agentId);
public boolean generateSetupCommand(Long zoneId);
public boolean generateVMSetupCommand(Long hostId);
public Pair<HostVO, SecondaryStorageVmVO> assignSecStorageVm(long zoneId, Command cmd);
public Pair<HostVO, SecondaryStorageVmVO> assignSecStorageVm(long zoneId, Command cmd);
boolean generateSetupCommand(Long hostId);
}

View File

@ -130,4 +130,6 @@ public interface SnapshotManager {
List<SnapshotVO> listSnapsforPolicy(long policyId, Filter filter);
void downloadSnapshotsFromSwift(SnapshotVO ss);
String getSecondaryStorageURL(SnapshotVO snapshot);
}

View File

@ -518,8 +518,10 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
String primaryStoragePoolNameLabel = _storageMgr.getPrimaryStorageNameLabel(volume);
Long dcId = volume.getDataCenterId();
Long accountId = volume.getAccountId();
String secondaryStoragePoolUrl = _storageMgr.getSecondaryStorageURL(volume.getDataCenterId());
HostVO secHost = getSecHost(volumeId, volume.getDataCenterId());
String secondaryStoragePoolUrl = secHost.getStorageUrl();
String snapshotUuid = snapshot.getPath();
// In order to verify that the snapshot is not empty,
// we check if the parent of the snapshot is not the same as the parent of the previous snapshot.
@ -603,6 +605,14 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
private HostVO getSecHost(long volumeId, long dcId) {
Long id = _snapshotDao.getSecHostId(volumeId);
if ( id != null) {
return _hostDao.findById(id);
}
return _storageMgr.getSecondaryStorageHost(dcId);
}
private Long getSnapshotUserId() {
Long userId = UserContext.current().getCallerUserId();
if (userId == null) {
@ -766,6 +776,13 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
return true;
}
@Override
public String getSecondaryStorageURL(SnapshotVO snapshot) {
HostVO secHost = _hostDao.findById(snapshot.getSecHostId());
return secHost.getStorageUrl();
}
@Override
@DB
public boolean destroySnapshotBackUp(long snapshotId) {
@ -776,7 +793,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
throw new CloudRuntimeException("Destroying snapshot " + snapshotId + " backup failed due to unable to find snapshot ");
}
String secondaryStoragePoolUrl = _storageMgr.getSecondaryStorageURL(snapshot.getDataCenterId());
String secondaryStoragePoolUrl = getSecondaryStorageURL(snapshot);
Long dcId = snapshot.getDataCenterId();
Long accountId = snapshot.getAccountId();
Long volumeId = snapshot.getVolumeId();
@ -954,32 +971,35 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
Long volumeId = volume.getId();
Long dcId = volume.getDataCenterId();
String secondaryStoragePoolURL = _storageMgr.getSecondaryStorageURL(dcId);
String primaryStoragePoolNameLabel = _storageMgr.getPrimaryStorageNameLabel(volume);
if (_snapshotDao.listByVolumeIdIncludingRemoved(volumeId).isEmpty()) {
// This volume doesn't have any snapshots. Nothing do delete.
continue;
}
DeleteSnapshotsDirCommand cmd = new DeleteSnapshotsDirCommand(primaryStoragePoolNameLabel, secondaryStoragePoolURL, dcId, accountId, volumeId, volume.getPath());
Answer answer = null;
Long poolId = volume.getPoolId();
if (poolId != null) {
// Retry only once for this command. There's low chance of failure because of a connection problem.
try {
answer = _storageMgr.sendToPool(poolId, cmd);
} catch (StorageUnavailableException e) {
List<HostVO> ssHosts = _hostDao.listSecondaryStorageHosts(dcId);
for ( HostVO ssHost : ssHosts ) {
DeleteSnapshotsDirCommand cmd = new DeleteSnapshotsDirCommand(primaryStoragePoolNameLabel, ssHost.getStorageUrl(), dcId, accountId, volumeId, volume.getPath());
Answer answer = null;
Long poolId = volume.getPoolId();
if (poolId != null) {
// Retry only once for this command. There's low chance of failure because of a connection problem.
try {
answer = _storageMgr.sendToPool(poolId, cmd);
} catch (StorageUnavailableException e) {
}
} else {
s_logger.info("Pool id for volume id: " + volumeId + " belonging to account id: " + accountId + " is null. Assuming the snapshotsDir for the account has already been deleted");
}
} else {
s_logger.info("Pool id for volume id: " + volumeId + " belonging to account id: " + accountId + " is null. Assuming the snapshotsDir for the account has already been deleted");
}
if (success) {
// SnapshotsDir has been deleted for the volumes so far.
success = (answer != null) && answer.getResult();
if (success) {
s_logger.debug("Deleted snapshotsDir for volume: " + volumeId + " under account: " + accountId);
} else if (answer != null) {
s_logger.error(answer.getDetails());
// SnapshotsDir has been deleted for the volumes so far.
success = (answer != null) && answer.getResult();
if (success) {
s_logger.debug("Deleted snapshotsDir for volume: " + volumeId + " under account: " + accountId);
} else if (answer != null) {
s_logger.error(answer.getDetails());
}
}
}

View File

@ -39,4 +39,5 @@ public interface SecondaryStorageVmDao extends GenericDao<SecondaryStorageVmVO,
public List<Long> getRunningSecStorageVmListByMsid(SecondaryStorageVm.Role role, long msid);
public List<Long> listRunningSecStorageOrderByLoad(SecondaryStorageVm.Role role, long zoneId);
SecondaryStorageVmVO findByInstanceName(String instanceName);
}

View File

@ -47,7 +47,8 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase<SecondaryStorageVm
protected SearchBuilder<SecondaryStorageVmVO> LastHostSearch;
protected SearchBuilder<SecondaryStorageVmVO> HostUpSearch;
protected SearchBuilder<SecondaryStorageVmVO> ZoneSearch;
protected SearchBuilder<SecondaryStorageVmVO> StateChangeSearch;
protected SearchBuilder<SecondaryStorageVmVO> StateChangeSearch;
protected SearchBuilder<SecondaryStorageVmVO> InstanceSearch;
protected final Attribute _updateTimeAttr;
@ -68,6 +69,10 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase<SecondaryStorageVm
HostSearch.and("role", HostSearch.entity().getRole(), SearchCriteria.Op.EQ);
HostSearch.done();
InstanceSearch = createSearchBuilder();
InstanceSearch.and("instanceName", InstanceSearch.entity().getInstanceName(), SearchCriteria.Op.EQ);
InstanceSearch.done();
LastHostSearch = createSearchBuilder();
LastHostSearch.and("lastHost", LastHostSearch.entity().getLastHostId(), SearchCriteria.Op.EQ);
LastHostSearch.and("state", LastHostSearch.entity().getState(), SearchCriteria.Op.EQ);
@ -186,6 +191,19 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase<SecondaryStorageVm
}
return l;
}
@Override
public SecondaryStorageVmVO findByInstanceName(String instanceName) {
SearchCriteria<SecondaryStorageVmVO> sc = InstanceSearch.create();
sc.setParameters("instanceName", instanceName);
List<SecondaryStorageVmVO> list = listBy(sc);
if( list == null ) {
return null;
} else {
return list.get(0);
}
}
@Override
public List<SecondaryStorageVmVO> listByZoneId(SecondaryStorageVm.Role role, long zoneId) {

View File

@ -410,6 +410,7 @@ CREATE TABLE `cloud`.`snapshots` (
`backup_snap_id` varchar(255) COMMENT 'Back up uuid of the snapshot',
`swift_id` bigint unsigned COMMENT 'which swift',
`swift_name` varchar(255) COMMENT 'Back up name in swift',
`sechost_id` bigint unsigned COMMENT 'secondary storage host id',
`prev_snap_id` bigint unsigned COMMENT 'Id of the most recent snapshot',
`hypervisor_type` varchar(32) NOT NULL COMMENT 'hypervisor that the snapshot was taken under',
`version` varchar(32) COMMENT 'snapshot version',