diff --git a/api/src/com/cloud/agent/api/SecStorageSetupCommand.java b/api/src/com/cloud/agent/api/SecStorageSetupCommand.java
index 1c15eb8087d..73a9d4e350b 100644
--- a/api/src/com/cloud/agent/api/SecStorageSetupCommand.java
+++ b/api/src/com/cloud/agent/api/SecStorageSetupCommand.java
@@ -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;
+ }
}
diff --git a/api/src/com/cloud/agent/api/SecStorageVMSetupCommand.java b/api/src/com/cloud/agent/api/SecStorageVMSetupCommand.java
new file mode 100644
index 00000000000..57755ced82b
--- /dev/null
+++ b/api/src/com/cloud/agent/api/SecStorageVMSetupCommand.java
@@ -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 .
+ *
+ */
+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;
+ }
+
+}
diff --git a/api/src/com/cloud/agent/api/StartupSecondaryStorageCommand.java b/api/src/com/cloud/agent/api/StartupSecondaryStorageCommand.java
new file mode 100644
index 00000000000..6fbf34e1b13
--- /dev/null
+++ b/api/src/com/cloud/agent/api/StartupSecondaryStorageCommand.java
@@ -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 .
+ *
+ */
+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;
+ }
+}
diff --git a/api/src/com/cloud/agent/api/StartupStorageCommand.java b/api/src/com/cloud/agent/api/StartupStorageCommand.java
index 65137528d88..5fabd64e66f 100755
--- a/api/src/com/cloud/agent/api/StartupStorageCommand.java
+++ b/api/src/com/cloud/agent/api/StartupStorageCommand.java
@@ -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;
}
diff --git a/api/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java b/api/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java
index 135dc80a33d..da008458af2 100644
--- a/api/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java
+++ b/api/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java
@@ -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() {
diff --git a/api/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java b/api/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java
index 5d09d3dd9d8..16efb3f83f9 100644
--- a/api/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java
+++ b/api/src/com/cloud/agent/api/storage/DeleteTemplateCommand.java
@@ -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;
}
-
}
diff --git a/api/src/com/cloud/agent/api/storage/DownloadCommand.java b/api/src/com/cloud/agent/api/storage/DownloadCommand.java
index 700eb0e40a4..17a1f87887b 100644
--- a/api/src/com/cloud/agent/api/storage/DownloadCommand.java
+++ b/api/src/com/cloud/agent/api/storage/DownloadCommand.java
@@ -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;
}
diff --git a/api/src/com/cloud/agent/api/storage/ListTemplateAnswer.java b/api/src/com/cloud/agent/api/storage/ListTemplateAnswer.java
new file mode 100644
index 00000000000..cba3c1f3217
--- /dev/null
+++ b/api/src/com/cloud/agent/api/storage/ListTemplateAnswer.java
@@ -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 .
+ *
+ */
+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 templateInfos;
+
+ public ListTemplateAnswer() {
+
+ }
+
+ public ListTemplateAnswer(String secUrl, Map templateInfos) {
+ super(null, true, "success");
+ this.setSecUrl(secUrl);
+ this.templateInfos = templateInfos;
+ }
+
+ public Map getTemplateInfo() {
+ return templateInfos;
+ }
+
+ public void setTemplateInfo(Map templateInfos) {
+ this.templateInfos = templateInfos;
+ }
+
+ public void setSecUrl(String secUrl) {
+ this.secUrl = secUrl;
+ }
+
+ public String getSecUrl() {
+ return secUrl;
+ }
+}
diff --git a/api/src/com/cloud/agent/api/storage/ListTemplateCommand.java b/api/src/com/cloud/agent/api/storage/ListTemplateCommand.java
new file mode 100644
index 00000000000..ea9200e7033
--- /dev/null
+++ b/api/src/com/cloud/agent/api/storage/ListTemplateCommand.java
@@ -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 .
+ *
+ */
+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;
+ }
+
+}
diff --git a/api/src/com/cloud/agent/api/storage/ssCommand.java b/api/src/com/cloud/agent/api/storage/ssCommand.java
new file mode 100644
index 00000000000..e99fe74e6f6
--- /dev/null
+++ b/api/src/com/cloud/agent/api/storage/ssCommand.java
@@ -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 .
+ *
+ */
+
+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;
+ }
+
+}
diff --git a/api/src/com/cloud/host/Host.java b/api/src/com/cloud/host/Host.java
index 69b3cccc8db..280ad33d72b 100755
--- a/api/src/com/cloud/host/Host.java
+++ b/api/src/com/cloud/host/Host.java
@@ -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;
diff --git a/api/src/com/cloud/storage/Storage.java b/api/src/com/cloud/storage/Storage.java
index 66b4c1c0a8e..91213fa1f30 100644
--- a/api/src/com/cloud/storage/Storage.java
+++ b/api/src/com/cloud/storage/Storage.java
@@ -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}
}
diff --git a/core/src/com/cloud/storage/SnapshotVO.java b/core/src/com/cloud/storage/SnapshotVO.java
index 8e476007d7e..287c554d1ef 100644
--- a/core/src/com/cloud/storage/SnapshotVO.java
+++ b/core/src/com/cloud/storage/SnapshotVO.java
@@ -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;
}
diff --git a/core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java
index a19c2de700a..0833279caa7 100644
--- a/core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java
+++ b/core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java
@@ -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());
}
+ @Override
+ public String getRootDir(ssCommand cmd){
+ return null;
+
+ }
+
@Override
@SuppressWarnings("unchecked")
public boolean configure(String name, Map 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 tInfo = _dlMgr.gatherTemplateInfo();
- cmd.setTemplateInfo(tInfo);
-
+
return new StartupCommand [] {cmd};
}
diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
index 52a6a1473d5..72156a04121 100755
--- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
+++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
@@ -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 _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 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 res = new ArrayList();
+ 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());
-
- 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 tInfo = new HashMap();
- 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) {
diff --git a/core/src/com/cloud/storage/resource/SecondaryStorageResource.java b/core/src/com/cloud/storage/resource/SecondaryStorageResource.java
new file mode 100755
index 00000000000..61b730d0990
--- /dev/null
+++ b/core/src/com/cloud/storage/resource/SecondaryStorageResource.java
@@ -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 .
+ *
+ */
+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);
+
+}
diff --git a/core/src/com/cloud/storage/template/DownloadManager.java b/core/src/com/cloud/storage/template/DownloadManager.java
index e3838f4f95c..e13894dd9e5 100644
--- a/core/src/com/cloud/storage/template/DownloadManager.java
+++ b/core/src/com/cloud/storage/template/DownloadManager.java
@@ -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 listPublicTemplates();
/**
/**
* @return list of template info for installed templates
*/
- public Map gatherTemplateInfo();
-
- public String getPublicTemplateRepo();
-
+ public Map gatherTemplateInfo(String templateDir);
}
\ No newline at end of file
diff --git a/core/src/com/cloud/storage/template/DownloadManagerImpl.java b/core/src/com/cloud/storage/template/DownloadManagerImpl.java
index f141a2610e9..4a37f6e5100 100755
--- a/core/src/com/cloud/storage/template/DownloadManagerImpl.java
+++ b/core/src/com/cloud/storage/template/DownloadManagerImpl.java
@@ -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 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 listPublicTemplates() {
- return listTemplates(publicTemplateRepo);
- }
-
private List listTemplates(String rootdir) {
List result = new ArrayList();
Script script = new Script(listTmpltScr, s_logger);
@@ -631,9 +613,10 @@ public class DownloadManagerImpl implements DownloadManager {
}
@Override
- public Map gatherTemplateInfo() {
+ public Map gatherTemplateInfo(String rootDir) {
Map result = new HashMap();
- List publicTmplts = listPublicTemplates();
+ String templateDir = rootDir + File.separator + _templateDir;
+ List 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("VMDK Processor", VmdkProcessor.class, processor));
_processors = new Adapters("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 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;
- }
}
}
diff --git a/core/src/com/cloud/storage/template/UploadManager.java b/core/src/com/cloud/storage/template/UploadManager.java
index d06cb6bd35e..4745bfbcfd2 100755
--- a/core/src/com/cloud/storage/template/UploadManager.java
+++ b/core/src/com/cloud/storage/template/UploadManager.java
@@ -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();
diff --git a/core/src/com/cloud/storage/template/UploadManagerImpl.java b/core/src/com/cloud/storage/template/UploadManagerImpl.java
index 10b2a3fecdf..4dd2269cbe1 100755
--- a/core/src/com/cloud/storage/template/UploadManagerImpl.java
+++ b/core/src/com/cloud/storage/template/UploadManagerImpl.java
@@ -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);
diff --git a/server/src/com/cloud/agent/AgentManager.java b/server/src/com/cloud/agent/AgentManager.java
index cda55e06791..ac85a36f189 100755
--- a/server/src/com/cloud/agent/AgentManager.java
+++ b/server/src/com/cloud/agent/AgentManager.java
@@ -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);
}
diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java
index 1550b30b5b4..1e06f546353 100755
--- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java
+++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java
@@ -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 result = new ArrayList();
+
+ 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 details = new HashMap();
+ 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 hosts = new ArrayList();
+ Map extends ServerResource, Map> 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> 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 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 hostTags = cmd.getHostTags();
+ Map bareMetalParams = new HashMap();
+
+ 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 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 discoverHosts(Long dcId, Long podId, Long clusterId, String clusterName, String url, String username, String password, String hypervisorType, List hostTags)
+ throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException {
+ return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, hypervisorType, hostTags, null, null);
+ }
+
+ private List discoverHostsFull(Long dcId, Long podId, Long clusterId, String clusterName, String url, String username, String password, String hypervisorType, List hostTags,
+ Map 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 hosts = new ArrayList();
+ s_logger.info("Trying to add a new host at " + url + " in data center " + dcId);
+ Enumeration 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> 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> 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 details = entry.getValue();
+ String guid = details.get("guid");
+ List 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 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 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 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 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) {
diff --git a/server/src/com/cloud/host/dao/HostDao.java b/server/src/com/cloud/host/dao/HostDao.java
index 663376ca143..54f2214c4a1 100644
--- a/server/src/com/cloud/host/dao/HostDao.java
+++ b/server/src/com/cloud/host/dao/HostDao.java
@@ -169,4 +169,8 @@ public interface HostDao extends GenericDao {
boolean directConnect(HostVO host, long msId, boolean secondConnect);
HostVO findTrafficMonitorHost();
+
+ List listLocalSecondaryStorageHosts();
+
+ List listLocalSecondaryStorageHosts(long dataCenterId);
}
diff --git a/server/src/com/cloud/host/dao/HostDaoImpl.java b/server/src/com/cloud/host/dao/HostDaoImpl.java
index 569ac3888cd..75f11285b12 100644
--- a/server/src/com/cloud/host/dao/HostDaoImpl.java
+++ b/server/src/com/cloud/host/dao/HostDaoImpl.java
@@ -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 implements HostDao
}
@Override
- public HostVO findSecondaryStorageHost(long dcId) {
- SearchCriteria sc = TypeDcSearch.create();
- sc.setParameters("type", Host.Type.SecondaryStorage);
- sc.setParameters("dc", dcId);
- List storageHosts = listBy(sc);
-
- if (storageHosts == null || storageHosts.size() < 1) {
- return null;
- } else {
- return storageHosts.get(0);
- }
+ public HostVO findSecondaryStorageHost(long dcId) {
+ SearchCriteria sc = TypeDcSearch.create();
+ sc.setParameters("type", Host.Type.SecondaryStorage);
+ sc.setParameters("dc", dcId);
+ List storageHosts = listBy(sc);
+ if (storageHosts == null || storageHosts.size() < 1) {
+ return null;
+ } else {
+ Collections.shuffle(storageHosts);
+ return storageHosts.get(0);
+ }
}
@Override
public List listSecondaryStorageHosts() {
- SearchCriteria sc = TypeSearch.create();
- sc.setParameters("type", Host.Type.SecondaryStorage);
- List secondaryStorageHosts = listIncludingRemovedBy(sc);
-
- return secondaryStorageHosts;
- }
-
+ SearchCriteria sc = createSearchCriteria();
+ sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.SecondaryStorage);
+ return search(sc, null);
+ }
+
+ @Override
+ public List listSecondaryStorageHosts(long dataCenterId) {
+ SearchCriteria 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 listLocalSecondaryStorageHosts() {
+ SearchCriteria sc = createSearchCriteria();
+ sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.LocalSecondaryStorage);
+ return search(sc, null);
+ }
+
+ @Override
+ public List listLocalSecondaryStorageHosts(long dataCenterId) {
+ SearchCriteria 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 findDirectlyConnectedHosts() {
SearchCriteria sc = DirectlyConnectedSearch.create();
diff --git a/server/src/com/cloud/server/StatsCollector.java b/server/src/com/cloud/server/StatsCollector.java
index 404eda7124a..2059b81aff0 100755
--- a/server/src/com/cloud/server/StatsCollector.java
+++ b/server/src/com/cloud/server/StatsCollector.java
@@ -248,17 +248,11 @@ public class StatsCollector {
class StorageCollector implements Runnable {
@Override
public void run() {
- try {
- SearchCriteria sc = _hostDao.createSearchCriteria();
- ConcurrentHashMap storageStats = new ConcurrentHashMap();
- List 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 hosts = _hostDao.listSecondaryStorageHosts();
+ ConcurrentHashMap storageStats = new ConcurrentHashMap();
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()) {
diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java
index 2ae4c8c8867..41a7be9338c 100755
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@ -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 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()));
diff --git a/server/src/com/cloud/storage/dao/SnapshotDao.java b/server/src/com/cloud/storage/dao/SnapshotDao.java
index e5731b00359..e88cb60db7f 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDao.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDao.java
@@ -35,5 +35,6 @@ public interface SnapshotDao extends GenericDao {
List listByBackupUuid(long volumeId, String backupUuid);
long updateSnapshotVersion(long volumeId, String from, String to);
List listByVolumeIdVersion(long volumeId, String version);
+ Long getSecHostId(long volumeId);
}
diff --git a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
index fce66e1c66f..2cc8efce3f9 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
@@ -39,6 +39,7 @@ public class SnapshotDaoImpl extends GenericDaoBase 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 VolumeIdSearch;
private final SearchBuilder VolumeIdTypeSearch;
@@ -129,6 +130,23 @@ public class SnapshotDaoImpl extends GenericDaoBase 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();
diff --git a/server/src/com/cloud/storage/download/DownloadListener.java b/server/src/com/cloud/storage/download/DownloadListener.java
index 152ee474cd4..1ecf2de530f 100644
--- a/server/src/com/cloud/storage/download/DownloadListener.java
+++ b/server/src/com/cloud/storage/download/DownloadListener.java
@@ -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());
}
}
diff --git a/server/src/com/cloud/storage/download/DownloadMonitor.java b/server/src/com/cloud/storage/download/DownloadMonitor.java
index dd5dbe67094..db62749a7c0 100644
--- a/server/src/com/cloud/storage/download/DownloadMonitor.java
+++ b/server/src/com/cloud/storage/download/DownloadMonitor.java
@@ -38,7 +38,7 @@ public interface DownloadMonitor extends Manager{
public void cancelAllDownloads(Long templateId);
- public void handleTemplateSync(long id, Map 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 templateInfos);
+
}
\ No newline at end of file
diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java
index 278ce402fff..56751b7cc66 100755
--- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java
+++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java
@@ -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 _listenerMap = new ConcurrentHashMap();
-
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 dcs = new ArrayList();
-
- 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 dcs = new ArrayList();
+ if (zoneId == null) {
+ dcs.addAll(_dcDao.listAll());
+ } else {
+ dcs.add(_dcDao.findById(zoneId));
+ }
+ for ( DataCenterVO dc : dcs ) {
+ List 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 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 rtngTmplts = _templateDao.listAllSystemVMTemplates();
+ List 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 templateInfos){
+ if ( templateInfos == null ) {
+ return;
+ }
+ Long hostId = host.getId();
List rtngTmplts = _templateDao.listAllSystemVMTemplates();
- List 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 ssHosts = _hostDao.listSecondaryStorageHosts(dcId);
+ for ( HostVO ssHost : ssHosts ) {
+ Long hostId = ssHost.getId();
+ List ths = _vmTemplateHostDao.listByHostId(hostId);
+ Map templateInfos = new HashMap();
+ for ( VMTemplateHostVO th : ths ) {
+ String tname = _templateDao.findById(th.getTemplateId()).getUniqueName();
+ templateInfos.put(tname, null);
+ }
+ handleTemplateSync(ssHost);
+ }
+ }
+
+ private Map 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 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 templateInfos = listTemplate(ssHost);
+ if( templateInfos == null ) {
+ return;
+ }
+ long zoneId = ssHost.getDataCenterId();
Set toBeDownloaded = new HashSet();
- List allTemplates = _templateDao.listAllInZone(storageHost.getDataCenterId());
+ List allTemplates = _templateDao.listAllInZone(ssHost.getDataCenterId());
List rtngTmplts = _templateDao.listAllSystemVMTemplates();
List 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 availHypers = _clusterDao.getAvailableHypervisorInZone(sserver.getDataCenterId());
+ List 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);
diff --git a/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java b/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java
index f4ff10e4c71..4e654d92129 100644
--- a/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java
+++ b/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java
@@ -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);
}
diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java b/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java
index 6822c3be3c9..bcc3e9259cf 100644
--- a/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java
+++ b/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java
@@ -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
diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
index 4b99781517b..4700af2dfc7 100644
--- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
+++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
@@ -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 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 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 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 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 allowedCidrs = new ArrayList();
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 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 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 scanPool(Long pool) {
long dataCenterId = pool.longValue();
- List alreadyRunning = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running, State.Migrating,
- State.Starting);
- List 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.expand, SecondaryStorageVm.Role.templateProcessor);
- } else {
- s_logger.warn("Stopped secondary storage vms found in datacenter id=" + dataCenterId + ", not restarting them automatically");
- }
+ List 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 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.expand, SecondaryStorageVm.Role.templateProcessor);
}
return new Pair(AfterScanAction.nop, SecondaryStorageVm.Role.templateProcessor);
diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java b/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java
index abb9b6946c7..885ba5c14ce 100644
--- a/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java
+++ b/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java
@@ -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 assignSecStorageVm(long zoneId, Command cmd);
+ public Pair assignSecStorageVm(long zoneId, Command cmd);
+ boolean generateSetupCommand(Long hostId);
}
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManager.java b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
index ff8b5035d7f..fdf16a17388 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManager.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
@@ -130,4 +130,6 @@ public interface SnapshotManager {
List listSnapsforPolicy(long policyId, Filter filter);
void downloadSnapshotsFromSwift(SnapshotVO ss);
+
+ String getSecondaryStorageURL(SnapshotVO snapshot);
}
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index 81f19f9197b..61bd6e2ae89 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -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 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());
+ }
}
}
diff --git a/server/src/com/cloud/vm/dao/SecondaryStorageVmDao.java b/server/src/com/cloud/vm/dao/SecondaryStorageVmDao.java
index 352afbffd83..b085b85a818 100644
--- a/server/src/com/cloud/vm/dao/SecondaryStorageVmDao.java
+++ b/server/src/com/cloud/vm/dao/SecondaryStorageVmDao.java
@@ -39,4 +39,5 @@ public interface SecondaryStorageVmDao extends GenericDao getRunningSecStorageVmListByMsid(SecondaryStorageVm.Role role, long msid);
public List listRunningSecStorageOrderByLoad(SecondaryStorageVm.Role role, long zoneId);
+ SecondaryStorageVmVO findByInstanceName(String instanceName);
}
diff --git a/server/src/com/cloud/vm/dao/SecondaryStorageVmDaoImpl.java b/server/src/com/cloud/vm/dao/SecondaryStorageVmDaoImpl.java
index dfb5432e53d..3d33a4b8704 100644
--- a/server/src/com/cloud/vm/dao/SecondaryStorageVmDaoImpl.java
+++ b/server/src/com/cloud/vm/dao/SecondaryStorageVmDaoImpl.java
@@ -47,7 +47,8 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase LastHostSearch;
protected SearchBuilder HostUpSearch;
protected SearchBuilder ZoneSearch;
- protected SearchBuilder StateChangeSearch;
+ protected SearchBuilder StateChangeSearch;
+ protected SearchBuilder InstanceSearch;
protected final Attribute _updateTimeAttr;
@@ -68,6 +69,10 @@ public class SecondaryStorageVmDaoImpl extends GenericDaoBase sc = InstanceSearch.create();
+ sc.setParameters("instanceName", instanceName);
+ List list = listBy(sc);
+ if( list == null ) {
+ return null;
+ } else {
+ return list.get(0);
+ }
+ }
@Override
public List listByZoneId(SecondaryStorageVm.Role role, long zoneId) {
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index ae89dcad923..d7f31a7df72 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -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',