// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.storage.resource;
import static com.cloud.utils.S3Utils.deleteDirectory;
import static com.cloud.utils.S3Utils.getDirectory;
import static com.cloud.utils.S3Utils.putDirectory;
import static com.cloud.utils.StringUtils.join;
import static com.cloud.utils.db.GlobalLock.executeWithNoWaitLock;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static org.apache.commons.lang.StringUtils.substringAfterLast;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.URI;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckHealthAnswer;
import com.cloud.agent.api.CheckHealthCommand;
import com.cloud.agent.api.CleanupSnapshotBackupCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.ComputeChecksumCommand;
import com.cloud.agent.api.DeleteObjectFromSwiftCommand;
import com.cloud.agent.api.DeleteSnapshotBackupCommand;
import com.cloud.agent.api.DeleteSnapshotsDirCommand;
import com.cloud.agent.api.DeleteTemplateFromS3Command;
import com.cloud.agent.api.DownloadSnapshotFromS3Command;
import com.cloud.agent.api.DownloadTemplateFromS3ToSecondaryStorageCommand;
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.SecStorageFirewallCfgCommand;
import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig;
import com.cloud.agent.api.SecStorageSetupAnswer;
import com.cloud.agent.api.SecStorageSetupCommand;
import com.cloud.agent.api.SecStorageSetupCommand.Certificates;
import com.cloud.agent.api.SecStorageVMSetupCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.UploadTemplateToS3FromSecondaryStorageCommand;
import com.cloud.agent.api.downloadSnapshotFromSwiftCommand;
import com.cloud.agent.api.downloadTemplateFromSwiftToSecondaryStorageCommand;
import com.cloud.agent.api.uploadTemplateToSwiftFromSecondaryStorageCommand;
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.DeleteVolumeCommand;
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.ListVolumeAnswer;
import com.cloud.agent.api.storage.ListVolumeCommand;
import com.cloud.agent.api.storage.UploadCommand;
import com.cloud.agent.api.storage.ssCommand;
import com.cloud.agent.api.to.S3TO;
import com.cloud.agent.api.to.SwiftTO;
import com.cloud.exception.InternalErrorException;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResourceBase;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.template.DownloadManager;
import com.cloud.storage.template.DownloadManagerImpl;
import com.cloud.storage.template.DownloadManagerImpl.ZfsPathParser;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.storage.template.TemplateLocation;
import com.cloud.storage.template.UploadManager;
import com.cloud.storage.template.UploadManagerImpl;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.S3Utils;
import com.cloud.utils.S3Utils.FileNamingStrategy;
import com.cloud.utils.S3Utils.ObjectNamingStrategy;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
import com.cloud.vm.SecondaryStorageVm;
public class NfsSecondaryStorageResource extends ServerResourceBase implements
SecondaryStorageResource {
private static final Logger s_logger = Logger
.getLogger(NfsSecondaryStorageResource.class);
private static final String TEMPLATE_ROOT_DIR = "template/tmpl";
private static final String SNAPSHOT_ROOT_DIR = "snapshots";
int _timeout;
String _instance;
String _dc;
String _pod;
String _guid;
String _role;
Map<String, Object> _params;
StorageLayer _storage;
boolean _inSystemVM = false;
boolean _sslCopy = false;
DownloadManager _dlMgr;
UploadManager _upldMgr;
private String _configSslScr;
private String _configAuthScr;
private String _configIpFirewallScr;
private String _publicIp;
private String _hostname;
private String _localgw;
private String _eth1mask;
private String _eth1ip;
private String _storageIp;
private String _storageNetmask;
private String _storageGateway;
private final List<String> nfsIps = new ArrayList<String>();
final private String _parent = "/mnt/SecStorage";
final private String _tmpltDir = "/var/cloudstack/template";
final private String _tmpltpp = "template.properties";
@Override
public void disconnected() {
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof DownloadProgressCommand) {
return _dlMgr.handleDownloadCommand(this, (DownloadProgressCommand)cmd);
} else if (cmd instanceof DownloadCommand) {
return _dlMgr.handleDownloadCommand(this, (DownloadCommand)cmd);
} else if (cmd instanceof UploadCommand) {
return _upldMgr.handleUploadCommand(this, (UploadCommand)cmd);
} else if (cmd instanceof CreateEntityDownloadURLCommand){
return _upldMgr.handleCreateEntityURLCommand((CreateEntityDownloadURLCommand)cmd);
} else if(cmd instanceof DeleteEntityDownloadURLCommand){
return _upldMgr.handleDeleteEntityDownloadURLCommand((DeleteEntityDownloadURLCommand)cmd);
} else if (cmd instanceof GetStorageStatsCommand) {
return execute((GetStorageStatsCommand)cmd);
} else if (cmd instanceof CheckHealthCommand) {
return new CheckHealthAnswer((CheckHealthCommand)cmd, true);
} else if (cmd instanceof DeleteTemplateCommand) {
return execute((DeleteTemplateCommand) cmd);
} else if (cmd instanceof DeleteVolumeCommand) {
return execute((DeleteVolumeCommand) cmd);
}else if (cmd instanceof ReadyCommand) {
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);
} else if (cmd instanceof ComputeChecksumCommand){
return execute((ComputeChecksumCommand)cmd);
} else if (cmd instanceof ListTemplateCommand){
return execute((ListTemplateCommand)cmd);
} else if (cmd instanceof ListVolumeCommand){
return execute((ListVolumeCommand)cmd);
}else if (cmd instanceof downloadSnapshotFromSwiftCommand){
return execute((downloadSnapshotFromSwiftCommand)cmd);
} else if (cmd instanceof DownloadSnapshotFromS3Command) {
return execute((DownloadSnapshotFromS3Command) cmd);
} else if (cmd instanceof DeleteSnapshotBackupCommand){
return execute((DeleteSnapshotBackupCommand)cmd);
} else if (cmd instanceof DeleteSnapshotsDirCommand){
return execute((DeleteSnapshotsDirCommand)cmd);
} else if (cmd instanceof downloadTemplateFromSwiftToSecondaryStorageCommand) {
return execute((downloadTemplateFromSwiftToSecondaryStorageCommand) cmd);
} else if (cmd instanceof DownloadTemplateFromS3ToSecondaryStorageCommand) {
return execute((DownloadTemplateFromS3ToSecondaryStorageCommand) cmd);
} else if (cmd instanceof uploadTemplateToSwiftFromSecondaryStorageCommand) {
return execute((uploadTemplateToSwiftFromSecondaryStorageCommand) cmd);
} else if (cmd instanceof UploadTemplateToS3FromSecondaryStorageCommand) {
return execute((UploadTemplateToS3FromSecondaryStorageCommand) cmd);
} else if (cmd instanceof DeleteObjectFromSwiftCommand) {
return execute((DeleteObjectFromSwiftCommand) cmd);
} else if (cmd instanceof DeleteTemplateFromS3Command) {
return execute((DeleteTemplateFromS3Command) cmd);
} else if (cmd instanceof CleanupSnapshotBackupCommand){
return execute((CleanupSnapshotBackupCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
@SuppressWarnings("unchecked")
private String determineS3TemplateDirectory(final Long accountId,
final Long templateId) {
return join(asList(TEMPLATE_ROOT_DIR, accountId, templateId),
S3Utils.SEPARATOR);
}
@SuppressWarnings("unchecked")
private String determineStorageTemplatePath(final String storagePath,
final Long accountId, final Long templateId) {
return join(
asList(getRootDir(storagePath), TEMPLATE_ROOT_DIR, accountId,
templateId), File.separator);
}
private Answer execute(
final DownloadTemplateFromS3ToSecondaryStorageCommand cmd) {
final S3TO s3 = cmd.getS3();
final String storagePath = cmd.getStoragePath();
final Long accountId = cmd.getAccountId();
final Long templateId = cmd.getTemplateId();
try {
final File downloadDirectory = _storage
.getFile(determineStorageTemplatePath(storagePath,
accountId, templateId));
downloadDirectory.mkdirs();
if (!downloadDirectory.exists()) {
final String errMsg = format(
"Unable to create directory "
+ "download directory %1$s for download of template id "
+ "%2$s from S3.", downloadDirectory.getName(),
templateId);
s_logger.error(errMsg);
return new Answer(cmd, false, errMsg);
}
getDirectory(s3, s3.getBucketName(),
determineS3TemplateDirectory(accountId, templateId),
downloadDirectory, new FileNamingStrategy() {
@Override
public String determineFileName(final String key) {
return substringAfterLast(key, S3Utils.SEPARATOR);
}
});
return new Answer(cmd, true, format("Successfully downloaded "
+ "template id %1$s from S3 to directory %2$s", templateId,
downloadDirectory.getName()));
} catch (Exception e) {
final String errMsg = format("Failed to upload template id %1$s "
+ "due to $2%s", templateId, e.getMessage());
s_logger.error(errMsg, e);
return new Answer(cmd, false, errMsg);
}
}
private Answer execute(downloadTemplateFromSwiftToSecondaryStorageCommand cmd) {
SwiftTO swift = cmd.getSwift();
String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
Long accountId = cmd.getAccountId();
Long templateId = cmd.getTemplateId();
String path = cmd.getPath();
String errMsg;
String lDir = null;
try {
String parent = getRootDir(secondaryStorageUrl);
lDir = parent + "/template/tmpl/" + accountId.toString() + "/" + templateId.toString();
String result = createLocalDir(lDir);
if (result != null) {
errMsg = "downloadTemplateFromSwiftToSecondaryStorageCommand failed due to Create local directory failed";
s_logger.warn(errMsg);
throw new InternalErrorException(errMsg);
}
String lPath = lDir + "/" + path;
result = swiftDownload(swift, "T-" + templateId.toString(), path, lPath);
if (result != null) {
errMsg = "failed to download template " + path + " from Swift to secondary storage " + lPath + " , err=" + result;
s_logger.warn(errMsg);
throw new CloudRuntimeException(errMsg);
}
path = "template.properties";
lPath = lDir + "/" + path;
result = swiftDownload(swift, "T-" + templateId.toString(), path, lPath);
if (result != null) {
errMsg = "failed to download template " + path + " from Swift to secondary storage " + lPath + " , err=" + result;
s_logger.warn(errMsg);
throw new CloudRuntimeException(errMsg);
}
return new Answer(cmd, true, "success");
} catch (Exception e) {
if (lDir != null) {
deleteLocalDir(lDir);
}
errMsg = cmd + " Command failed due to " + e.toString();
s_logger.warn(errMsg, e);
return new Answer(cmd, false, errMsg);
}
}
private Answer execute(uploadTemplateToSwiftFromSecondaryStorageCommand cmd) {
SwiftTO swift = cmd.getSwift();
String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
Long accountId = cmd.getAccountId();
Long templateId = cmd.getTemplateId();
try {
String parent = getRootDir(secondaryStorageUrl);
String lPath = parent + "/template/tmpl/" + accountId.toString() + "/" + templateId.toString();
if (!_storage.isFile(lPath + "/template.properties")) {
String errMsg = cmd + " Command failed due to template doesn't exist ";
s_logger.debug(errMsg);
return new Answer(cmd, false, errMsg);
}
String result = swiftUpload(swift, "T-" + templateId.toString(), lPath, "*");
if (result != null) {
String errMsg = "failed to upload template from secondary storage " + lPath + " to swift , err=" + result;
s_logger.debug(errMsg);
return new Answer(cmd, false, errMsg);
}
return new Answer(cmd, true, "success");
} catch (Exception e) {
String errMsg = cmd + " Command failed due to " + e.toString();
s_logger.warn(errMsg, e);
return new Answer(cmd, false, errMsg);
}
}
private Answer execute(UploadTemplateToS3FromSecondaryStorageCommand cmd) {
final S3TO s3 = cmd.getS3();
final Long accountId = cmd.getAccountId();
final Long templateId = cmd.getTemplateId();
try {
final String templatePath = determineStorageTemplatePath(
cmd.getStoragePath(), accountId, templateId);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Found template id " + templateId
+ " account id " + accountId + " from directory "
+ templatePath + " to upload to S3.");
}
if (!_storage.isDirectory(templatePath)) {
final String errMsg = format("S3 Sync Failure: Directory %1$s"
+ "for template id %2$s does not exist.", templatePath,
templateId);
s_logger.error(errMsg);
return new Answer(cmd, false, errMsg);
}
if (!_storage.isFile(templatePath + "/template.properties")) {
final String errMsg = format("S3 Sync Failure: Template id "
+ "%1$s does not exist on the file system.",
templatePath);
s_logger.error(errMsg);
return new Answer(cmd, false, errMsg);
}
if (s_logger.isDebugEnabled()) {
s_logger.debug(format(
"Pushing template id %1$s from %2$s to S3...",
templateId, templatePath));
}
final String bucket = s3.getBucketName();
putDirectory(s3, bucket, _storage.getFile(templatePath),
new FilenameFilter() {
@Override
public boolean accept(final File directory,
final String fileName) {
File fileToUpload = new File(directory.getAbsolutePath() + "/" + fileName);
return !fileName.startsWith(".") && !fileToUpload.isDirectory();
}
}, new ObjectNamingStrategy() {
@Override
public String determineKey(final File file) {
s_logger.debug(String
.format("Determining key using account id %1$s and template id %2$s",
accountId, templateId));
return join(
asList(determineS3TemplateDirectory(
accountId, templateId), file
.getName()), S3Utils.SEPARATOR);
}
});
return new Answer(
cmd,
true,
format("Uploaded the contents of directory %1$s for template id %2$s to S3 bucket %3$s",
templatePath, templateId, bucket));
} catch (Exception e) {
final String errMsg = format("Failed to upload template id %1$s",
templateId);
s_logger.error(errMsg, e);
return new Answer(cmd, false, errMsg);
}
}
private Answer execute(DeleteObjectFromSwiftCommand cmd) {
SwiftTO swift = cmd.getSwift();
String container = cmd.getContainer();
String object = cmd.getObject();
if (object == null) {
object = "";
}
try {
String result = swiftDelete(swift, container, object);
if (result != null) {
String errMsg = "failed to delete object " + container + "/" + object + " , err=" + result;
s_logger.warn(errMsg);
return new Answer(cmd, false, errMsg);
}
return new Answer(cmd, true, "success");
} catch (Exception e) {
String errMsg = cmd + " Command failed due to " + e.toString();
s_logger.warn(errMsg, e);
return new Answer(cmd, false, errMsg);
}
}
private Answer execute(final DeleteTemplateFromS3Command cmd) {
final S3TO s3 = cmd.getS3();
final Long accountId = cmd.getAccountId();
final Long templateId = cmd.getTemplateId();
if (accountId == null || (accountId != null && accountId <= 0)) {
final String errorMessage = "No account id specified for S3 template deletion.";
s_logger.error(errorMessage);
return new Answer(cmd, false, errorMessage);
}
if (templateId == null || (templateId != null && templateId <= 0)) {
final String errorMessage = "No template id specified for S3 template deletion.";
s_logger.error(errorMessage);
return new Answer(cmd, false, errorMessage);
}
if (s3 == null) {
final String errorMessge = "No S3 client options provided";
s_logger.error(errorMessge);
return new Answer(cmd, false, errorMessge);
}
final String bucket = s3.getBucketName();
try {
deleteDirectory(s3, bucket,
determineS3TemplateDirectory(templateId, accountId));
return new Answer(cmd, true, String.format(
"Deleted template %1%s from bucket %2$s.", templateId,
bucket));
} catch (Exception e) {
final String errorMessage = String
.format("Failed to delete templaet id %1$s from bucket %2$s due to the following error: %3$s",
templateId, bucket, e.getMessage());
s_logger.error(errorMessage, e);
return new Answer(cmd, false, errorMessage);
}
}
String swiftDownload(SwiftTO swift, String container, String rfilename, String lFullPath) {
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A "
+ swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + swift.getKey()
+ " download " + container + " " + rfilename + " -o " + lFullPath);
OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
String result = command.execute(parser);
if (result != null) {
String errMsg = "swiftDownload failed err=" + result;
s_logger.warn(errMsg);
return errMsg;
}
if (parser.getLines() != null) {
String[] lines = parser.getLines().split("\\n");
for (String line : lines) {
if (line.contains("Errno") || line.contains("failed")) {
String errMsg = "swiftDownload failed , err=" + lines.toString();
s_logger.warn(errMsg);
return errMsg;
}
}
}
return null;
}
String swiftDownloadContainer(SwiftTO swift, String container, String ldir) {
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("cd " + ldir + ";/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K "
+ swift.getKey() + " download " + container);
OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
String result = command.execute(parser);
if (result != null) {
String errMsg = "swiftDownloadContainer failed err=" + result;
s_logger.warn(errMsg);
return errMsg;
}
if (parser.getLines() != null) {
String[] lines = parser.getLines().split("\\n");
for (String line : lines) {
if (line.contains("Errno") || line.contains("failed")) {
String errMsg = "swiftDownloadContainer failed , err=" + lines.toString();
s_logger.warn(errMsg);
return errMsg;
}
}
}
return null;
}
String swiftUpload(SwiftTO swift, String container, String lDir, String lFilename) {
long SWIFT_MAX_SIZE = 5L * 1024L * 1024L * 1024L;
List<String> files = new ArrayList<String>();
if (lFilename.equals("*")) {
File dir = new File(lDir);
for (String file : dir.list()) {
if (file.startsWith(".")) {
continue;
}
files.add(file);
}
} else {
files.add(lFilename);
}
for (String file : files) {
File f = new File(lDir + "/" + file);
long size = f.length();
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
if (size <= SWIFT_MAX_SIZE) {
command.add("cd " + lDir + ";/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName()
+ " -K " + swift.getKey() + " upload " + container + " " + file);
} else {
command.add("cd " + lDir + ";/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName()
+ " -K " + swift.getKey() + " upload -S " + SWIFT_MAX_SIZE + " " + container + " " + file);
}
OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
String result = command.execute(parser);
if (result != null) {
String errMsg = "swiftUpload failed , err=" + result;
s_logger.warn(errMsg);
return errMsg;
}
if (parser.getLines() != null) {
String[] lines = parser.getLines().split("\\n");
for (String line : lines) {
if (line.contains("Errno") || line.contains("failed")) {
String errMsg = "swiftUpload failed , err=" + lines.toString();
s_logger.warn(errMsg);
return errMsg;
}
}
}
}
return null;
}
String[] swiftList(SwiftTO swift, String container, String rFilename) {
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K "
+ swift.getKey() + " list " + container + " " + rFilename);
OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
String result = command.execute(parser);
if (result == null && parser.getLines() != null) {
String[] lines = parser.getLines().split("\\n");
return lines;
} else {
if (result != null) {
String errMsg = "swiftList failed , err=" + result;
s_logger.warn(errMsg);
} else {
String errMsg = "swiftList failed, no lines returns";
s_logger.warn(errMsg);
}
}
return null;
}
String swiftDelete(SwiftTO swift, String container, String object) {
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A "
+ swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + swift.getKey()
+ " delete " + container + " " + object);
OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
String result = command.execute(parser);
if (result != null) {
String errMsg = "swiftDelete failed , err=" + result;
s_logger.warn(errMsg);
return errMsg;
}
if (parser.getLines() != null) {
String[] lines = parser.getLines().split("\\n");
for (String line : lines) {
if (line.contains("Errno") || line.contains("failed")) {
String errMsg = "swiftDelete failed , err=" + lines.toString();
s_logger.warn(errMsg);
return errMsg;
}
}
}
return null;
}
public Answer execute(DeleteSnapshotsDirCommand cmd){
String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
Long accountId = cmd.getAccountId();
Long volumeId = cmd.getVolumeId();
try {
String parent = getRootDir(secondaryStorageUrl);
String lPath = parent + "/snapshots/" + String.valueOf(accountId) + "/" + String.valueOf(volumeId) + "/*";
String result = deleteLocalFile(lPath);
if (result != null) {
String errMsg = "failed to delete all snapshots " + lPath + " , err=" + result;
s_logger.warn(errMsg);
return new Answer(cmd, false, errMsg);
}
return new Answer(cmd, true, "success");
} catch (Exception e) {
String errMsg = cmd + " Command failed due to " + e.toString();
s_logger.warn(errMsg, e);
return new Answer(cmd, false, errMsg);
}
}
public Answer execute(final DownloadSnapshotFromS3Command cmd) {
final S3TO s3 = cmd.getS3();
final String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
final Long accountId = cmd.getAccountId();
final Long volumeId = cmd.getVolumeId();
try {
executeWithNoWaitLock(determineSnapshotLockId(accountId, volumeId),
new Callable<Void>() {
@Override
public Void call() throws Exception {
final String directoryName = determineSnapshotLocalDirectory(
secondaryStorageUrl, accountId, volumeId);
String result = createLocalDir(directoryName);
if (result != null) {
throw new InternalErrorException(
format("Failed to create directory %1$s during S3 snapshot download.",
directoryName));
}
final String snapshotFileName = determineSnapshotBackupFilename(cmd
.getSnapshotUuid());
final String key = determineSnapshotS3Key(
accountId, volumeId, snapshotFileName);
final File targetFile = S3Utils.getFile(s3,
s3.getBucketName(), key,
_storage.getFile(directoryName),
new FileNamingStrategy() {
@Override
public String determineFileName(
String key) {
return snapshotFileName;
}
});
if (cmd.getParent() != null) {
final String parentPath = join(
File.pathSeparator, directoryName,
determineSnapshotBackupFilename(cmd
.getParent()));
result = setVhdParent(
targetFile.getAbsolutePath(),
parentPath);
if (result != null) {
throw new InternalErrorException(
format("Failed to set the parent for backup %1$s to %2$s due to %3$s.",
targetFile
.getAbsolutePath(),
parentPath, result));
}
}
return null;
}
});
return new Answer(
cmd,
true,
format("Succesfully retrieved volume id %1$s for account id %2$s to %3$s from S3.",
volumeId, accountId, secondaryStorageUrl));
} catch (Exception e) {
final String errMsg = format(
"Failed to retrieve volume id %1$s for account id %2$s to %3$s from S3 due to exception %4$s",
volumeId, accountId, secondaryStorageUrl, e.getMessage());
s_logger.error(errMsg);
return new Answer(cmd, false, errMsg);
}
}
private String determineSnapshotS3Directory(final Long accountId,
final Long volumeId) {
return join(S3Utils.SEPARATOR, SNAPSHOT_ROOT_DIR, accountId, volumeId);
}
private String determineSnapshotS3Key(final Long accountId,
final Long volumeId, final String snapshotFileName) {
final String directoryName = determineSnapshotS3Directory(accountId,
volumeId);
return join(S3Utils.SEPARATOR, directoryName, snapshotFileName);
}
private String determineSnapshotLocalDirectory(
final String secondaryStorageUrl, final Long accountId,
final Long volumeId) {
return join(File.pathSeparator, getRootDir(secondaryStorageUrl),
SNAPSHOT_ROOT_DIR, accountId, volumeId);
}
public Answer execute(downloadSnapshotFromSwiftCommand cmd){
SwiftTO swift = cmd.getSwift();
String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
Long accountId = cmd.getAccountId();
Long volumeId = cmd.getVolumeId();
String rFilename = cmd.getSnapshotUuid();
String sParent = cmd.getParent();
String errMsg = "";
try {
String parent = getRootDir(secondaryStorageUrl);
String lPath = parent + "/snapshots/" + String.valueOf(accountId) + "/" + String.valueOf(volumeId);
String result = createLocalDir(lPath);
if ( result != null ) {
errMsg = "downloadSnapshotFromSwiftCommand failed due to Create local path failed";
s_logger.warn(errMsg);
throw new InternalErrorException(errMsg);
}
String lFilename = rFilename;
if ( rFilename.startsWith("VHD-") ) {
lFilename = rFilename.replace("VHD-", "") + ".vhd";
}
String lFullPath = lPath + "/" + lFilename;
result = swiftDownload(swift, "S-" + volumeId.toString(), rFilename, lFullPath);
if (result != null) {
return new Answer(cmd, false, result);
}
if (sParent != null) {
if (sParent.startsWith("VHD-") || sParent.endsWith(".vhd")) {
String pFilename = sParent;
if (sParent.startsWith("VHD-")) {
pFilename = pFilename.replace("VHD-", "") + ".vhd";
}
String pFullPath = lPath + "/" + pFilename;
result = setVhdParent(lFullPath, pFullPath);
if (result != null) {
return new Answer(cmd, false, result);
}
}
}
return new Answer(cmd, true, "success");
} catch (Exception e) {
String msg = cmd + " Command failed due to " + e.toString();
s_logger.warn(msg, e);
throw new CloudRuntimeException(msg);
}
}
private Answer execute(ComputeChecksumCommand cmd) {
String relativeTemplatePath = cmd.getTemplatePath();
String parent = getRootDir(cmd);
if (relativeTemplatePath.startsWith(File.separator)) {
relativeTemplatePath = relativeTemplatePath.substring(1);
}
if (!parent.endsWith(File.separator)) {
parent += File.separator;
}
String absoluteTemplatePath = parent + relativeTemplatePath;
MessageDigest digest;
String checksum = null;
File f = new File(absoluteTemplatePath);
InputStream is = null;
byte[] buffer = new byte[8192];
int read = 0;
if(s_logger.isDebugEnabled()){
s_logger.debug("parent path " +parent+ " relative template path " +relativeTemplatePath );
}
try {
digest = MessageDigest.getInstance("MD5");
is = new FileInputStream(f);
while( (read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
byte[] md5sum = digest.digest();
BigInteger bigInt = new BigInteger(1, md5sum);
checksum = bigInt.toString(16);
if(s_logger.isDebugEnabled()){
s_logger.debug("Successfully calculated checksum for file " +absoluteTemplatePath+ " - " +checksum );
}
}catch(IOException e) {
String logMsg = "Unable to process file for MD5 - " + absoluteTemplatePath;
s_logger.error(logMsg);
return new Answer(cmd, false, checksum);
}catch (NoSuchAlgorithmException e) {
return new Answer(cmd, false, checksum);
}
finally {
try {
if(is != null)
is.close();
} catch (IOException e) {
if(s_logger.isDebugEnabled()){
s_logger.debug("Could not close the file " +absoluteTemplatePath);
}
return new Answer(cmd, false, checksum);
}
}
return new Answer(cmd, true, checksum);
}
private void configCerts(Certificates certs) {
if (certs == null) {
configureSSL();
} else {
String prvKey = certs.getPrivKey();
String pubCert = certs.getPrivCert();
String certChain = certs.getCertChain();
try {
File prvKeyFile = File.createTempFile("prvkey", null);
String prvkeyPath = prvKeyFile.getAbsolutePath();
BufferedWriter out = new BufferedWriter(new FileWriter(prvKeyFile));
out.write(prvKey);
out.close();
File pubCertFile = File.createTempFile("pubcert", null);
String pubCertFilePath = pubCertFile.getAbsolutePath();
out = new BufferedWriter(new FileWriter(pubCertFile));
out.write(pubCert);
out.close();
configureSSL(prvkeyPath, pubCertFilePath, null);
prvKeyFile.delete();
pubCertFile.delete();
} catch (IOException e) {
s_logger.debug("Failed to config ssl: " + e.toString());
}
}
}
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(_storageGateway, _storageIp, _storageNetmask, nfsHostIp);
String nfsPath = nfsHostIp + ":" + uri.getPath();
String dir = UUID.nameUUIDFromBytes(nfsPath.getBytes()).toString();
String root = _parent + "/" + dir;
mount(root, nfsPath);
configCerts(cmd.getCerts());
nfsIps.add(nfsHostIp);
return new SecStorageSetupAnswer(dir);
} catch (Exception e) {
String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString();
s_logger.error(msg);
return new Answer(cmd, false, msg);
}
}
private String deleteSnapshotBackupFromLocalFileSystem(
final String secondaryStorageUrl, final Long accountId,
final Long volumeId, final String name, final Boolean deleteAllFlag) {
final String lPath = determineSnapshotLocalDirectory(
secondaryStorageUrl, accountId, volumeId)
+ File.pathSeparator
+ (deleteAllFlag ? "*" : "*" + name + "*");
final String result = deleteLocalFile(lPath);
if (result != null) {
return "failed to delete snapshot " + lPath + " , err=" + result;
}
return null;
}
private String deleteSnapshotBackupfromS3(final S3TO s3,
final String secondaryStorageUrl, final Long accountId,
final Long volumeId, final String name, final Boolean deleteAllFlag) {
try {
final String bucket = s3.getBucketName();
final String result = executeWithNoWaitLock(
determineSnapshotLockId(accountId, volumeId),
new Callable<String>() {
@Override
public String call() throws Exception {
final String innerResult = deleteSnapshotBackupFromLocalFileSystem(
secondaryStorageUrl, accountId, volumeId,
name, deleteAllFlag);
if (innerResult != null) {
return innerResult;
}
if (deleteAllFlag) {
S3Utils.deleteDirectory(
s3,
bucket,
determineSnapshotS3Directory(accountId,
volumeId));
} else {
S3Utils.deleteObject(
s3,
bucket,
determineSnapshotS3Key(
accountId,
volumeId,
determineSnapshotBackupFilename(name)));
}
return null;
}
});
return result;
} catch (Exception e) {
s_logger.error(
String.format(
"Failed to delete snapshot backup for account id %1$s volume id %2$sfrom S3.",
accountId, volumeId), e);
return e.getMessage();
}
}
private String determineSnapshotBackupFilename(final String snapshotUuid) {
return snapshotUuid + ".vhd";
}
private String determineSnapshotLockId(final Long accountId,
final Long volumeId) {
return join("_", "SNAPSHOT", accountId, volumeId);
}
protected Answer execute(final DeleteSnapshotBackupCommand cmd) {
String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
Long accountId = cmd.getAccountId();
Long volumeId = cmd.getVolumeId();
String name = cmd.getSnapshotUuid();
try {
SwiftTO swift = cmd.getSwift();
S3TO s3 = cmd.getS3();
if (swift == null) {
final String result = deleteSnapshotBackupFromLocalFileSystem(
secondaryStorageUrl, accountId, volumeId, name,
cmd.isAll());
if (result != null) {
s_logger.warn(result);
return new Answer(cmd, false, result);
}
} else if (s3 != null) {
final String result = deleteSnapshotBackupfromS3(s3,
secondaryStorageUrl, accountId, volumeId, name,
cmd.isAll());
if (result != null) {
s_logger.warn(result);
return new Answer(cmd, false, result);
}
} else {
String filename;
if (cmd.isAll()) {
filename = "";
} else {
filename = name;
}
String result = swiftDelete(swift, "V-" + volumeId.toString(), filename);
if (result != null) {
String errMsg = "failed to delete snapshot " + filename + " , err=" + result;
s_logger.warn(errMsg);
return new Answer(cmd, false, errMsg);
}
}
return new Answer(cmd, true, "success");
} catch (Exception e) {
String errMsg = cmd + " Command failed due to " + e.toString();
s_logger.warn(errMsg, e);
return new Answer(cmd, false, errMsg);
}
}
Map<String, TemplateInfo> swiftListTemplate(SwiftTO swift) {
String[] containers = swiftList(swift, "", "");
if (containers == null) {
return null;
}
Map<String, TemplateInfo> tmpltInfos = new HashMap<String, TemplateInfo>();
for( String container : containers) {
if ( container.startsWith("T-")) {
String ldir = _tmpltDir + "/" + UUID.randomUUID().toString();
createLocalDir(ldir);
String lFullPath = ldir + "/" + _tmpltpp;
swiftDownload(swift, container, _tmpltpp, lFullPath);
TemplateLocation loc = new TemplateLocation(_storage, ldir);
try {
if (!loc.load()) {
s_logger.warn("Can not parse template.properties file for template " + container);
continue;
}
} catch (IOException e) {
s_logger.warn("Unable to load template location " + ldir + " due to " + e.toString(), e);
continue;
}
TemplateInfo tInfo = loc.getTemplateInfo();
tInfo.setInstallPath(container);
tmpltInfos.put(tInfo.getTemplateName(), tInfo);
loc.purge();
deleteLocalDir(ldir);
}
}
return tmpltInfos;
}
private Answer execute(ListTemplateCommand cmd) {
if (!_inSystemVM){
return new Answer(cmd, true, null);
}
if (cmd.getSwift() != null) {
Map<String, TemplateInfo> templateInfos = swiftListTemplate(cmd.getSwift());
return new ListTemplateAnswer(cmd.getSwift().toString(), templateInfos);
} else {
String root = getRootDir(cmd.getSecUrl());
Map<String, TemplateInfo> templateInfos = _dlMgr.gatherTemplateInfo(root);
return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos);
}
}
private Answer execute(ListVolumeCommand cmd) {
if (!_inSystemVM){
return new Answer(cmd, true, null);
}
String root = getRootDir(cmd.getSecUrl());
Map<Long, TemplateInfo> templateInfos = _dlMgr.gatherVolumeInfo(root);
return new ListVolumeAnswer(cmd.getSecUrl(), templateInfos);
}
private Answer execute(SecStorageVMSetupCommand cmd) {
if (!_inSystemVM){
return new Answer(cmd, true, null);
}
boolean success = true;
StringBuilder result = new StringBuilder();
for (String cidr: cmd.getAllowedInternalSites()) {
if (nfsIps.contains(cidr)) {
/*
* if the internal download ip is the same with secondary storage ip, adding internal sites will flush
* ip route to nfs through storage ip.
*/
continue;
}
String tmpresult = allowOutgoingOnPrivate(cidr);
if (tmpresult != null) {
result.append(", ").append(tmpresult);
success = false;
}
}
if (success) {
if (cmd.getCopyPassword() != null && cmd.getCopyUserName() != null) {
String tmpresult = configureAuth(cmd.getCopyUserName(), cmd.getCopyPassword());
if (tmpresult != null) {
result.append("Failed to configure auth for copy ").append(tmpresult);
success = false;
}
}
}
return new Answer(cmd, success, result.toString());
}
private String setVhdParent(String lFullPath, String pFullPath) {
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("/bin/vhd-util modify -n " + lFullPath + " -p " + pFullPath);
String result = command.execute();
if (result != null) {
String errMsg = "failed to set vhd parent, child " + lFullPath + " parent " + pFullPath + ", err=" + result;
s_logger.warn(errMsg);
return errMsg;
}
return null;
}
private String createLocalDir(String folder) {
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("mkdir -p " + folder);
String result = command.execute();
if (result != null) {
String errMsg = "Create local path " + folder + " failed , err=" + result;
s_logger.warn(errMsg);
return errMsg;
}
return null;
}
private String deleteLocalDir(String folder) {
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("rmdir " + folder);
String result = command.execute();
if (result != null) {
String errMsg = "Delete local path " + folder + " failed , err=" + result;
s_logger.warn(errMsg);
return errMsg;
}
return null;
}
private String deleteLocalFile(String fullPath) {
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("rm -f " + fullPath);
String result = command.execute();
if (result != null) {
String errMsg = "Failed to delete file " + fullPath + ", err=" + result;
s_logger.warn(errMsg);
return errMsg;
}
return null;
}
public String allowOutgoingOnPrivate(String destCidr) {
Script command = new Script("/bin/bash", s_logger);
String intf = "eth1";
command.add("-c");
command.add("iptables -I OUTPUT -o " + intf + " -d " + destCidr + " -p tcp -m state --state NEW -m tcp -j ACCEPT");
String result = command.execute();
if (result != null) {
s_logger.warn("Error in allowing outgoing to " + destCidr + ", err=" + result );
return "Error in allowing outgoing to " + destCidr + ", err=" + result;
}
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, destCidr);
return null;
}
private Answer execute(SecStorageFirewallCfgCommand cmd) {
if (!_inSystemVM){
return new Answer(cmd, true, null);
}
List<String> ipList = new ArrayList<String>();
for (PortConfig pCfg:cmd.getPortConfigs()){
if (pCfg.isAdd()) {
ipList.add(pCfg.getSourceIp());
}
}
boolean success = true;
String result;
result = configureIpFirewall(ipList, cmd.getIsAppendAIp());
if (result !=null)
success = false;
return new Answer(cmd, success, result);
}
protected GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) {
String rootDir = getRootDir(cmd.getSecUrl());
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 {
return new GetStorageStatsAnswer(cmd, totalSize, usedSize) ;
}
}
protected Answer execute(final DeleteTemplateCommand cmd) {
String relativeTemplatePath = cmd.getTemplatePath();
String parent = getRootDir(cmd);
if (relativeTemplatePath.startsWith(File.separator)) {
relativeTemplatePath = relativeTemplatePath.substring(1);
}
if (!parent.endsWith(File.separator)) {
parent += File.separator;
}
String absoluteTemplatePath = parent + relativeTemplatePath;
File tmpltParent = new File(absoluteTemplatePath).getParentFile();
String details = null;
if (!tmpltParent.exists()) {
details = "template parent directory " + tmpltParent.getName() + " doesn't exist";
s_logger.debug(details);
return new Answer(cmd, true, details);
}
File[] tmpltFiles = tmpltParent.listFiles();
if (tmpltFiles == null || tmpltFiles.length == 0) {
details = "No files under template parent directory " + tmpltParent.getName();
s_logger.debug(details);
} else {
boolean found = false;
for (File f : tmpltFiles) {
if (!found && f.getName().equals("template.properties")) {
found = true;
}
if (!f.delete()) {
return new Answer(cmd, false, "Unable to delete file " + f.getName() + " under Template path "
+ relativeTemplatePath);
}
}
if (!found) {
details = "Can not find template.properties under " + tmpltParent.getName();
s_logger.debug(details);
}
}
if (!tmpltParent.delete()) {
details = "Unable to delete directory " + tmpltParent.getName() + " under Template path "
+ relativeTemplatePath;
s_logger.debug(details);
return new Answer(cmd, false, details);
}
return new Answer(cmd, true, null);
}
protected Answer execute(final DeleteVolumeCommand cmd) {
String relativeVolumePath = cmd.getVolumePath();
String parent = getRootDir(cmd);
if (relativeVolumePath.startsWith(File.separator)) {
relativeVolumePath = relativeVolumePath.substring(1);
}
if (!parent.endsWith(File.separator)) {
parent += File.separator;
}
String absoluteVolumePath = parent + relativeVolumePath;
File tmpltParent = new File(absoluteVolumePath).getParentFile();
String details = null;
if (!tmpltParent.exists()) {
details = "volume parent directory " + tmpltParent.getName() + " doesn't exist";
s_logger.debug(details);
return new Answer(cmd, true, details);
}
File[] tmpltFiles = tmpltParent.listFiles();
if (tmpltFiles == null || tmpltFiles.length == 0) {
details = "No files under volume parent directory " + tmpltParent.getName();
s_logger.debug(details);
} else {
boolean found = false;
for (File f : tmpltFiles) {
if (!found && f.getName().equals("volume.properties")) {
found = true;
}
if (!f.delete()) {
return new Answer(cmd, false, "Unable to delete file " + f.getName() + " under Volume path "
+ relativeVolumePath);
}
}
if (!found) {
details = "Can not find volume.properties under " + tmpltParent.getName();
s_logger.debug(details);
}
}
if (!tmpltParent.delete()) {
details = "Unable to delete directory " + tmpltParent.getName() + " under Volume path "
+ relativeVolumePath;
s_logger.debug(details);
return new Answer(cmd, false, details);
}
return new Answer(cmd, true, null);
}
Answer execute(CleanupSnapshotBackupCommand cmd) {
String parent = getRootDir(cmd.getSecondaryStoragePoolURL());
if (!parent.endsWith(File.separator)) {
parent += File.separator;
}
String absoluteSnapsthotDir = parent + File.separator + "snapshots" + File.separator + cmd.getAccountId() + File.separator + cmd.getVolumeId();
File ssParent = new File(absoluteSnapsthotDir);
if (ssParent.exists() && ssParent.isDirectory()) {
File[] files = ssParent.listFiles();
for (File file : files) {
boolean found = false;
String filename = file.getName();
for (String uuid : cmd.getValidBackupUUIDs()) {
if (filename.startsWith(uuid)) {
found = true;
break;
}
}
if (!found) {
file.delete();
String msg = "snapshot " + filename + " is not recorded in DB, remove it";
s_logger.warn(msg);
}
}
}
return new Answer(cmd, true, null);
}
synchronized 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 = _parent + "/" + 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);
}
}
@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) {
if (size == null || size.isEmpty()) {
return -1;
}
long multiplier = 1;
if (size.endsWith("T")) {
multiplier = 1024l * 1024l * 1024l * 1024l;
} else if (size.endsWith("G")) {
multiplier = 1024l * 1024l * 1024l;
} else if (size.endsWith("M")) {
multiplier = 1024l * 1024l;
} else {
assert (false) : "Well, I have no idea what this is: " + size;
}
return (long)(Double.parseDouble(size.substring(0, size.length() - 1)) * multiplier);
}
@Override
public Type getType() {
if(SecondaryStorageVm.Role.templateProcessor.toString().equals(_role))
return Host.Type.SecondaryStorage;
return Host.Type.SecondaryStorageCmdExecutor;
}
@Override
public PingCommand getCurrentStatus(final long id) {
return new PingStorageCommand(Host.Type.Storage, id, new HashMap<String, Boolean>());
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_eth1ip = (String)params.get("eth1ip");
_eth1mask = (String)params.get("eth1mask");
if (_eth1ip != null) { //can only happen inside service vm
params.put("private.network.device", "eth1");
} else {
s_logger.warn("Wait, what's going on? eth1ip is null!!");
}
String eth2ip = (String) params.get("eth2ip");
if (eth2ip != null) {
params.put("public.network.device", "eth2");
}
_publicIp = (String) params.get("eth2ip");
_hostname = (String) params.get("name");
_storageIp = (String) params.get("storageip");
if (_storageIp == null) {
s_logger.warn("Wait, there is no storageip in /proc/cmdline, something wrong!");
}
_storageNetmask = (String) params.get("storagenetmask");
_storageGateway = (String) params.get("storagegateway");
super.configure(name, params);
_params = params;
String value = (String)params.get("scripts.timeout");
_timeout = NumbersUtil.parseInt(value, 1440) * 1000;
_storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey);
if (_storage == null) {
value = (String)params.get(StorageLayer.ClassConfigKey);
if (value == null) {
value = "com.cloud.storage.JavaStorageLayer";
}
try {
Class<?> clazz = Class.forName(value);
_storage = (StorageLayer)clazz.newInstance();
_storage.configure("StorageLayer", params);
} catch (ClassNotFoundException e) {
throw new ConfigurationException("Unable to find class " + value);
} catch (InstantiationException e) {
throw new ConfigurationException("Unable to find class " + value);
} catch (IllegalAccessException e) {
throw new ConfigurationException("Unable to find class " + value);
}
}
_storage.mkdirs(_parent);
_configSslScr = Script.findScript(getDefaultScriptsDir(), "config_ssl.sh");
if (_configSslScr != null) {
s_logger.info("config_ssl.sh found in " + _configSslScr);
}
_configAuthScr = Script.findScript(getDefaultScriptsDir(), "config_auth.sh");
if (_configSslScr != null) {
s_logger.info("config_auth.sh found in " + _configAuthScr);
}
_configIpFirewallScr = Script.findScript(getDefaultScriptsDir(), "ipfirewall.sh");
if (_configIpFirewallScr != null) {
s_logger.info("_configIpFirewallScr found in " + _configIpFirewallScr);
}
_role = (String)params.get("role");
if(_role == null)
_role = SecondaryStorageVm.Role.templateProcessor.toString();
s_logger.info("Secondary storage runs in role " + _role);
_guid = (String)params.get("guid");
if (_guid == null) {
throw new ConfigurationException("Unable to find the guid");
}
_dc = (String)params.get("zone");
if (_dc == null) {
throw new ConfigurationException("Unable to find the zone");
}
_pod = (String)params.get("pod");
_instance = (String)params.get("instance");
String inSystemVM = (String)params.get("secondary.storage.vm");
if (inSystemVM == null || "true".equalsIgnoreCase(inSystemVM)) {
_inSystemVM = true;
_localgw = (String)params.get("localgw");
if (_localgw != null) { // can only happen inside service vm
String mgmtHost = (String) params.get("host");
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, mgmtHost);
String internalDns1 = (String) params.get("internaldns1");
if (internalDns1 == null) {
s_logger.warn("No DNS entry found during configuration of NfsSecondaryStorage");
} else {
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, internalDns1);
}
String internalDns2 = (String) params.get("internaldns2");
if (internalDns2 != null) {
addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, internalDns2);
}
}
startAdditionalServices();
_params.put("install.numthreads", "50");
_params.put("secondary.storage.vm", "true");
}
try {
_params.put(StorageLayer.InstanceConfigKey, _storage);
_dlMgr = new DownloadManagerImpl();
_dlMgr.configure("DownloadManager", _params);
_upldMgr = new UploadManagerImpl();
_upldMgr.configure("UploadManager", params);
} catch (ConfigurationException e) {
s_logger.warn("Caught problem while configuring DownloadManager", e);
return false;
}
return true;
}
private void startAdditionalServices() {
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("if [ -f /etc/init.d/ssh ]; then service ssh restart; else service sshd restart; fi ");
String result = command.execute();
if (result != null) {
s_logger.warn("Error in starting sshd service err=" + result );
}
command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("iptables -I INPUT -i eth1 -p tcp -m state --state NEW -m tcp --dport 3922 -j ACCEPT");
result = command.execute();
if (result != null) {
s_logger.warn("Error in opening up ssh port err=" + result );
}
}
private void addRouteToInternalIpOrCidr(String localgw, String eth1ip, String eth1mask, String destIpOrCidr) {
s_logger.debug("addRouteToInternalIp: localgw=" + localgw + ", eth1ip=" + eth1ip + ", eth1mask=" + eth1mask + ",destIp=" + destIpOrCidr);
if (destIpOrCidr == null) {
s_logger.debug("addRouteToInternalIp: destIp is null");
return;
}
if (!NetUtils.isValidIp(destIpOrCidr) && !NetUtils.isValidCIDR(destIpOrCidr)){
s_logger.warn(" destIp is not a valid ip address or cidr destIp=" + destIpOrCidr);
return;
}
boolean inSameSubnet = false;
if (NetUtils.isValidIp(destIpOrCidr)) {
if (eth1ip != null && eth1mask != null) {
inSameSubnet = NetUtils.sameSubnet(eth1ip, destIpOrCidr, eth1mask);
} else {
s_logger.warn("addRouteToInternalIp: unable to determine same subnet: _eth1ip=" + eth1ip + ", dest ip=" + destIpOrCidr + ", _eth1mask=" + eth1mask);
}
} else {
inSameSubnet = NetUtils.isNetworkAWithinNetworkB(destIpOrCidr, NetUtils.ipAndNetMaskToCidr(eth1ip, eth1mask));
}
if (inSameSubnet) {
s_logger.debug("addRouteToInternalIp: dest ip " + destIpOrCidr + " is in the same subnet as eth1 ip " + eth1ip);
return;
}
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("ip route delete " + destIpOrCidr);
command.execute();
command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("ip route add " + destIpOrCidr + " via " + localgw);
String result = command.execute();
if (result != null) {
s_logger.warn("Error in configuring route to internal ip err=" + result );
} else {
s_logger.debug("addRouteToInternalIp: added route to internal ip=" + destIpOrCidr + " via " + localgw);
}
}
private void configureSSL() {
Script command = new Script(_configSslScr);
command.add("-i", _publicIp);
command.add("-h", _hostname);
String result = command.execute();
if (result != null) {
s_logger.warn("Unable to configure httpd to use ssl");
}
}
private void configureSSL(String prvkeyPath, String prvCertPath, String certChainPath) {
Script command = new Script(_configSslScr);
command.add("-i", _publicIp);
command.add("-h", _hostname);
command.add("-k", prvkeyPath);
command.add("-p", prvCertPath);
if (certChainPath != null) {
command.add("-t", certChainPath);
}
String result = command.execute();
if (result != null) {
s_logger.warn("Unable to configure httpd to use ssl");
}
}
private String configureAuth(String user, String passwd) {
Script command = new Script(_configAuthScr);
command.add(user);
command.add(passwd);
String result = command.execute();
if (result != null) {
s_logger.warn("Unable to configure httpd to use auth");
}
return result;
}
private String configureIpFirewall(List<String> ipList, boolean isAppend){
Script command = new Script(_configIpFirewallScr);
command.add(String.valueOf(isAppend));
for (String ip : ipList){
command.add(ip);
}
String result = command.execute();
if (result != null) {
s_logger.warn("Unable to configure firewall for command : " +command);
}
return result;
}
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;
}
}
Script script = null;
String result = null;
script = new Script(!_inSystemVM, "mount", _timeout, s_logger);
List<String> res = new ArrayList<String>();
ZfsPathParser parser = new ZfsPathParser(root);
script.execute(parser);
res.addAll(parser.getPaths());
for( String s : res ) {
if ( s.contains(root)) {
return root;
}
}
Script command = new Script(!_inSystemVM, "mount", _timeout, s_logger);
command.add("-t", "nfs");
if (_inSystemVM) {
//Fedora Core 12 errors out with any -o option executed from java
command.add("-o", "soft,timeo=133,retrans=2147483647,tcp,acdirmax=0,acdirmin=0");
}
command.add(nfsPath);
command.add(root);
result = command.execute();
if (result != null) {
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(root)) {
return null;
}
// Create the volumes dir
if (!checkForVolumesDir(root)) {
return null;
}
return root;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public StartupCommand[] initialize() {
final StartupSecondaryStorageCommand cmd = new StartupSecondaryStorageCommand();
fillNetworkInformation(cmd);
if(_publicIp != null)
cmd.setPublicIpAddress(_publicIp);
Script command = new Script("/bin/bash", s_logger);
command.add("-c");
command.add("ln -sf " + _parent + " /var/www/html/copy");
String result = command.execute();
if (result != null) {
s_logger.warn("Error in linking err=" + result);
return null;
}
return new StartupCommand[] {cmd};
}
protected boolean checkForSnapshotsDir(String mountPoint) {
String snapshotsDirLocation = mountPoint + File.separator + "snapshots";
return createDir("snapshots", snapshotsDirLocation, mountPoint);
}
protected boolean checkForVolumesDir(String mountPoint) {
String volumesDirLocation = mountPoint + "/" + "volumes";
return createDir("volumes", volumesDirLocation, mountPoint);
}
protected boolean createDir(String dirName, String dirLocation, String mountPoint) {
boolean dirExists = false;
File dir = new File(dirLocation);
if (dir.exists()) {
if (dir.isDirectory()) {
s_logger.debug(dirName + " already exists on secondary storage, and is mounted at " + mountPoint);
dirExists = true;
} else {
if (dir.delete() && _storage.mkdir(dirLocation)) {
dirExists = true;
}
}
} else if (_storage.mkdir(dirLocation)) {
dirExists = true;
}
if (dirExists) {
s_logger.info(dirName + " directory created/exists on Secondary Storage.");
} else {
s_logger.info(dirName + " directory does not exist on Secondary Storage.");
}
return dirExists;
}
@Override
protected String getDefaultScriptsDir() {
return "./scripts/storage/secondary";
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
}
@Override
public void setConfigParams(Map<String, Object> params) {
// TODO Auto-generated method stub
}
@Override
public Map<String, Object> getConfigParams() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getRunLevel() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void setRunLevel(int level) {
// TODO Auto-generated method stub
}
}