mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge branch 'refactor/libvirt_resource' of https://github.com/schubergphilis/cloudstack
This closes #233
This commit is contained in:
commit
45c0fa2faa
@ -53,9 +53,9 @@ public class SnapshotCommand extends Command {
|
|||||||
* is the value of that field If you have better ideas on how to
|
* is the value of that field If you have better ideas on how to
|
||||||
* get it, you are welcome.
|
* get it, you are welcome.
|
||||||
*/
|
*/
|
||||||
public SnapshotCommand(StoragePool pool, String secondaryStorageUrl, String snapshotUuid, String snapshotName, Long dcId, Long accountId, Long volumeId) {
|
public SnapshotCommand(final StoragePool pool, final String secondaryStorageUrl, final String snapshotUuid, final String snapshotName, final Long dcId, final Long accountId, final Long volumeId) {
|
||||||
// this.primaryStoragePoolNameLabel = pool.getUuid();
|
primaryStoragePoolNameLabel = pool.getUuid();
|
||||||
//this.primaryPool = new StorageFilerTO(pool);
|
primaryPool = new StorageFilerTO(pool);
|
||||||
this.snapshotUuid = snapshotUuid;
|
this.snapshotUuid = snapshotUuid;
|
||||||
this.secondaryStorageUrl = secondaryStorageUrl;
|
this.secondaryStorageUrl = secondaryStorageUrl;
|
||||||
this.dcId = dcId;
|
this.dcId = dcId;
|
||||||
@ -112,7 +112,7 @@ public class SnapshotCommand extends Command {
|
|||||||
return volumePath;
|
return volumePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVolumePath(String path) {
|
public void setVolumePath(final String path) {
|
||||||
volumePath = path;
|
volumePath = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,81 +19,16 @@
|
|||||||
|
|
||||||
package com.cloud.resource;
|
package com.cloud.resource;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
import com.cloud.agent.api.Command;
|
import com.cloud.agent.api.Command;
|
||||||
import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class CommandWrapper<T extends Command, A extends Answer, R extends ServerResource> {
|
public abstract class CommandWrapper<T extends Command, A extends Answer, R extends ServerResource> {
|
||||||
|
|
||||||
private static final Logger s_logger = Logger.getLogger(CommandWrapper.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param T is the command to be used.
|
* @param T is the command to be used.
|
||||||
* @param R is the resource base to be used.
|
* @param R is the resource base to be used.
|
||||||
* @return A and the Answer from the command.
|
* @return A and the Answer from the command.
|
||||||
*/
|
*/
|
||||||
public abstract A execute(T command, R serverResource);
|
public abstract A execute(T command, R serverResource);
|
||||||
|
|
||||||
/**
|
|
||||||
* Common method so we added it here.
|
|
||||||
*
|
|
||||||
* @param cmd
|
|
||||||
* @param proxyVmId
|
|
||||||
* @param proxyVmName
|
|
||||||
* @param proxyManagementIp
|
|
||||||
* @param cmdPort
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected Answer executeProxyLoadScan(final Command cmd, final long proxyVmId, final String proxyVmName, final String proxyManagementIp, final int cmdPort) {
|
|
||||||
String result = null;
|
|
||||||
|
|
||||||
final StringBuffer sb = new StringBuffer();
|
|
||||||
sb.append("http://").append(proxyManagementIp).append(":" + cmdPort).append("/cmd/getstatus");
|
|
||||||
|
|
||||||
boolean success = true;
|
|
||||||
try {
|
|
||||||
final URL url = new URL(sb.toString());
|
|
||||||
final URLConnection conn = url.openConnection();
|
|
||||||
|
|
||||||
// setting TIMEOUTs to avoid possible waiting until death situations
|
|
||||||
conn.setConnectTimeout(5000);
|
|
||||||
conn.setReadTimeout(5000);
|
|
||||||
|
|
||||||
final InputStream is = conn.getInputStream();
|
|
||||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charset.defaultCharset()));
|
|
||||||
final StringBuilder sb2 = new StringBuilder();
|
|
||||||
String line = null;
|
|
||||||
try {
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
sb2.append(line + "\n");
|
|
||||||
}
|
|
||||||
result = sb2.toString();
|
|
||||||
} catch (final IOException e) {
|
|
||||||
success = false;
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
is.close();
|
|
||||||
} catch (final IOException e) {
|
|
||||||
s_logger.warn("Exception when closing , console proxy address : " + proxyManagementIp);
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (final IOException e) {
|
|
||||||
s_logger.warn("Unable to open console proxy command port url, console proxy address : " + proxyManagementIp);
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ConsoleProxyLoadAnswer(cmd, proxyVmId, proxyVmName, success, result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -19,14 +19,93 @@
|
|||||||
|
|
||||||
package com.cloud.resource;
|
package com.cloud.resource;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
import com.cloud.agent.api.Command;
|
import com.cloud.agent.api.Command;
|
||||||
|
|
||||||
public abstract class RequestWrapper {
|
public abstract class RequestWrapper {
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
protected Hashtable<Class<? extends ServerResource>, Hashtable<Class<? extends Command>, CommandWrapper>> resources = new Hashtable<Class<? extends ServerResource>, Hashtable<Class<? extends Command>, CommandWrapper>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param command to be executed.
|
* @param command to be executed.
|
||||||
* @return an Answer for the executed command.
|
* @return an Answer for the executed command.
|
||||||
*/
|
*/
|
||||||
public abstract Answer execute(Command command, ServerResource serverResource);
|
public abstract Answer execute(Command command, ServerResource serverResource);
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
protected Hashtable<Class<? extends Command>, CommandWrapper> retrieveResource(final Command command, final Class<? extends ServerResource> resourceClass) {
|
||||||
|
Class<? extends ServerResource> keepResourceClass = resourceClass;
|
||||||
|
Hashtable<Class<? extends Command>, CommandWrapper> resource = resources.get(keepResourceClass);
|
||||||
|
while (resource == null) {
|
||||||
|
try {
|
||||||
|
final Class<? extends ServerResource> keepResourceClass2 = (Class<? extends ServerResource>) keepResourceClass.getSuperclass();
|
||||||
|
resource = resources.get(keepResourceClass2);
|
||||||
|
|
||||||
|
keepResourceClass = keepResourceClass2;
|
||||||
|
} catch (final ClassCastException e) {
|
||||||
|
throw new NullPointerException("No key found for '" + command.getClass() + "' in the Map!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
protected CommandWrapper<Command, Answer, ServerResource> retrieveCommands(final Class<? extends Command> commandClass,
|
||||||
|
final Hashtable<Class<? extends Command>, CommandWrapper> resourceCommands) {
|
||||||
|
|
||||||
|
Class<? extends Command> keepCommandClass = commandClass;
|
||||||
|
CommandWrapper<Command, Answer, ServerResource> commandWrapper = resourceCommands.get(keepCommandClass);
|
||||||
|
while (commandWrapper == null) {
|
||||||
|
try {
|
||||||
|
final Class<? extends Command> commandClass2 = (Class<? extends Command>) keepCommandClass.getSuperclass();
|
||||||
|
|
||||||
|
if (commandClass2 == null) {
|
||||||
|
throw new NullPointerException("All the COMMAND hierarchy tree has been visited but no compliant key has been found for '" + commandClass + "'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
commandWrapper = resourceCommands.get(commandClass2);
|
||||||
|
|
||||||
|
keepCommandClass = commandClass2;
|
||||||
|
} catch (final NullPointerException e) {
|
||||||
|
// Will now traverse all the resource hierarchy. Returning null
|
||||||
|
// is not a problem.
|
||||||
|
// It is all being nicely checked and in case we do not have a
|
||||||
|
// resource, an Unsupported answer will be thrown by the base
|
||||||
|
// class.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return commandWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
protected CommandWrapper<Command, Answer, ServerResource> retryWhenAllFails(final Command command, final Class<? extends ServerResource> resourceClass,
|
||||||
|
final Hashtable<Class<? extends Command>, CommandWrapper> resourceCommands) {
|
||||||
|
|
||||||
|
Class<? extends ServerResource> keepResourceClass = resourceClass;
|
||||||
|
CommandWrapper<Command, Answer, ServerResource> commandWrapper = resourceCommands.get(command.getClass());
|
||||||
|
while (commandWrapper == null) {
|
||||||
|
// Could not find the command in the given resource, will traverse
|
||||||
|
// the family tree.
|
||||||
|
try {
|
||||||
|
final Class<? extends ServerResource> resourceClass2 = (Class<? extends ServerResource>) keepResourceClass.getSuperclass();
|
||||||
|
|
||||||
|
if (resourceClass2 == null) {
|
||||||
|
throw new NullPointerException("All the SERVER-RESOURCE hierarchy tree has been visited but no compliant key has been found for '" + command.getClass() + "'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Hashtable<Class<? extends Command>, CommandWrapper> resourceCommands2 = retrieveResource(command,
|
||||||
|
(Class<? extends ServerResource>) keepResourceClass.getSuperclass());
|
||||||
|
keepResourceClass = resourceClass2;
|
||||||
|
|
||||||
|
commandWrapper = retrieveCommands(command.getClass(), resourceCommands2);
|
||||||
|
} catch (final NullPointerException e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return commandWrapper;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -19,15 +19,14 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
import com.cloud.agent.api.Command;
|
|
||||||
import com.cloud.agent.api.to.DiskTO;
|
import com.cloud.agent.api.to.DiskTO;
|
||||||
|
|
||||||
public final class AttachCommand extends Command implements StorageSubSystemCommand {
|
public final class AttachCommand extends StorageSubSystemCommand {
|
||||||
private DiskTO disk;
|
private DiskTO disk;
|
||||||
private String vmName;
|
private String vmName;
|
||||||
private boolean inSeq = false;
|
private boolean inSeq;
|
||||||
|
|
||||||
public AttachCommand(DiskTO disk, String vmName) {
|
public AttachCommand(final DiskTO disk, final String vmName) {
|
||||||
super();
|
super();
|
||||||
this.disk = disk;
|
this.disk = disk;
|
||||||
this.vmName = vmName;
|
this.vmName = vmName;
|
||||||
@ -42,7 +41,7 @@ public final class AttachCommand extends Command implements StorageSubSystemComm
|
|||||||
return disk;
|
return disk;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisk(DiskTO disk) {
|
public void setDisk(final DiskTO disk) {
|
||||||
this.disk = disk;
|
this.disk = disk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,12 +49,12 @@ public final class AttachCommand extends Command implements StorageSubSystemComm
|
|||||||
return vmName;
|
return vmName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVmName(String vmName) {
|
public void setVmName(final String vmName) {
|
||||||
this.vmName = vmName;
|
this.vmName = vmName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(boolean inSeq) {
|
public void setExecuteInSequence(final boolean inSeq) {
|
||||||
this.inSeq = inSeq;
|
this.inSeq = inSeq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,17 +19,16 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
import com.cloud.agent.api.Command;
|
|
||||||
|
|
||||||
public final class AttachPrimaryDataStoreCmd extends Command implements StorageSubSystemCommand {
|
public final class AttachPrimaryDataStoreCmd extends StorageSubSystemCommand {
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(boolean inSeq) {
|
public void setExecuteInSequence(final boolean inSeq) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String dataStore;
|
private final String dataStore;
|
||||||
|
|
||||||
public AttachPrimaryDataStoreCmd(String uri) {
|
public AttachPrimaryDataStoreCmd(final String uri) {
|
||||||
super();
|
super();
|
||||||
dataStore = uri;
|
dataStore = uri;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,10 +22,9 @@ package org.apache.cloudstack.storage.command;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.cloud.agent.api.Command;
|
|
||||||
import com.cloud.agent.api.to.DataTO;
|
import com.cloud.agent.api.to.DataTO;
|
||||||
|
|
||||||
public final class CopyCommand extends Command implements StorageSubSystemCommand {
|
public final class CopyCommand extends StorageSubSystemCommand {
|
||||||
private DataTO srcTO;
|
private DataTO srcTO;
|
||||||
private DataTO destTO;
|
private DataTO destTO;
|
||||||
private DataTO cacheTO;
|
private DataTO cacheTO;
|
||||||
@ -33,28 +32,28 @@ public final class CopyCommand extends Command implements StorageSubSystemComman
|
|||||||
private Map<String, String> options = new HashMap<String, String>();
|
private Map<String, String> options = new HashMap<String, String>();
|
||||||
private Map<String, String> options2 = new HashMap<String, String>();
|
private Map<String, String> options2 = new HashMap<String, String>();
|
||||||
|
|
||||||
public CopyCommand(DataTO srcData, DataTO destData, int timeout, boolean executeInSequence) {
|
public CopyCommand(final DataTO srcData, final DataTO destData, final int timeout, final boolean executeInSequence) {
|
||||||
super();
|
super();
|
||||||
this.srcTO = srcData;
|
srcTO = srcData;
|
||||||
this.destTO = destData;
|
destTO = destData;
|
||||||
this.setWait(timeout);
|
setWait(timeout);
|
||||||
this.executeInSequence = executeInSequence;
|
this.executeInSequence = executeInSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataTO getDestTO() {
|
public DataTO getDestTO() {
|
||||||
return this.destTO;
|
return destTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSrcTO(DataTO srcTO) {
|
public void setSrcTO(final DataTO srcTO) {
|
||||||
this.srcTO = srcTO;
|
this.srcTO = srcTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDestTO(DataTO destTO) {
|
public void setDestTO(final DataTO destTO) {
|
||||||
this.destTO = destTO;
|
this.destTO = destTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataTO getSrcTO() {
|
public DataTO getSrcTO() {
|
||||||
return this.srcTO;
|
return srcTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -66,15 +65,15 @@ public final class CopyCommand extends Command implements StorageSubSystemComman
|
|||||||
return cacheTO;
|
return cacheTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCacheTO(DataTO cacheTO) {
|
public void setCacheTO(final DataTO cacheTO) {
|
||||||
this.cacheTO = cacheTO;
|
this.cacheTO = cacheTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWaitInMillSeconds() {
|
public int getWaitInMillSeconds() {
|
||||||
return this.getWait() * 1000;
|
return getWait() * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOptions(Map<String, String> options) {
|
public void setOptions(final Map<String, String> options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +81,7 @@ public final class CopyCommand extends Command implements StorageSubSystemComman
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOptions2(Map<String, String> options2) {
|
public void setOptions2(final Map<String, String> options2) {
|
||||||
this.options2 = options2;
|
this.options2 = options2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +90,7 @@ public final class CopyCommand extends Command implements StorageSubSystemComman
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(boolean inSeq) {
|
public void setExecuteInSequence(final boolean inSeq) {
|
||||||
this.executeInSequence = inSeq;
|
executeInSequence = inSeq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,13 +19,12 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
import com.cloud.agent.api.Command;
|
|
||||||
import com.cloud.agent.api.to.DataTO;
|
import com.cloud.agent.api.to.DataTO;
|
||||||
|
|
||||||
public final class CreateObjectCommand extends Command implements StorageSubSystemCommand {
|
public final class CreateObjectCommand extends StorageSubSystemCommand {
|
||||||
private DataTO data;
|
private DataTO data;
|
||||||
|
|
||||||
public CreateObjectCommand(DataTO obj) {
|
public CreateObjectCommand(final DataTO obj) {
|
||||||
super();
|
super();
|
||||||
data = obj;
|
data = obj;
|
||||||
}
|
}
|
||||||
@ -44,7 +43,7 @@ public final class CreateObjectCommand extends Command implements StorageSubSyst
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(boolean inSeq) {
|
public void setExecuteInSequence(final boolean inSeq) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,18 +19,17 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
import com.cloud.agent.api.Command;
|
|
||||||
|
|
||||||
public final class CreatePrimaryDataStoreCmd extends Command implements StorageSubSystemCommand {
|
public final class CreatePrimaryDataStoreCmd extends StorageSubSystemCommand {
|
||||||
private final String dataStore;
|
private final String dataStore;
|
||||||
|
|
||||||
public CreatePrimaryDataStoreCmd(String uri) {
|
public CreatePrimaryDataStoreCmd(final String uri) {
|
||||||
super();
|
super();
|
||||||
this.dataStore = uri;
|
dataStore = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDataStore() {
|
public String getDataStore() {
|
||||||
return this.dataStore;
|
return dataStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -39,7 +38,7 @@ public final class CreatePrimaryDataStoreCmd extends Command implements StorageS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(boolean inSeq) {
|
public void setExecuteInSequence(final boolean inSeq) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,13 +19,12 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
import com.cloud.agent.api.Command;
|
|
||||||
import com.cloud.agent.api.to.DataTO;
|
import com.cloud.agent.api.to.DataTO;
|
||||||
|
|
||||||
public final class DeleteCommand extends Command implements StorageSubSystemCommand {
|
public final class DeleteCommand extends StorageSubSystemCommand {
|
||||||
private DataTO data;
|
private DataTO data;
|
||||||
|
|
||||||
public DeleteCommand(DataTO data) {
|
public DeleteCommand(final DataTO data) {
|
||||||
super();
|
super();
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
@ -44,7 +43,7 @@ public final class DeleteCommand extends Command implements StorageSubSystemComm
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(boolean inSeq) {
|
public void setExecuteInSequence(final boolean inSeq) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,10 +19,9 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
import com.cloud.agent.api.Command;
|
|
||||||
import com.cloud.agent.api.to.DiskTO;
|
import com.cloud.agent.api.to.DiskTO;
|
||||||
|
|
||||||
public class DettachCommand extends Command implements StorageSubSystemCommand {
|
public class DettachCommand extends StorageSubSystemCommand {
|
||||||
private DiskTO disk;
|
private DiskTO disk;
|
||||||
private String vmName;
|
private String vmName;
|
||||||
private boolean _managed;
|
private boolean _managed;
|
||||||
@ -30,7 +29,7 @@ public class DettachCommand extends Command implements StorageSubSystemCommand {
|
|||||||
private String _storageHost;
|
private String _storageHost;
|
||||||
private int _storagePort;
|
private int _storagePort;
|
||||||
|
|
||||||
public DettachCommand(DiskTO disk, String vmName) {
|
public DettachCommand(final DiskTO disk, final String vmName) {
|
||||||
super();
|
super();
|
||||||
this.disk = disk;
|
this.disk = disk;
|
||||||
this.vmName = vmName;
|
this.vmName = vmName;
|
||||||
@ -45,7 +44,7 @@ public class DettachCommand extends Command implements StorageSubSystemCommand {
|
|||||||
return disk;
|
return disk;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisk(DiskTO disk) {
|
public void setDisk(final DiskTO disk) {
|
||||||
this.disk = disk;
|
this.disk = disk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,11 +52,11 @@ public class DettachCommand extends Command implements StorageSubSystemCommand {
|
|||||||
return vmName;
|
return vmName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVmName(String vmName) {
|
public void setVmName(final String vmName) {
|
||||||
this.vmName = vmName;
|
this.vmName = vmName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setManaged(boolean managed) {
|
public void setManaged(final boolean managed) {
|
||||||
_managed = managed;
|
_managed = managed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +64,7 @@ public class DettachCommand extends Command implements StorageSubSystemCommand {
|
|||||||
return _managed;
|
return _managed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set_iScsiName(String iScsiName) {
|
public void set_iScsiName(final String iScsiName) {
|
||||||
_iScsiName = iScsiName;
|
_iScsiName = iScsiName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +72,7 @@ public class DettachCommand extends Command implements StorageSubSystemCommand {
|
|||||||
return _iScsiName;
|
return _iScsiName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStorageHost(String storageHost) {
|
public void setStorageHost(final String storageHost) {
|
||||||
_storageHost = storageHost;
|
_storageHost = storageHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +80,7 @@ public class DettachCommand extends Command implements StorageSubSystemCommand {
|
|||||||
return _storageHost;
|
return _storageHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStoragePort(int storagePort) {
|
public void setStoragePort(final int storagePort) {
|
||||||
_storagePort = storagePort;
|
_storagePort = storagePort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +89,7 @@ public class DettachCommand extends Command implements StorageSubSystemCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(boolean inSeq) {
|
public void setExecuteInSequence(final boolean inSeq) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,13 +19,12 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
import com.cloud.agent.api.Command;
|
|
||||||
import com.cloud.agent.api.to.DataTO;
|
import com.cloud.agent.api.to.DataTO;
|
||||||
|
|
||||||
public class ForgetObjectCmd extends Command implements StorageSubSystemCommand {
|
public class ForgetObjectCmd extends StorageSubSystemCommand {
|
||||||
private DataTO dataTO;
|
private final DataTO dataTO;
|
||||||
|
|
||||||
public ForgetObjectCmd(DataTO data) {
|
public ForgetObjectCmd(final DataTO data) {
|
||||||
dataTO = data;
|
dataTO = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +38,7 @@ public class ForgetObjectCmd extends Command implements StorageSubSystemCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(boolean inSeq) {
|
public void setExecuteInSequence(final boolean inSeq) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,13 +19,12 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
import com.cloud.agent.api.Command;
|
|
||||||
import com.cloud.agent.api.to.DataTO;
|
import com.cloud.agent.api.to.DataTO;
|
||||||
|
|
||||||
public class IntroduceObjectCmd extends Command implements StorageSubSystemCommand {
|
public class IntroduceObjectCmd extends StorageSubSystemCommand {
|
||||||
private DataTO dataTO;
|
private final DataTO dataTO;
|
||||||
|
|
||||||
public IntroduceObjectCmd(DataTO dataTO) {
|
public IntroduceObjectCmd(final DataTO dataTO) {
|
||||||
this.dataTO = dataTO;
|
this.dataTO = dataTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +38,7 @@ public class IntroduceObjectCmd extends Command implements StorageSubSystemComma
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(boolean inSeq) {
|
public void setExecuteInSequence(final boolean inSeq) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,18 +19,16 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
import com.cloud.agent.api.Command;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public final class SnapshotAndCopyCommand extends Command implements StorageSubSystemCommand {
|
public final class SnapshotAndCopyCommand extends StorageSubSystemCommand {
|
||||||
private String _uuidOfSourceVdi;
|
private final String _uuidOfSourceVdi;
|
||||||
private Map<String, String> _sourceDetails;
|
private final Map<String, String> _sourceDetails;
|
||||||
private Map<String, String> _destDetails;
|
private final Map<String, String> _destDetails;
|
||||||
|
|
||||||
private boolean _executeInSequence = true;
|
private boolean _executeInSequence = true;
|
||||||
|
|
||||||
public SnapshotAndCopyCommand(String uuidOfSourceVdi, Map<String, String> sourceDetails, Map<String, String> destDetails) {
|
public SnapshotAndCopyCommand(final String uuidOfSourceVdi, final Map<String, String> sourceDetails, final Map<String, String> destDetails) {
|
||||||
_uuidOfSourceVdi = uuidOfSourceVdi;
|
_uuidOfSourceVdi = uuidOfSourceVdi;
|
||||||
_sourceDetails = sourceDetails;
|
_sourceDetails = sourceDetails;
|
||||||
_destDetails = destDetails;
|
_destDetails = destDetails;
|
||||||
@ -49,7 +47,7 @@ public final class SnapshotAndCopyCommand extends Command implements StorageSubS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExecuteInSequence(boolean executeInSequence) {
|
public void setExecuteInSequence(final boolean executeInSequence) {
|
||||||
_executeInSequence = executeInSequence;
|
_executeInSequence = executeInSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.command;
|
package org.apache.cloudstack.storage.command;
|
||||||
|
|
||||||
public interface StorageSubSystemCommand {
|
import com.cloud.agent.api.Command;
|
||||||
void setExecuteInSequence(boolean inSeq);
|
|
||||||
|
public abstract class StorageSubSystemCommand extends Command {
|
||||||
|
public abstract void setExecuteInSequence(boolean inSeq);
|
||||||
}
|
}
|
||||||
@ -31,4 +31,7 @@
|
|||||||
<property name="name" value="KVMInvestigator" />
|
<property name="name" value="KVMInvestigator" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="libvirtUtilitiesHelper"
|
||||||
|
class="com.cloud.hypervisor.kvm.resource.wrapper.LibvirtUtilitiesHelper" />
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,38 @@
|
|||||||
|
package com.cloud.hypervisor.kvm.resource;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.Domain;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
public class MigrateKVMAsync implements Callable<Domain> {
|
||||||
|
|
||||||
|
private final LibvirtComputingResource libvirtComputingResource;
|
||||||
|
|
||||||
|
private Domain dm = null;
|
||||||
|
private Connect dconn = null;
|
||||||
|
private String dxml = "";
|
||||||
|
private String vmName = "";
|
||||||
|
private String destIp = "";
|
||||||
|
|
||||||
|
public MigrateKVMAsync(final LibvirtComputingResource libvirtComputingResource, final Domain dm, final Connect dconn, final String dxml, final String vmName, final String destIp) {
|
||||||
|
this.libvirtComputingResource = libvirtComputingResource;
|
||||||
|
|
||||||
|
this.dm = dm;
|
||||||
|
this.dconn = dconn;
|
||||||
|
this.dxml = dxml;
|
||||||
|
this.vmName = vmName;
|
||||||
|
this.destIp = destIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Domain call() throws LibvirtException {
|
||||||
|
// set compression flag for migration if libvirt version supports it
|
||||||
|
if (dconn.getLibVirVersion() < 1003000) {
|
||||||
|
return dm.migrate(dconn, 1 << 0, dxml, vmName, "tcp:" + destIp, libvirtComputingResource.getMigrateSpeed());
|
||||||
|
} else {
|
||||||
|
return dm.migrate(dconn, 1 << 0|1 << 11, dxml, vmName, "tcp:" + destIp, libvirtComputingResource.getMigrateSpeed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.AttachIsoCommand;
|
||||||
|
import com.cloud.exception.InternalErrorException;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtAttachIsoCommandWrapper extends CommandWrapper<AttachIsoCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final AttachIsoCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(command.getVmName());
|
||||||
|
libvirtComputingResource.attachOrDetachISO(conn, command.getVmName(), command.getIsoPath(), command.isAttach());
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
return new Answer(command, false, e.toString());
|
||||||
|
} catch (final URISyntaxException e) {
|
||||||
|
return new Answer(command, false, e.toString());
|
||||||
|
} catch (final InternalErrorException e) {
|
||||||
|
return new Answer(command, false, e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Answer(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.AttachVolumeAnswer;
|
||||||
|
import com.cloud.agent.api.AttachVolumeCommand;
|
||||||
|
import com.cloud.exception.InternalErrorException;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtAttachVolumeCommandWrapper extends CommandWrapper<AttachVolumeCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final AttachVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(command.getVmName());
|
||||||
|
|
||||||
|
final KVMStoragePool primary = libvirtComputingResource.getStoragePoolMgr().getStoragePool(command.getPooltype(), command.getPoolUuid());
|
||||||
|
final KVMPhysicalDisk disk = primary.getPhysicalDisk(command.getVolumePath());
|
||||||
|
|
||||||
|
libvirtComputingResource.attachOrDetachDisk(conn, command.getAttach(), command.getVmName(), disk,
|
||||||
|
command.getDeviceId().intValue(), command.getBytesReadRate(), command.getBytesWriteRate(), command.getIopsReadRate(), command.getIopsWriteRate(),
|
||||||
|
command.getCacheMode());
|
||||||
|
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
return new AttachVolumeAnswer(command, e.toString());
|
||||||
|
} catch (final InternalErrorException e) {
|
||||||
|
return new AttachVolumeAnswer(command, e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AttachVolumeAnswer(command, command.getDeviceId(), command.getVolumePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,204 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.Domain;
|
||||||
|
import org.libvirt.DomainInfo.DomainState;
|
||||||
|
import org.libvirt.DomainSnapshot;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.ceph.rados.IoCTX;
|
||||||
|
import com.ceph.rados.Rados;
|
||||||
|
import com.ceph.rados.RadosException;
|
||||||
|
import com.ceph.rbd.Rbd;
|
||||||
|
import com.ceph.rbd.RbdException;
|
||||||
|
import com.ceph.rbd.RbdImage;
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.BackupSnapshotAnswer;
|
||||||
|
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtBackupSnapshotCommandWrapper extends CommandWrapper<BackupSnapshotCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtBackupSnapshotCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final BackupSnapshotCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final Long dcId = command.getDataCenterId();
|
||||||
|
final Long accountId = command.getAccountId();
|
||||||
|
final Long volumeId = command.getVolumeId();
|
||||||
|
final String secondaryStoragePoolUrl = command.getSecondaryStorageUrl();
|
||||||
|
final String snapshotName = command.getSnapshotName();
|
||||||
|
String snapshotDestPath = null;
|
||||||
|
String snapshotRelPath = null;
|
||||||
|
final String vmName = command.getVmName();
|
||||||
|
KVMStoragePool secondaryStoragePool = null;
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
|
||||||
|
|
||||||
|
secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(secondaryStoragePoolUrl);
|
||||||
|
|
||||||
|
final String ssPmountPath = secondaryStoragePool.getLocalPath();
|
||||||
|
snapshotRelPath = File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId;
|
||||||
|
|
||||||
|
snapshotDestPath = ssPmountPath + File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId;
|
||||||
|
final KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(command.getPool().getType(), command.getPrimaryStoragePoolNameLabel());
|
||||||
|
final KVMPhysicalDisk snapshotDisk = primaryPool.getPhysicalDisk(command.getVolumePath());
|
||||||
|
|
||||||
|
final String manageSnapshotPath = libvirtComputingResource.manageSnapshotPath();
|
||||||
|
final int cmdsTimeout = libvirtComputingResource.getCmdsTimeout();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RBD snapshots can't be copied using qemu-img, so we have to use
|
||||||
|
* the Java bindings for librbd here.
|
||||||
|
*
|
||||||
|
* These bindings will read the snapshot and write the contents to
|
||||||
|
* the secondary storage directly
|
||||||
|
*
|
||||||
|
* It will stop doing so if the amount of time spend is longer then
|
||||||
|
* cmds.timeout
|
||||||
|
*/
|
||||||
|
if (primaryPool.getType() == StoragePoolType.RBD) {
|
||||||
|
try {
|
||||||
|
final Rados r = new Rados(primaryPool.getAuthUserName());
|
||||||
|
r.confSet("mon_host", primaryPool.getSourceHost() + ":" + primaryPool.getSourcePort());
|
||||||
|
r.confSet("key", primaryPool.getAuthSecret());
|
||||||
|
r.confSet("client_mount_timeout", "30");
|
||||||
|
r.connect();
|
||||||
|
s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
|
||||||
|
|
||||||
|
final IoCTX io = r.ioCtxCreate(primaryPool.getSourceDir());
|
||||||
|
final Rbd rbd = new Rbd(io);
|
||||||
|
final RbdImage image = rbd.open(snapshotDisk.getName(), snapshotName);
|
||||||
|
final File fh = new File(snapshotDestPath);
|
||||||
|
try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fh));) {
|
||||||
|
final int chunkSize = 4194304;
|
||||||
|
long offset = 0;
|
||||||
|
s_logger.debug("Backuping up RBD snapshot " + snapshotName + " to " + snapshotDestPath);
|
||||||
|
while (true) {
|
||||||
|
final byte[] buf = new byte[chunkSize];
|
||||||
|
final int bytes = image.read(offset, buf, chunkSize);
|
||||||
|
if (bytes <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bos.write(buf, 0, bytes);
|
||||||
|
offset += bytes;
|
||||||
|
}
|
||||||
|
s_logger.debug("Completed backing up RBD snapshot " + snapshotName + " to " + snapshotDestPath + ". Bytes written: " + offset);
|
||||||
|
}catch(final IOException ex)
|
||||||
|
{
|
||||||
|
s_logger.error("BackupSnapshotAnswer:Exception:"+ ex.getMessage());
|
||||||
|
}
|
||||||
|
r.ioCtxDestroy(io);
|
||||||
|
} catch (final RadosException e) {
|
||||||
|
s_logger.error("A RADOS operation failed. The error was: " + e.getMessage());
|
||||||
|
return new BackupSnapshotAnswer(command, false, e.toString(), null, true);
|
||||||
|
} catch (final RbdException e) {
|
||||||
|
s_logger.error("A RBD operation on " + snapshotDisk.getName() + " failed. The error was: " + e.getMessage());
|
||||||
|
return new BackupSnapshotAnswer(command, false, e.toString(), null, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final Script scriptCommand = new Script(manageSnapshotPath, cmdsTimeout, s_logger);
|
||||||
|
scriptCommand.add("-b", snapshotDisk.getPath());
|
||||||
|
scriptCommand.add("-n", snapshotName);
|
||||||
|
scriptCommand.add("-p", snapshotDestPath);
|
||||||
|
scriptCommand.add("-t", snapshotName);
|
||||||
|
final String result = scriptCommand.execute();
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
s_logger.debug("Failed to backup snaptshot: " + result);
|
||||||
|
return new BackupSnapshotAnswer(command, false, result, null, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Delete the snapshot on primary */
|
||||||
|
|
||||||
|
DomainState state = null;
|
||||||
|
Domain vm = null;
|
||||||
|
if (vmName != null) {
|
||||||
|
try {
|
||||||
|
vm = libvirtComputingResource.getDomain(conn, command.getVmName());
|
||||||
|
state = vm.getInfo().state;
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.trace("Ignoring libvirt error.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final KVMStoragePool primaryStorage = storagePoolMgr.getStoragePool(command.getPool().getType(), command.getPool().getUuid());
|
||||||
|
|
||||||
|
if (state == DomainState.VIR_DOMAIN_RUNNING && !primaryStorage.isExternalSnapshot()) {
|
||||||
|
final MessageFormat snapshotXML = new MessageFormat(" <domainsnapshot>" + " <name>{0}</name>" + " <domain>"
|
||||||
|
+ " <uuid>{1}</uuid>" + " </domain>" + " </domainsnapshot>");
|
||||||
|
|
||||||
|
final String vmUuid = vm.getUUIDString();
|
||||||
|
final Object[] args = new Object[] {snapshotName, vmUuid};
|
||||||
|
final String snapshot = snapshotXML.format(args);
|
||||||
|
s_logger.debug(snapshot);
|
||||||
|
final DomainSnapshot snap = vm.snapshotLookupByName(snapshotName);
|
||||||
|
snap.delete(0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libvirt on RHEL6 doesn't handle resume event emitted from
|
||||||
|
* qemu
|
||||||
|
*/
|
||||||
|
vm = libvirtComputingResource.getDomain(conn, command.getVmName());
|
||||||
|
state = vm.getInfo().state;
|
||||||
|
if (state == DomainState.VIR_DOMAIN_PAUSED) {
|
||||||
|
vm.resume();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final Script scriptCommand = new Script(manageSnapshotPath, cmdsTimeout, s_logger);
|
||||||
|
scriptCommand.add("-d", snapshotDisk.getPath());
|
||||||
|
scriptCommand.add("-n", snapshotName);
|
||||||
|
final String result = scriptCommand.execute();
|
||||||
|
if (result != null) {
|
||||||
|
s_logger.debug("Failed to backup snapshot: " + result);
|
||||||
|
return new BackupSnapshotAnswer(command, false, "Failed to backup snapshot: " + result, null, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
return new BackupSnapshotAnswer(command, false, e.toString(), null, true);
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
return new BackupSnapshotAnswer(command, false, e.toString(), null, true);
|
||||||
|
} finally {
|
||||||
|
if (secondaryStoragePool != null) {
|
||||||
|
storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(), secondaryStoragePool.getUuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new BackupSnapshotAnswer(command, true, null, snapshotRelPath + File.separator + snapshotName, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
|
||||||
|
public class LibvirtCheckConsoleProxyLoadCommandWrapper extends LibvirtConsoleProxyLoadCommandWrapper<CheckConsoleProxyLoadCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final Command command, final ServerResource serverResource) {
|
||||||
|
final CheckConsoleProxyLoadCommand cmd = (CheckConsoleProxyLoadCommand) command;
|
||||||
|
|
||||||
|
final long proxyVmId = cmd.getProxyVmId();
|
||||||
|
final String proxyVmName = cmd.getProxyVmName();
|
||||||
|
final String proxyManagementIp = cmd.getProxyManagementIp();
|
||||||
|
final int proxyCmdPort = cmd.getProxyCmdPort();
|
||||||
|
|
||||||
|
return executeProxyLoadScan(cmd, proxyVmId, proxyVmName, proxyManagementIp, proxyCmdPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CheckHealthAnswer;
|
||||||
|
import com.cloud.agent.api.CheckHealthCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtCheckHealthCommandWrapper extends CommandWrapper<CheckHealthCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CheckHealthCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
return new CheckHealthAnswer(command, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CheckNetworkAnswer;
|
||||||
|
import com.cloud.agent.api.CheckNetworkCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.network.PhysicalNetworkSetupInfo;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtCheckNetworkCommandWrapper extends CommandWrapper<CheckNetworkCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CheckNetworkCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final List<PhysicalNetworkSetupInfo> phyNics = command.getPhysicalNetworkInfoList();
|
||||||
|
String errMsg = null;
|
||||||
|
|
||||||
|
for (final PhysicalNetworkSetupInfo nic : phyNics) {
|
||||||
|
if (!libvirtComputingResource.checkNetwork(nic.getGuestNetworkName())) {
|
||||||
|
errMsg = "Can not find network: " + nic.getGuestNetworkName();
|
||||||
|
break;
|
||||||
|
} else if (!libvirtComputingResource.checkNetwork(nic.getPrivateNetworkName())) {
|
||||||
|
errMsg = "Can not find network: " + nic.getPrivateNetworkName();
|
||||||
|
break;
|
||||||
|
} else if (!libvirtComputingResource.checkNetwork(nic.getPublicNetworkName())) {
|
||||||
|
errMsg = "Can not find network: " + nic.getPublicNetworkName();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errMsg != null) {
|
||||||
|
return new CheckNetworkAnswer(command, false, errMsg);
|
||||||
|
} else {
|
||||||
|
return new CheckNetworkAnswer(command, true, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CheckOnHostCommand;
|
||||||
|
import com.cloud.agent.api.to.HostTO;
|
||||||
|
import com.cloud.agent.api.to.NetworkTO;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.KVMHABase.NfsStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.KVMHAChecker;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.KVMHAMonitor;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtCheckOnHostCommandWrapper extends CommandWrapper<CheckOnHostCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CheckOnHostCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final ExecutorService executors = Executors.newSingleThreadExecutor();
|
||||||
|
final KVMHAMonitor monitor = libvirtComputingResource.getMonitor();
|
||||||
|
|
||||||
|
final List<NfsStoragePool> pools = monitor.getStoragePools();
|
||||||
|
HostTO host = command.getHost();
|
||||||
|
NetworkTO privateNetwork = host.getPrivateNetwork();
|
||||||
|
final KVMHAChecker ha = new KVMHAChecker(pools, privateNetwork.getIp());
|
||||||
|
|
||||||
|
final Future<Boolean> future = executors.submit(ha);
|
||||||
|
try {
|
||||||
|
final Boolean result = future.get();
|
||||||
|
if (result) {
|
||||||
|
return new Answer(command, false, "Heart is still beating...");
|
||||||
|
} else {
|
||||||
|
return new Answer(command);
|
||||||
|
}
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
return new Answer(command, false, "can't get status of host:");
|
||||||
|
} catch (final ExecutionException e) {
|
||||||
|
return new Answer(command, false, "can't get status of host:");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.check.CheckSshAnswer;
|
||||||
|
import com.cloud.agent.api.check.CheckSshCommand;
|
||||||
|
import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtCheckSshCommandWrapper extends CommandWrapper<CheckSshCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtOvsVpcRoutingPolicyConfigCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CheckSshCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final String vmName = command.getName();
|
||||||
|
final String privateIp = command.getIp();
|
||||||
|
final int cmdPort = command.getPort();
|
||||||
|
|
||||||
|
if (s_logger.isDebugEnabled()) {
|
||||||
|
s_logger.debug("Ping command port, " + privateIp + ":" + cmdPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
final VirtualRoutingResource virtRouterResource = libvirtComputingResource.getVirtRouterResource();
|
||||||
|
if (!virtRouterResource.connect(privateIp, cmdPort)) {
|
||||||
|
return new CheckSshAnswer(command, "Can not ping System vm " + vmName + " because of a connection failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_logger.isDebugEnabled()) {
|
||||||
|
s_logger.debug("Ping command port succeeded for vm " + vmName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CheckSshAnswer(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CheckVirtualMachineAnswer;
|
||||||
|
import com.cloud.agent.api.CheckVirtualMachineCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.vm.VirtualMachine.PowerState;
|
||||||
|
|
||||||
|
public final class LibvirtCheckVirtualMachineCommandWrapper extends CommandWrapper<CheckVirtualMachineCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CheckVirtualMachineCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(command.getVmName());
|
||||||
|
final PowerState state = libvirtComputingResource.getVmState(conn, command.getVmName());
|
||||||
|
Integer vncPort = null;
|
||||||
|
if (state == PowerState.PowerOn) {
|
||||||
|
vncPort = libvirtComputingResource.getVncPort(conn, command.getVmName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CheckVirtualMachineAnswer(command, state, vncPort);
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
return new CheckVirtualMachineAnswer(command, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CleanupNetworkRulesCmd;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtCleanupNetworkRulesCommandWrapper extends CommandWrapper<CleanupNetworkRulesCmd, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CleanupNetworkRulesCmd command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final boolean result = libvirtComputingResource.cleanupRules();
|
||||||
|
return new Answer(command, result, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
|
||||||
|
public abstract class LibvirtConsoleProxyLoadCommandWrapper<T extends Command, A extends Answer, R extends ServerResource> extends CommandWrapper<Command, Answer, ServerResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtConsoleProxyLoadCommandWrapper.class);
|
||||||
|
|
||||||
|
public Answer executeProxyLoadScan(final Command cmd, final long proxyVmId, final String proxyVmName, final String proxyManagementIp, final int cmdPort) {
|
||||||
|
String result = null;
|
||||||
|
|
||||||
|
final StringBuffer sb = new StringBuffer();
|
||||||
|
sb.append("http://").append(proxyManagementIp).append(":" + cmdPort).append("/cmd/getstatus");
|
||||||
|
|
||||||
|
boolean success = true;
|
||||||
|
try {
|
||||||
|
final URL url = new URL(sb.toString());
|
||||||
|
final URLConnection conn = url.openConnection();
|
||||||
|
|
||||||
|
final InputStream is = conn.getInputStream();
|
||||||
|
final BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||||
|
final StringBuilder sb2 = new StringBuilder();
|
||||||
|
String line = null;
|
||||||
|
try {
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
sb2.append(line + "\n");
|
||||||
|
}
|
||||||
|
result = sb2.toString();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
success = false;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
is.close();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
s_logger.warn("Exception when closing , console proxy address : " + proxyManagementIp);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (final IOException e) {
|
||||||
|
s_logger.warn("Unable to open console proxy command port url, console proxy address : " + proxyManagementIp);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ConsoleProxyLoadAnswer(cmd, proxyVmId, proxyVmName, success, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.storage.CopyVolumeAnswer;
|
||||||
|
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||||
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
|
public final class LibvirtCopyVolumeCommandWrapper extends CommandWrapper<CopyVolumeCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CopyVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
/**
|
||||||
|
* This method is only used for copying files from Primary Storage TO
|
||||||
|
* Secondary Storage
|
||||||
|
*
|
||||||
|
* It COULD also do it the other way around, but the code in the
|
||||||
|
* ManagementServerImpl shows that it always sets copyToSecondary to
|
||||||
|
* true
|
||||||
|
*/
|
||||||
|
final boolean copyToSecondary = command.toSecondaryStorage();
|
||||||
|
String volumePath = command.getVolumePath();
|
||||||
|
final StorageFilerTO pool = command.getPool();
|
||||||
|
final String secondaryStorageUrl = command.getSecondaryStorageURL();
|
||||||
|
KVMStoragePool secondaryStoragePool = null;
|
||||||
|
KVMStoragePool primaryPool = null;
|
||||||
|
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
primaryPool = storagePoolMgr.getStoragePool(pool.getType(), pool.getUuid());
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
if (e.getMessage().contains("not found")) {
|
||||||
|
primaryPool = storagePoolMgr.createStoragePool(pool.getUuid(), pool.getHost(), pool.getPort(), pool.getPath(), pool.getUserInfo(), pool.getType());
|
||||||
|
} else {
|
||||||
|
return new CopyVolumeAnswer(command, false, e.getMessage(), null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
final String volumeName = libvirtUtilitiesHelper.generatereUUIDName();
|
||||||
|
|
||||||
|
if (copyToSecondary) {
|
||||||
|
final String destVolumeName = volumeName + ".qcow2";
|
||||||
|
final KVMPhysicalDisk volume = primaryPool.getPhysicalDisk(command.getVolumePath());
|
||||||
|
final String volumeDestPath = "/volumes/" + command.getVolumeId() + File.separator;
|
||||||
|
|
||||||
|
secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(secondaryStorageUrl);
|
||||||
|
secondaryStoragePool.createFolder(volumeDestPath);
|
||||||
|
storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(), secondaryStoragePool.getUuid());
|
||||||
|
secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(secondaryStorageUrl + volumeDestPath);
|
||||||
|
storagePoolMgr.copyPhysicalDisk(volume, destVolumeName, secondaryStoragePool, 0);
|
||||||
|
|
||||||
|
return new CopyVolumeAnswer(command, true, null, null, volumeName);
|
||||||
|
} else {
|
||||||
|
volumePath = "/volumes/" + command.getVolumeId() + File.separator;
|
||||||
|
secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(secondaryStorageUrl + volumePath);
|
||||||
|
|
||||||
|
final KVMPhysicalDisk volume = secondaryStoragePool.getPhysicalDisk(command.getVolumePath() + ".qcow2");
|
||||||
|
storagePoolMgr.copyPhysicalDisk(volume, volumeName, primaryPool, 0);
|
||||||
|
|
||||||
|
return new CopyVolumeAnswer(command, true, null, null, volumeName);
|
||||||
|
}
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
return new CopyVolumeAnswer(command, false, e.toString(), null, null);
|
||||||
|
} finally {
|
||||||
|
if (secondaryStoragePool != null) {
|
||||||
|
storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(), secondaryStoragePool.getUuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.storage.CreateAnswer;
|
||||||
|
import com.cloud.agent.api.storage.CreateCommand;
|
||||||
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
|
import com.cloud.agent.api.to.VolumeTO;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.vm.DiskProfile;
|
||||||
|
|
||||||
|
public final class LibvirtCreateCommandWrapper extends CommandWrapper<CreateCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtCreateCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CreateCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final StorageFilerTO pool = command.getPool();
|
||||||
|
final DiskProfile dskch = command.getDiskCharacteristics();
|
||||||
|
KVMPhysicalDisk baseVol = null;
|
||||||
|
KVMStoragePool primaryPool = null;
|
||||||
|
KVMPhysicalDisk vol = null;
|
||||||
|
long disksize;
|
||||||
|
try {
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
primaryPool = storagePoolMgr.getStoragePool(pool.getType(), pool.getUuid());
|
||||||
|
disksize = dskch.getSize();
|
||||||
|
|
||||||
|
if (command.getTemplateUrl() != null) {
|
||||||
|
if (primaryPool.getType() == StoragePoolType.CLVM) {
|
||||||
|
vol = libvirtComputingResource.templateToPrimaryDownload(command.getTemplateUrl(), primaryPool, dskch.getPath());
|
||||||
|
} else {
|
||||||
|
baseVol = primaryPool.getPhysicalDisk(command.getTemplateUrl());
|
||||||
|
vol = storagePoolMgr.createDiskFromTemplate(baseVol,
|
||||||
|
dskch.getPath(), dskch.getProvisioningType(), primaryPool, 0);
|
||||||
|
}
|
||||||
|
if (vol == null) {
|
||||||
|
return new Answer(command, false, " Can't create storage volume on storage pool");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vol = primaryPool.createPhysicalDisk(dskch.getPath(), dskch.getProvisioningType(), dskch.getSize());
|
||||||
|
}
|
||||||
|
final VolumeTO volume =
|
||||||
|
new VolumeTO(command.getVolumeId(), dskch.getType(), pool.getType(), pool.getUuid(), pool.getPath(), vol.getName(), vol.getName(), disksize, null);
|
||||||
|
|
||||||
|
volume.setBytesReadRate(dskch.getBytesReadRate());
|
||||||
|
volume.setBytesWriteRate(dskch.getBytesWriteRate());
|
||||||
|
volume.setIopsReadRate(dskch.getIopsReadRate());
|
||||||
|
volume.setIopsWriteRate(dskch.getIopsWriteRate());
|
||||||
|
volume.setCacheMode(dskch.getCacheMode());
|
||||||
|
return new CreateAnswer(command, volume);
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
s_logger.debug("Failed to create volume: " + e.toString());
|
||||||
|
return new CreateAnswer(command, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
|
||||||
|
import com.cloud.exception.InternalErrorException;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.storage.StorageLayer;
|
||||||
|
import com.cloud.storage.template.Processor;
|
||||||
|
import com.cloud.storage.template.Processor.FormatInfo;
|
||||||
|
import com.cloud.storage.template.TemplateLocation;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtCreatePrivateTemplateFromSnapshotCommandWrapper extends CommandWrapper<CreatePrivateTemplateFromSnapshotCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtCreatePrivateTemplateFromSnapshotCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CreatePrivateTemplateFromSnapshotCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final String templateFolder = command.getAccountId() + File.separator + command.getNewTemplateId();
|
||||||
|
final String templateInstallFolder = "template/tmpl/" + templateFolder;
|
||||||
|
final String tmplName = libvirtUtilitiesHelper.generatereUUIDName();
|
||||||
|
final String tmplFileName = tmplName + ".qcow2";
|
||||||
|
|
||||||
|
KVMStoragePool secondaryPool = null;
|
||||||
|
KVMStoragePool snapshotPool = null;
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
|
||||||
|
try {
|
||||||
|
String snapshotPath = command.getSnapshotUuid();
|
||||||
|
final int index = snapshotPath.lastIndexOf("/");
|
||||||
|
snapshotPath = snapshotPath.substring(0, index);
|
||||||
|
|
||||||
|
snapshotPool = storagePoolMgr.getStoragePoolByURI(command.getSecondaryStorageUrl() + snapshotPath);
|
||||||
|
secondaryPool = storagePoolMgr.getStoragePoolByURI(command.getSecondaryStorageUrl());
|
||||||
|
|
||||||
|
final KVMPhysicalDisk snapshot = snapshotPool.getPhysicalDisk(command.getSnapshotName());
|
||||||
|
|
||||||
|
final String templatePath = secondaryPool.getLocalPath() + File.separator + templateInstallFolder;
|
||||||
|
|
||||||
|
final StorageLayer storage = libvirtComputingResource.getStorage();
|
||||||
|
storage.mkdirs(templatePath);
|
||||||
|
|
||||||
|
final String tmplPath = templateInstallFolder + File.separator + tmplFileName;
|
||||||
|
final String createTmplPath = libvirtComputingResource.createTmplPath();
|
||||||
|
final int cmdsTimeout = libvirtComputingResource.getCmdsTimeout();
|
||||||
|
|
||||||
|
final Script scriptCommand = new Script(createTmplPath, cmdsTimeout, s_logger);
|
||||||
|
scriptCommand.add("-t", templatePath);
|
||||||
|
scriptCommand.add("-n", tmplFileName);
|
||||||
|
scriptCommand.add("-f", snapshot.getPath());
|
||||||
|
scriptCommand.execute();
|
||||||
|
|
||||||
|
final Processor qcow2Processor = libvirtUtilitiesHelper.buildQCOW2Processor(storage);
|
||||||
|
final FormatInfo info = qcow2Processor.process(templatePath, null, tmplName);
|
||||||
|
final TemplateLocation loc = libvirtUtilitiesHelper.buildTemplateLocation(storage, templatePath);
|
||||||
|
|
||||||
|
loc.create(1, true, tmplName);
|
||||||
|
loc.addFormat(info);
|
||||||
|
loc.save();
|
||||||
|
|
||||||
|
return new CreatePrivateTemplateAnswer(command, true, "", tmplPath, info.virtualSize, info.size, tmplName, info.format);
|
||||||
|
} catch (final ConfigurationException e) {
|
||||||
|
return new CreatePrivateTemplateAnswer(command, false, e.getMessage());
|
||||||
|
} catch (final InternalErrorException e) {
|
||||||
|
return new CreatePrivateTemplateAnswer(command, false, e.getMessage());
|
||||||
|
} catch (final IOException e) {
|
||||||
|
return new CreatePrivateTemplateAnswer(command, false, e.getMessage());
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
return new CreatePrivateTemplateAnswer(command, false, e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (secondaryPool != null) {
|
||||||
|
storagePoolMgr.deleteStoragePool(secondaryPool.getType(), secondaryPool.getUuid());
|
||||||
|
}
|
||||||
|
if (snapshotPool != null) {
|
||||||
|
storagePoolMgr.deleteStoragePool(snapshotPool.getType(), snapshotPool.getUuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,176 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.utils.qemu.QemuImg;
|
||||||
|
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
|
||||||
|
import org.apache.cloudstack.utils.qemu.QemuImgException;
|
||||||
|
import org.apache.cloudstack.utils.qemu.QemuImgFile;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
|
||||||
|
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
|
||||||
|
import com.cloud.exception.InternalErrorException;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.storage.Storage.ImageFormat;
|
||||||
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
|
import com.cloud.storage.StorageLayer;
|
||||||
|
import com.cloud.storage.template.Processor;
|
||||||
|
import com.cloud.storage.template.Processor.FormatInfo;
|
||||||
|
import com.cloud.storage.template.QCOW2Processor;
|
||||||
|
import com.cloud.storage.template.TemplateLocation;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtCreatePrivateTemplateFromVolumeCommandWrapper extends CommandWrapper<CreatePrivateTemplateFromVolumeCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtCreatePrivateTemplateFromVolumeCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CreatePrivateTemplateFromVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final String secondaryStorageURL = command.getSecondaryStorageUrl();
|
||||||
|
|
||||||
|
KVMStoragePool secondaryStorage = null;
|
||||||
|
KVMStoragePool primary = null;
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
try {
|
||||||
|
final String templateFolder = command.getAccountId() + File.separator + command.getTemplateId() + File.separator;
|
||||||
|
final String templateInstallFolder = "/template/tmpl/" + templateFolder;
|
||||||
|
|
||||||
|
secondaryStorage = storagePoolMgr.getStoragePoolByURI(secondaryStorageURL);
|
||||||
|
|
||||||
|
try {
|
||||||
|
primary = storagePoolMgr.getStoragePool(command.getPool().getType(), command.getPrimaryStoragePoolNameLabel());
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
if (e.getMessage().contains("not found")) {
|
||||||
|
primary =
|
||||||
|
storagePoolMgr.createStoragePool(command.getPool().getUuid(), command.getPool().getHost(), command.getPool().getPort(), command.getPool().getPath(),
|
||||||
|
command.getPool().getUserInfo(), command.getPool().getType());
|
||||||
|
} else {
|
||||||
|
return new CreatePrivateTemplateAnswer(command, false, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final KVMPhysicalDisk disk = primary.getPhysicalDisk(command.getVolumePath());
|
||||||
|
final String tmpltPath = secondaryStorage.getLocalPath() + File.separator + templateInstallFolder;
|
||||||
|
final StorageLayer storage = libvirtComputingResource.getStorage();
|
||||||
|
storage.mkdirs(tmpltPath);
|
||||||
|
|
||||||
|
if (primary.getType() != StoragePoolType.RBD) {
|
||||||
|
final String createTmplPath = libvirtComputingResource.createTmplPath();
|
||||||
|
final int cmdsTimeout = libvirtComputingResource.getCmdsTimeout();
|
||||||
|
|
||||||
|
final Script scriptCommand = new Script(createTmplPath, cmdsTimeout, s_logger);
|
||||||
|
scriptCommand.add("-f", disk.getPath());
|
||||||
|
scriptCommand.add("-t", tmpltPath);
|
||||||
|
scriptCommand.add("-n", command.getUniqueName() + ".qcow2");
|
||||||
|
|
||||||
|
final String result = scriptCommand.execute();
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
s_logger.debug("failed to create template: " + result);
|
||||||
|
return new CreatePrivateTemplateAnswer(command, false, result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + command.getUniqueName());
|
||||||
|
|
||||||
|
final QemuImgFile srcFile =
|
||||||
|
new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(), primary.getSourcePort(), primary.getAuthUserName(),
|
||||||
|
primary.getAuthSecret(), disk.getPath()));
|
||||||
|
srcFile.setFormat(PhysicalDiskFormat.RAW);
|
||||||
|
|
||||||
|
final QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + command.getUniqueName() + ".qcow2");
|
||||||
|
destFile.setFormat(PhysicalDiskFormat.QCOW2);
|
||||||
|
|
||||||
|
final QemuImg q = new QemuImg(0);
|
||||||
|
try {
|
||||||
|
q.convert(srcFile, destFile);
|
||||||
|
} catch (final QemuImgException e) {
|
||||||
|
s_logger.error("Failed to create new template while converting " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " +
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
final File templateProp = new File(tmpltPath + "/template.properties");
|
||||||
|
if (!templateProp.exists()) {
|
||||||
|
templateProp.createNewFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
String templateContent = "filename=" + command.getUniqueName() + ".qcow2" + System.getProperty("line.separator");
|
||||||
|
|
||||||
|
final DateFormat dateFormat = new SimpleDateFormat("MM_dd_yyyy");
|
||||||
|
final Date date = new Date();
|
||||||
|
templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
|
||||||
|
|
||||||
|
try(FileOutputStream templFo = new FileOutputStream(templateProp);) {
|
||||||
|
templFo.write(templateContent.getBytes());
|
||||||
|
templFo.flush();
|
||||||
|
}catch(final IOException ex)
|
||||||
|
{
|
||||||
|
s_logger.error("CreatePrivateTemplateAnswer:Exception:"+ex.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, Object> params = new HashMap<String, Object>();
|
||||||
|
params.put(StorageLayer.InstanceConfigKey, storage);
|
||||||
|
final Processor qcow2Processor = new QCOW2Processor();
|
||||||
|
|
||||||
|
qcow2Processor.configure("QCOW2 Processor", params);
|
||||||
|
|
||||||
|
final FormatInfo info = qcow2Processor.process(tmpltPath, null, command.getUniqueName());
|
||||||
|
|
||||||
|
final TemplateLocation loc = new TemplateLocation(storage, tmpltPath);
|
||||||
|
loc.create(1, true, command.getUniqueName());
|
||||||
|
loc.addFormat(info);
|
||||||
|
loc.save();
|
||||||
|
|
||||||
|
return new CreatePrivateTemplateAnswer(command, true, null, templateInstallFolder + command.getUniqueName() + ".qcow2", info.virtualSize, info.size,
|
||||||
|
command.getUniqueName(), ImageFormat.QCOW2);
|
||||||
|
} catch (final InternalErrorException e) {
|
||||||
|
return new CreatePrivateTemplateAnswer(command, false, e.toString());
|
||||||
|
} catch (final IOException e) {
|
||||||
|
return new CreatePrivateTemplateAnswer(command, false, e.toString());
|
||||||
|
} catch (final ConfigurationException e) {
|
||||||
|
return new CreatePrivateTemplateAnswer(command, false, e.toString());
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
return new CreatePrivateTemplateAnswer(command, false, e.toString());
|
||||||
|
} finally {
|
||||||
|
if (secondaryStorage != null) {
|
||||||
|
storagePoolMgr.deleteStoragePool(secondaryStorage.getType(), secondaryStorage.getUuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CreateStoragePoolCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtCreateStoragePoolCommandWrapper extends CommandWrapper<CreateStoragePoolCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CreateStoragePoolCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
return new Answer(command, true, "success");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer;
|
||||||
|
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
|
public final class LibvirtCreateVolumeFromSnapshotCommandWrapper extends CommandWrapper<CreateVolumeFromSnapshotCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final CreateVolumeFromSnapshotCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
String snapshotPath = command.getSnapshotUuid();
|
||||||
|
final int index = snapshotPath.lastIndexOf("/");
|
||||||
|
snapshotPath = snapshotPath.substring(0, index);
|
||||||
|
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
final KVMStoragePool secondaryPool = storagePoolMgr.getStoragePoolByURI(command.getSecondaryStorageUrl() + snapshotPath);
|
||||||
|
final KVMPhysicalDisk snapshot = secondaryPool.getPhysicalDisk(command.getSnapshotName());
|
||||||
|
|
||||||
|
final String primaryUuid = command.getPrimaryStoragePoolNameLabel();
|
||||||
|
|
||||||
|
final StorageFilerTO pool = command.getPool();
|
||||||
|
final KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(pool.getType(), primaryUuid);
|
||||||
|
|
||||||
|
final String volUuid = UUID.randomUUID().toString();
|
||||||
|
final KVMPhysicalDisk disk = storagePoolMgr.copyPhysicalDisk(snapshot, volUuid, primaryPool, 0);
|
||||||
|
|
||||||
|
if (disk == null) {
|
||||||
|
throw new NullPointerException("Disk was not successfully copied to the new storage.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CreateVolumeFromSnapshotAnswer(command, true, "", disk.getName());
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
return new CreateVolumeFromSnapshotAnswer(command, false, e.toString(), null);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
return new CreateVolumeFromSnapshotAnswer(command, false, e.toString(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.DeleteStoragePoolCommand;
|
||||||
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
|
public final class LibvirtDeleteStoragePoolCommandWrapper extends CommandWrapper<DeleteStoragePoolCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final DeleteStoragePoolCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
try {
|
||||||
|
StorageFilerTO pool = command.getPool();
|
||||||
|
KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
storagePoolMgr.deleteStoragePool(pool.getType(), pool.getUuid());
|
||||||
|
return new Answer(command);
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
return new Answer(command, false, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.storage.DestroyCommand;
|
||||||
|
import com.cloud.agent.api.to.VolumeTO;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
|
public final class LibvirtDestroyCommandWrapper extends CommandWrapper<DestroyCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtDestroyCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final DestroyCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final VolumeTO vol = command.getVolume();
|
||||||
|
try {
|
||||||
|
KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
final KVMStoragePool pool = storagePoolMgr.getStoragePool(vol.getPoolType(), vol.getPoolUuid());
|
||||||
|
pool.deletePhysicalDisk(vol.getPath(), null);
|
||||||
|
return new Answer(command, true, "Success");
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
s_logger.debug("Failed to delete volume: " + e.toString());
|
||||||
|
return new Answer(command, false, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.FenceAnswer;
|
||||||
|
import com.cloud.agent.api.FenceCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.KVMHABase.NfsStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.KVMHAChecker;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.KVMHAMonitor;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtFenceCommandWrapper extends CommandWrapper<FenceCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtFenceCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final FenceCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final ExecutorService executors = Executors.newSingleThreadExecutor();
|
||||||
|
final KVMHAMonitor monitor = libvirtComputingResource.getMonitor();
|
||||||
|
|
||||||
|
final List<NfsStoragePool> pools = monitor.getStoragePools();
|
||||||
|
final KVMHAChecker ha = new KVMHAChecker(pools, command.getHostIp());
|
||||||
|
|
||||||
|
final Future<Boolean> future = executors.submit(ha);
|
||||||
|
try {
|
||||||
|
final Boolean result = future.get();
|
||||||
|
if (result) {
|
||||||
|
return new FenceAnswer(command, false, "Heart is still beating...");
|
||||||
|
} else {
|
||||||
|
return new FenceAnswer(command);
|
||||||
|
}
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
s_logger.warn("Unable to fence", e);
|
||||||
|
return new FenceAnswer(command, false, e.getMessage());
|
||||||
|
} catch (final ExecutionException e) {
|
||||||
|
s_logger.warn("Unable to fence", e);
|
||||||
|
return new FenceAnswer(command, false, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.GetHostStatsAnswer;
|
||||||
|
import com.cloud.agent.api.GetHostStatsCommand;
|
||||||
|
import com.cloud.agent.api.HostStatsEntry;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.Pair;
|
||||||
|
import com.cloud.utils.script.OutputInterpreter;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtGetHostStatsCommandWrapper extends CommandWrapper<GetHostStatsCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtGetHostStatsCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final GetHostStatsCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final Script cpuScript = new Script("/bin/bash", s_logger);
|
||||||
|
cpuScript.add("-c");
|
||||||
|
cpuScript.add("idle=$(top -b -n 1| awk -F, '/^[%]*[Cc]pu/{$0=$4; gsub(/[^0-9.,]+/,\"\"); print }'); echo $idle");
|
||||||
|
|
||||||
|
final OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser();
|
||||||
|
String result = cpuScript.execute(parser);
|
||||||
|
if (result != null) {
|
||||||
|
s_logger.debug("Unable to get the host CPU state: " + result);
|
||||||
|
return new Answer(command, false, result);
|
||||||
|
}
|
||||||
|
final double cpuUtil = 100.0D - Double.parseDouble(parser.getLine());
|
||||||
|
|
||||||
|
long freeMem = 0;
|
||||||
|
final Script memScript = new Script("/bin/bash", s_logger);
|
||||||
|
memScript.add("-c");
|
||||||
|
memScript.add("freeMem=$(free|grep cache:|awk '{print $4}');echo $freeMem");
|
||||||
|
final OutputInterpreter.OneLineParser Memparser = new OutputInterpreter.OneLineParser();
|
||||||
|
result = memScript.execute(Memparser);
|
||||||
|
if (result != null) {
|
||||||
|
s_logger.debug("Unable to get the host Mem state: " + result);
|
||||||
|
return new Answer(command, false, result);
|
||||||
|
}
|
||||||
|
freeMem = Long.parseLong(Memparser.getLine());
|
||||||
|
|
||||||
|
final Script totalMem = new Script("/bin/bash", s_logger);
|
||||||
|
totalMem.add("-c");
|
||||||
|
totalMem.add("free|grep Mem:|awk '{print $2}'");
|
||||||
|
final OutputInterpreter.OneLineParser totMemparser = new OutputInterpreter.OneLineParser();
|
||||||
|
result = totalMem.execute(totMemparser);
|
||||||
|
if (result != null) {
|
||||||
|
s_logger.debug("Unable to get the host Mem state: " + result);
|
||||||
|
return new Answer(command, false, result);
|
||||||
|
}
|
||||||
|
final long totMem = Long.parseLong(totMemparser.getLine());
|
||||||
|
|
||||||
|
final Pair<Double, Double> nicStats = libvirtComputingResource.getNicStats(libvirtComputingResource.getPublicBridgeName());
|
||||||
|
|
||||||
|
final HostStatsEntry hostStats = new HostStatsEntry(command.getHostId(), cpuUtil, nicStats.first() / 1024, nicStats.second() / 1024, "host", totMem, freeMem, 0, 0);
|
||||||
|
return new GetHostStatsAnswer(command, hostStats);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.GetStorageStatsAnswer;
|
||||||
|
import com.cloud.agent.api.GetStorageStatsCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
|
public final class LibvirtGetStorageStatsCommandWrapper extends CommandWrapper<GetStorageStatsCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final GetStorageStatsCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
try {
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
final KVMStoragePool sp = storagePoolMgr.getStoragePool(command.getPooltype(), command.getStorageId(), true);
|
||||||
|
return new GetStorageStatsAnswer(command, sp.getCapacity(), sp.getUsed());
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
return new GetStorageStatsAnswer(command, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.GetVmDiskStatsAnswer;
|
||||||
|
import com.cloud.agent.api.GetVmDiskStatsCommand;
|
||||||
|
import com.cloud.agent.api.VmDiskStatsEntry;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtGetVmDiskStatsCommandWrapper extends CommandWrapper<GetVmDiskStatsCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtGetVmDiskStatsCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final GetVmDiskStatsCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final List<String> vmNames = command.getVmNames();
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final HashMap<String, List<VmDiskStatsEntry>> vmDiskStatsNameMap = new HashMap<String, List<VmDiskStatsEntry>>();
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnection();
|
||||||
|
for (final String vmName : vmNames) {
|
||||||
|
final List<VmDiskStatsEntry> statEntry = libvirtComputingResource.getVmDiskStat(conn, vmName);
|
||||||
|
if (statEntry == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vmDiskStatsNameMap.put(vmName, statEntry);
|
||||||
|
}
|
||||||
|
return new GetVmDiskStatsAnswer(command, "", command.getHostName(), vmDiskStatsNameMap);
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.debug("Can't get vm disk stats: " + e.toString());
|
||||||
|
return new GetVmDiskStatsAnswer(command, null, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.GetVmStatsAnswer;
|
||||||
|
import com.cloud.agent.api.GetVmStatsCommand;
|
||||||
|
import com.cloud.agent.api.VmStatsEntry;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtGetVmStatsCommandWrapper extends CommandWrapper<GetVmStatsCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtGetVmStatsCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final GetVmStatsCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final List<String> vmNames = command.getVmNames();
|
||||||
|
try {
|
||||||
|
final HashMap<String, VmStatsEntry> vmStatsNameMap = new HashMap<String, VmStatsEntry>();
|
||||||
|
for (final String vmName : vmNames) {
|
||||||
|
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
|
||||||
|
final VmStatsEntry statEntry = libvirtComputingResource.getVmStat(conn, vmName);
|
||||||
|
if (statEntry == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vmStatsNameMap.put(vmName, statEntry);
|
||||||
|
}
|
||||||
|
return new GetVmStatsAnswer(command, vmStatsNameMap);
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.debug("Can't get vm stats: " + e.toString());
|
||||||
|
return new GetVmStatsAnswer(command, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.GetVncPortAnswer;
|
||||||
|
import com.cloud.agent.api.GetVncPortCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtGetVncPortCommandWrapper extends CommandWrapper<GetVncPortCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final GetVncPortCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(command.getName());
|
||||||
|
final Integer vncPort = libvirtComputingResource.getVncPort(conn, command.getName());
|
||||||
|
return new GetVncPortAnswer(command, libvirtComputingResource.getPrivateIp(), 5900 + vncPort);
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
return new GetVncPortAnswer(command, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.MaintainAnswer;
|
||||||
|
import com.cloud.agent.api.MaintainCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtMaintainCommandWrapper extends CommandWrapper<MaintainCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final MaintainCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
return new MaintainAnswer(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,167 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.Domain;
|
||||||
|
import org.libvirt.DomainInfo.DomainState;
|
||||||
|
import org.libvirt.DomainSnapshot;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.ceph.rados.IoCTX;
|
||||||
|
import com.ceph.rados.Rados;
|
||||||
|
import com.ceph.rbd.Rbd;
|
||||||
|
import com.ceph.rbd.RbdImage;
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.ManageSnapshotAnswer;
|
||||||
|
import com.cloud.agent.api.ManageSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtManageSnapshotCommandWrapper extends CommandWrapper<ManageSnapshotCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtManageSnapshotCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final ManageSnapshotCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final String snapshotName = command.getSnapshotName();
|
||||||
|
final String snapshotPath = command.getSnapshotPath();
|
||||||
|
final String vmName = command.getVmName();
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
|
||||||
|
DomainState state = null;
|
||||||
|
Domain vm = null;
|
||||||
|
if (vmName != null) {
|
||||||
|
try {
|
||||||
|
vm = libvirtComputingResource.getDomain(conn, command.getVmName());
|
||||||
|
state = vm.getInfo().state;
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.trace("Ignoring libvirt error.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
StorageFilerTO pool = command.getPool();
|
||||||
|
final KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(pool.getType(), pool.getUuid());
|
||||||
|
|
||||||
|
final KVMPhysicalDisk disk = primaryPool.getPhysicalDisk(command.getVolumePath());
|
||||||
|
if (state == DomainState.VIR_DOMAIN_RUNNING && !primaryPool.isExternalSnapshot()) {
|
||||||
|
|
||||||
|
final MessageFormat snapshotXML = new MessageFormat(" <domainsnapshot>" + " <name>{0}</name>" + " <domain>"
|
||||||
|
+ " <uuid>{1}</uuid>" + " </domain>" + " </domainsnapshot>");
|
||||||
|
|
||||||
|
final String vmUuid = vm.getUUIDString();
|
||||||
|
final Object[] args = new Object[] {snapshotName, vmUuid};
|
||||||
|
final String snapshot = snapshotXML.format(args);
|
||||||
|
s_logger.debug(snapshot);
|
||||||
|
if (command.getCommandSwitch().equalsIgnoreCase(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
|
||||||
|
vm.snapshotCreateXML(snapshot);
|
||||||
|
} else {
|
||||||
|
final DomainSnapshot snap = vm.snapshotLookupByName(snapshotName);
|
||||||
|
snap.delete(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* libvirt on RHEL6 doesn't handle resume event emitted from
|
||||||
|
* qemu
|
||||||
|
*/
|
||||||
|
vm = libvirtComputingResource.getDomain(conn, command.getVmName());
|
||||||
|
state = vm.getInfo().state;
|
||||||
|
if (state == DomainState.VIR_DOMAIN_PAUSED) {
|
||||||
|
vm.resume();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* For RBD we can't use libvirt to do our snapshotting or any Bash scripts.
|
||||||
|
* libvirt also wants to store the memory contents of the Virtual Machine,
|
||||||
|
* but that's not possible with RBD since there is no way to store the memory
|
||||||
|
* contents in RBD.
|
||||||
|
*
|
||||||
|
* So we rely on the Java bindings for RBD to create our snapshot
|
||||||
|
*
|
||||||
|
* This snapshot might not be 100% consistent due to writes still being in the
|
||||||
|
* memory of the Virtual Machine, but if the VM runs a kernel which supports
|
||||||
|
* barriers properly (>2.6.32) this won't be any different then pulling the power
|
||||||
|
* cord out of a running machine.
|
||||||
|
*/
|
||||||
|
if (primaryPool.getType() == StoragePoolType.RBD) {
|
||||||
|
try {
|
||||||
|
final Rados r = new Rados(primaryPool.getAuthUserName());
|
||||||
|
r.confSet("mon_host", primaryPool.getSourceHost() + ":" + primaryPool.getSourcePort());
|
||||||
|
r.confSet("key", primaryPool.getAuthSecret());
|
||||||
|
r.confSet("client_mount_timeout", "30");
|
||||||
|
r.connect();
|
||||||
|
s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
|
||||||
|
|
||||||
|
final IoCTX io = r.ioCtxCreate(primaryPool.getSourceDir());
|
||||||
|
final Rbd rbd = new Rbd(io);
|
||||||
|
final RbdImage image = rbd.open(disk.getName());
|
||||||
|
|
||||||
|
if (command.getCommandSwitch().equalsIgnoreCase(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
|
||||||
|
s_logger.debug("Attempting to create RBD snapshot " + disk.getName() + "@" + snapshotName);
|
||||||
|
image.snapCreate(snapshotName);
|
||||||
|
} else {
|
||||||
|
s_logger.debug("Attempting to remove RBD snapshot " + disk.getName() + "@" + snapshotName);
|
||||||
|
image.snapRemove(snapshotName);
|
||||||
|
}
|
||||||
|
|
||||||
|
rbd.close(image);
|
||||||
|
r.ioCtxDestroy(io);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
s_logger.error("A RBD snapshot operation on " + disk.getName() + " failed. The error was: " + e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* VM is not running, create a snapshot by ourself */
|
||||||
|
final int cmdsTimeout = libvirtComputingResource.getCmdsTimeout();
|
||||||
|
final String manageSnapshotPath = libvirtComputingResource.manageSnapshotPath();
|
||||||
|
|
||||||
|
final Script scriptCommand = new Script(manageSnapshotPath, cmdsTimeout, s_logger);
|
||||||
|
if (command.getCommandSwitch().equalsIgnoreCase(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
|
||||||
|
scriptCommand.add("-c", disk.getPath());
|
||||||
|
} else {
|
||||||
|
scriptCommand.add("-d", snapshotPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptCommand.add("-n", snapshotName);
|
||||||
|
final String result = scriptCommand.execute();
|
||||||
|
if (result != null) {
|
||||||
|
s_logger.debug("Failed to manage snapshot: " + result);
|
||||||
|
return new ManageSnapshotAnswer(command, false, "Failed to manage snapshot: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ManageSnapshotAnswer(command, command.getSnapshotId(), disk.getPath() + File.separator + snapshotName, true, null);
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.debug("Failed to manage snapshot: " + e.toString());
|
||||||
|
return new ManageSnapshotAnswer(command, false, "Failed to manage snapshot: " + e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,183 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.Domain;
|
||||||
|
import org.libvirt.DomainInfo.DomainState;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.MigrateAnswer;
|
||||||
|
import com.cloud.agent.api.MigrateCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.MigrateKVMAsync;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.VifDriver;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtMigrateCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final MigrateCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final String vmName = command.getVmName();
|
||||||
|
|
||||||
|
String result = null;
|
||||||
|
|
||||||
|
List<InterfaceDef> ifaces = null;
|
||||||
|
List<DiskDef> disks = null;
|
||||||
|
|
||||||
|
Domain dm = null;
|
||||||
|
Connect dconn = null;
|
||||||
|
Domain destDomain = null;
|
||||||
|
Connect conn = null;
|
||||||
|
String xmlDesc = null;
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
|
||||||
|
ifaces = libvirtComputingResource.getInterfaces(conn, vmName);
|
||||||
|
disks = libvirtComputingResource.getDisks(conn, vmName);
|
||||||
|
dm = conn.domainLookupByName(vmName);
|
||||||
|
/*
|
||||||
|
We replace the private IP address with the address of the destination host.
|
||||||
|
This is because the VNC listens on the private IP address of the hypervisor,
|
||||||
|
but that address is ofcourse different on the target host.
|
||||||
|
|
||||||
|
MigrateCommand.getDestinationIp() returns the private IP address of the target
|
||||||
|
hypervisor. So it's safe to use.
|
||||||
|
|
||||||
|
The Domain.migrate method from libvirt supports passing a different XML
|
||||||
|
description for the instance to be used on the target host.
|
||||||
|
|
||||||
|
This is supported by libvirt-java from version 0.50.0
|
||||||
|
*/
|
||||||
|
xmlDesc = dm.getXMLDesc(0).replace(libvirtComputingResource.getPrivateIp(), command.getDestinationIp());
|
||||||
|
|
||||||
|
dconn = new Connect("qemu+tcp://" + command.getDestinationIp() + "/system");
|
||||||
|
|
||||||
|
//run migration in thread so we can monitor it
|
||||||
|
s_logger.info("Live migration of instance " + vmName + " initiated");
|
||||||
|
final ExecutorService executor = Executors.newFixedThreadPool(1);
|
||||||
|
final Callable<Domain> worker = new MigrateKVMAsync(libvirtComputingResource, dm, dconn, xmlDesc, vmName, command.getDestinationIp());
|
||||||
|
final Future<Domain> migrateThread = executor.submit(worker);
|
||||||
|
executor.shutdown();
|
||||||
|
long sleeptime = 0;
|
||||||
|
while (!executor.isTerminated()) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
sleeptime += 100;
|
||||||
|
if (sleeptime == 1000) { // wait 1s before attempting to set downtime on migration, since I don't know of a VIR_DOMAIN_MIGRATING state
|
||||||
|
final int migrateDowntime = libvirtComputingResource.getMigrateDowntime();
|
||||||
|
if (migrateDowntime > 0 ) {
|
||||||
|
try {
|
||||||
|
final int setDowntime = dm.migrateSetMaxDowntime(migrateDowntime);
|
||||||
|
if (setDowntime == 0 ) {
|
||||||
|
s_logger.debug("Set max downtime for migration of " + vmName + " to " + String.valueOf(migrateDowntime) + "ms");
|
||||||
|
}
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.debug("Failed to set max downtime for migration, perhaps migration completed? Error: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sleeptime % 1000 == 0) {
|
||||||
|
s_logger.info("Waiting for migration of " + vmName + " to complete, waited " + sleeptime + "ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
// pause vm if we meet the vm.migrate.pauseafter threshold and not already paused
|
||||||
|
final int migratePauseAfter = libvirtComputingResource.getMigratePauseAfter();
|
||||||
|
if (migratePauseAfter > 0 && sleeptime > migratePauseAfter && dm.getInfo().state == DomainState.VIR_DOMAIN_RUNNING ) {
|
||||||
|
s_logger.info("Pausing VM " + vmName + " due to property vm.migrate.pauseafter setting to " + migratePauseAfter+ "ms to complete migration");
|
||||||
|
try {
|
||||||
|
dm.suspend();
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
// pause could be racy if it attempts to pause right when vm is finished, simply warn
|
||||||
|
s_logger.info("Failed to pause vm " + vmName + " : " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s_logger.info("Migration thread for " + vmName + " is done");
|
||||||
|
|
||||||
|
destDomain = migrateThread.get(10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
if (destDomain != null) {
|
||||||
|
for (final DiskDef disk : disks) {
|
||||||
|
libvirtComputingResource.cleanupDisk(disk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.debug("Can't migrate domain: " + e.getMessage());
|
||||||
|
result = e.getMessage();
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
s_logger.debug("Interrupted while migrating domain: " + e.getMessage());
|
||||||
|
result = e.getMessage();
|
||||||
|
} catch (final ExecutionException e) {
|
||||||
|
s_logger.debug("Failed to execute while migrating domain: " + e.getMessage());
|
||||||
|
result = e.getMessage();
|
||||||
|
} catch (final TimeoutException e) {
|
||||||
|
s_logger.debug("Timed out while migrating domain: " + e.getMessage());
|
||||||
|
result = e.getMessage();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (dm != null) {
|
||||||
|
if (dm.isPersistent() == 1) {
|
||||||
|
dm.undefine();
|
||||||
|
}
|
||||||
|
dm.free();
|
||||||
|
}
|
||||||
|
if (dconn != null) {
|
||||||
|
dconn.close();
|
||||||
|
}
|
||||||
|
if (destDomain != null) {
|
||||||
|
destDomain.free();
|
||||||
|
}
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.trace("Ignoring libvirt error.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
} else {
|
||||||
|
libvirtComputingResource.destroyNetworkRulesForVM(conn, vmName);
|
||||||
|
for (final InterfaceDef iface : ifaces) {
|
||||||
|
// We don't know which "traffic type" is associated with
|
||||||
|
// each interface at this point, so inform all vif drivers
|
||||||
|
final List<VifDriver> allVifDrivers = libvirtComputingResource.getAllVifDrivers();
|
||||||
|
for (final VifDriver vifDriver : allVifDrivers) {
|
||||||
|
vifDriver.unplug(iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MigrateAnswer(command, result == null, result, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.ModifySshKeysCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtModifySshKeysCommandWrapper extends CommandWrapper<ModifySshKeysCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtModifySshKeysCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final ModifySshKeysCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final String sshkeyspath = libvirtUtilitiesHelper.retrieveSshKeysPath();
|
||||||
|
final String sshpubkeypath = libvirtUtilitiesHelper.retrieveSshPubKeyPath();
|
||||||
|
final String sshprvkeypath = libvirtUtilitiesHelper.retrieveSshPrvKeyPath();
|
||||||
|
|
||||||
|
final File sshKeysDir = new File(sshkeyspath);
|
||||||
|
String result = null;
|
||||||
|
if (!sshKeysDir.exists()) {
|
||||||
|
// Change permissions for the 700
|
||||||
|
final Script script = new Script("mkdir", libvirtComputingResource.getTimeout(), s_logger);
|
||||||
|
script.add("-m", "700");
|
||||||
|
script.add(sshkeyspath);
|
||||||
|
script.execute();
|
||||||
|
|
||||||
|
if (!sshKeysDir.exists()) {
|
||||||
|
s_logger.debug("failed to create directory " + sshkeyspath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final File pubKeyFile = new File(sshpubkeypath);
|
||||||
|
if (!pubKeyFile.exists()) {
|
||||||
|
try {
|
||||||
|
pubKeyFile.createNewFile();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
result = "Failed to create file: " + e.toString();
|
||||||
|
s_logger.debug(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pubKeyFile.exists()) {
|
||||||
|
try (FileOutputStream pubkStream = new FileOutputStream(pubKeyFile)) {
|
||||||
|
pubkStream.write(command.getPubKey().getBytes());
|
||||||
|
} catch (final FileNotFoundException e) {
|
||||||
|
result = "File" + sshpubkeypath + "is not found:"
|
||||||
|
+ e.toString();
|
||||||
|
s_logger.debug(result);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
result = "Write file " + sshpubkeypath + ":" + e.toString();
|
||||||
|
s_logger.debug(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final File prvKeyFile = new File(sshprvkeypath);
|
||||||
|
if (!prvKeyFile.exists()) {
|
||||||
|
try {
|
||||||
|
prvKeyFile.createNewFile();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
result = "Failed to create file: " + e.toString();
|
||||||
|
s_logger.debug(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prvKeyFile.exists()) {
|
||||||
|
final String prvKey = command.getPrvKey();
|
||||||
|
try (FileOutputStream prvKStream = new FileOutputStream(prvKeyFile);){
|
||||||
|
if ( prvKStream != null) {
|
||||||
|
prvKStream.write(prvKey.getBytes());
|
||||||
|
}
|
||||||
|
} catch (final FileNotFoundException e) {
|
||||||
|
result = "File" + sshprvkeypath + "is not found:" + e.toString();
|
||||||
|
s_logger.debug(result);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
result = "Write file " + sshprvkeypath + ":" + e.toString();
|
||||||
|
s_logger.debug(result);
|
||||||
|
}
|
||||||
|
final Script script = new Script("chmod", libvirtComputingResource.getTimeout(), s_logger);
|
||||||
|
script.add("600", sshprvkeypath);
|
||||||
|
script.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return new Answer(command, false, result);
|
||||||
|
} else {
|
||||||
|
return new Answer(command, true, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.ModifyStoragePoolAnswer;
|
||||||
|
import com.cloud.agent.api.ModifyStoragePoolCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.storage.template.TemplateProp;
|
||||||
|
|
||||||
|
public final class LibvirtModifyStoragePoolCommandWrapper extends CommandWrapper<ModifyStoragePoolCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final ModifyStoragePoolCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
final KVMStoragePool storagepool =
|
||||||
|
storagePoolMgr.createStoragePool(command.getPool().getUuid(), command.getPool().getHost(), command.getPool().getPort(), command.getPool().getPath(), command.getPool()
|
||||||
|
.getUserInfo(), command.getPool().getType());
|
||||||
|
if (storagepool == null) {
|
||||||
|
return new Answer(command, false, " Failed to create storage pool");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
|
||||||
|
final ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(command, storagepool.getCapacity(), storagepool.getAvailable(), tInfo);
|
||||||
|
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.routing.NetworkElementCommand;
|
||||||
|
import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtNetworkElementCommandWrapper extends CommandWrapper<NetworkElementCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final NetworkElementCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final VirtualRoutingResource virtRouterResource = libvirtComputingResource.getVirtRouterResource();
|
||||||
|
return virtRouterResource.executeRequest(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.NetworkRulesSystemVmCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtNetworkRulesSystemVmCommandWrapper extends CommandWrapper<NetworkRulesSystemVmCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtOvsVpcRoutingPolicyConfigCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final NetworkRulesSystemVmCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(command.getVmName());
|
||||||
|
success = libvirtComputingResource.configureDefaultNetworkRulesForSystemVm(conn, command.getVmName());
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.trace("Ignoring libvirt error.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Answer(command, success, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtNetworkRulesVmSecondaryIpCommandWrapper extends CommandWrapper<NetworkRulesVmSecondaryIpCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtOvsVpcRoutingPolicyConfigCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final NetworkRulesVmSecondaryIpCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
boolean result = false;
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(command.getVmName());
|
||||||
|
result = libvirtComputingResource.configureNetworkRulesVMSecondaryIP(conn, command.getVmName(), command.getVmSecIp(), command.getAction());
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.debug("Could not configure VM secondary IP! => " + e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Answer(command, result, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.NetworkUsageAnswer;
|
||||||
|
import com.cloud.agent.api.NetworkUsageCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtNetworkUsageCommandWrapper extends CommandWrapper<NetworkUsageCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final NetworkUsageCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
if (command.isForVpc()) {
|
||||||
|
if (command.getOption() != null && command.getOption().equals("create")) {
|
||||||
|
final String result = libvirtComputingResource.configureVPCNetworkUsage(command.getPrivateIP(), command.getGatewayIP(), "create", command.getVpcCIDR());
|
||||||
|
final NetworkUsageAnswer answer = new NetworkUsageAnswer(command, result, 0L, 0L);
|
||||||
|
return answer;
|
||||||
|
} else if (command.getOption() != null && (command.getOption().equals("get") || command.getOption().equals("vpn"))) {
|
||||||
|
final long[] stats = libvirtComputingResource.getVPCNetworkStats(command.getPrivateIP(), command.getGatewayIP(), command.getOption());
|
||||||
|
final NetworkUsageAnswer answer = new NetworkUsageAnswer(command, "", stats[0], stats[1]);
|
||||||
|
return answer;
|
||||||
|
} else {
|
||||||
|
final String result = libvirtComputingResource.configureVPCNetworkUsage(command.getPrivateIP(), command.getGatewayIP(), command.getOption(), command.getVpcCIDR());
|
||||||
|
final NetworkUsageAnswer answer = new NetworkUsageAnswer(command, result, 0L, 0L);
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (command.getOption() != null && command.getOption().equals("create")) {
|
||||||
|
final String result = libvirtComputingResource.networkUsage(command.getPrivateIP(), "create", null);
|
||||||
|
final NetworkUsageAnswer answer = new NetworkUsageAnswer(command, result, 0L, 0L);
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
final long [] stats = libvirtComputingResource.getNetworkStats(command.getPrivateIP());
|
||||||
|
final NetworkUsageAnswer answer = new NetworkUsageAnswer(command, "", stats[0], stats[1]);
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.OvsCreateTunnelAnswer;
|
||||||
|
import com.cloud.agent.api.OvsCreateTunnelCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtOvsCreateTunnelCommandWrapper extends CommandWrapper<OvsCreateTunnelCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtOvsCreateTunnelCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final OvsCreateTunnelCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final String bridge = command.getNetworkName();
|
||||||
|
try {
|
||||||
|
if (!libvirtComputingResource.findOrCreateTunnelNetwork(bridge)) {
|
||||||
|
s_logger.debug("Error during bridge setup");
|
||||||
|
return new OvsCreateTunnelAnswer(command, false,
|
||||||
|
"Cannot create network", bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
libvirtComputingResource.configureTunnelNetwork(command.getNetworkId(), command.getFrom(),
|
||||||
|
command.getNetworkName());
|
||||||
|
|
||||||
|
final Script scriptCommand = new Script(libvirtComputingResource.getOvsTunnelPath(), libvirtComputingResource.getTimeout(), s_logger);
|
||||||
|
scriptCommand.add("create_tunnel");
|
||||||
|
scriptCommand.add("--bridge", bridge);
|
||||||
|
scriptCommand.add("--remote_ip", command.getRemoteIp());
|
||||||
|
scriptCommand.add("--key", command.getKey().toString());
|
||||||
|
scriptCommand.add("--src_host", command.getFrom().toString());
|
||||||
|
scriptCommand.add("--dst_host", command.getTo().toString());
|
||||||
|
|
||||||
|
final String result = scriptCommand.execute();
|
||||||
|
if (result != null) {
|
||||||
|
return new OvsCreateTunnelAnswer(command, true, result, null,
|
||||||
|
bridge);
|
||||||
|
} else {
|
||||||
|
return new OvsCreateTunnelAnswer(command, false, result, bridge);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
s_logger.warn("Caught execption when creating ovs tunnel", e);
|
||||||
|
return new OvsCreateTunnelAnswer(command, false, e.getMessage(), bridge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.OvsDestroyBridgeCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtOvsDestroyBridgeCommandWrapper extends CommandWrapper<OvsDestroyBridgeCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtOvsDestroyBridgeCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final OvsDestroyBridgeCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final boolean result = libvirtComputingResource.destroyTunnelNetwork(command.getBridgeName());
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
s_logger.debug("Error trying to destroy OVS Bridge!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Answer(command, result, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.OvsDestroyTunnelCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtOvsDestroyTunnelCommandWrapper extends CommandWrapper<OvsDestroyTunnelCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtOvsDestroyTunnelCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final OvsDestroyTunnelCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
try {
|
||||||
|
if (!libvirtComputingResource.findOrCreateTunnelNetwork(command.getBridgeName())) {
|
||||||
|
s_logger.warn("Unable to find tunnel network for GRE key:"
|
||||||
|
+ command.getBridgeName());
|
||||||
|
return new Answer(command, false, "No network found");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Script scriptCommand = new Script(libvirtComputingResource.getOvsTunnelPath(), libvirtComputingResource.getTimeout(), s_logger);
|
||||||
|
scriptCommand.add("destroy_tunnel");
|
||||||
|
scriptCommand.add("--bridge", command.getBridgeName());
|
||||||
|
scriptCommand.add("--iface_name", command.getInPortName());
|
||||||
|
final String result = scriptCommand.execute();
|
||||||
|
if (result == null) {
|
||||||
|
return new Answer(command, true, result);
|
||||||
|
} else {
|
||||||
|
return new Answer(command, false, result);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
s_logger.warn("caught execption when destroy ovs tunnel", e);
|
||||||
|
return new Answer(command, false, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.OvsFetchInterfaceAnswer;
|
||||||
|
import com.cloud.agent.api.OvsFetchInterfaceCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtOvsFetchInterfaceCommandWrapper extends CommandWrapper<OvsFetchInterfaceCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtOvsFetchInterfaceCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final OvsFetchInterfaceCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final String label = command.getLabel();
|
||||||
|
|
||||||
|
s_logger.debug("Will look for network with name-label:" + label);
|
||||||
|
try {
|
||||||
|
final String ipadd = Script.runSimpleBashScript("ifconfig " + label + " | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'");
|
||||||
|
final String mask = Script.runSimpleBashScript("ifconfig " + label + " | grep 'inet addr:' | cut -d: -f4");
|
||||||
|
final String mac = Script.runSimpleBashScript("ifconfig " + label + " | grep HWaddr | awk -F \" \" '{print $5}'");
|
||||||
|
return new OvsFetchInterfaceAnswer(command, true, "Interface " + label
|
||||||
|
+ " retrieved successfully", ipadd, mask, mac);
|
||||||
|
|
||||||
|
} catch (final Exception e) {
|
||||||
|
s_logger.warn("Caught execption when fetching interface", e);
|
||||||
|
return new OvsFetchInterfaceAnswer(command, false, "EXCEPTION:"
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.OvsSetupBridgeCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtOvsSetupBridgeCommandWrapper extends CommandWrapper<OvsSetupBridgeCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtOvsSetupBridgeCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final OvsSetupBridgeCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final boolean findResult = libvirtComputingResource.findOrCreateTunnelNetwork(command.getBridgeName());
|
||||||
|
final boolean configResult = libvirtComputingResource.configureTunnelNetwork(command.getNetworkId(), command.getHostId(),
|
||||||
|
command.getBridgeName());
|
||||||
|
|
||||||
|
final boolean finalResult = findResult && configResult;
|
||||||
|
|
||||||
|
if (!finalResult) {
|
||||||
|
s_logger.debug("::FAILURE:: OVS Bridge was NOT configured properly!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Answer(command, finalResult, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtOvsVpcPhysicalTopologyConfigCommandWrapper extends CommandWrapper<OvsVpcPhysicalTopologyConfigCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtOvsVpcPhysicalTopologyConfigCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final OvsVpcPhysicalTopologyConfigCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
try {
|
||||||
|
final Script scriptCommand = new Script(libvirtComputingResource.getOvsTunnelPath(), libvirtComputingResource.getTimeout(), s_logger);
|
||||||
|
scriptCommand.add("configure_ovs_bridge_for_network_topology");
|
||||||
|
scriptCommand.add("--bridge", command.getBridgeName());
|
||||||
|
scriptCommand.add("--config", command.getVpcConfigInJson());
|
||||||
|
|
||||||
|
final String result = scriptCommand.execute();
|
||||||
|
if (result.equalsIgnoreCase("SUCCESS")) {
|
||||||
|
return new Answer(command, true, result);
|
||||||
|
} else {
|
||||||
|
return new Answer(command, false, result);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
s_logger.warn("caught exception while updating host with latest routing polcies", e);
|
||||||
|
return new Answer(command, false, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtOvsVpcRoutingPolicyConfigCommandWrapper extends CommandWrapper<OvsVpcRoutingPolicyConfigCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtOvsVpcRoutingPolicyConfigCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final OvsVpcRoutingPolicyConfigCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
try {
|
||||||
|
final Script scriptCommand = new Script(libvirtComputingResource.getOvsTunnelPath(), libvirtComputingResource.getTimeout(), s_logger);
|
||||||
|
scriptCommand.add("configure_ovs_bridge_for_routing_policies");
|
||||||
|
scriptCommand.add("--bridge", command.getBridgeName());
|
||||||
|
scriptCommand.add("--config", command.getVpcConfigInJson());
|
||||||
|
|
||||||
|
final String result = scriptCommand.execute();
|
||||||
|
if (result.equalsIgnoreCase("SUCCESS")) {
|
||||||
|
return new Answer(command, true, result);
|
||||||
|
} else {
|
||||||
|
return new Answer(command, false, result);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
s_logger.warn("caught exception while updating host with latest VPC topology", e);
|
||||||
|
return new Answer(command, false, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.PingTestCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtPingTestCommandWrapper extends CommandWrapper<PingTestCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtPingTestCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final PingTestCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
String result = null;
|
||||||
|
final String computingHostIp = command.getComputingHostIp(); // TODO, split the command into 2 types
|
||||||
|
|
||||||
|
if (computingHostIp != null) {
|
||||||
|
result = doPingTest(libvirtComputingResource, computingHostIp);
|
||||||
|
} else if (command.getRouterIp() != null && command.getPrivateIp() != null) {
|
||||||
|
result = doPingTest(libvirtComputingResource, command.getRouterIp(), command.getPrivateIp());
|
||||||
|
} else {
|
||||||
|
return new Answer(command, false, "routerip and private ip is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return new Answer(command, false, result);
|
||||||
|
}
|
||||||
|
return new Answer(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String doPingTest(final LibvirtComputingResource libvirtComputingResource, final String computingHostIp) {
|
||||||
|
final Script command = new Script(libvirtComputingResource.getPingTestPath(), 10000, s_logger);
|
||||||
|
command.add("-h", computingHostIp);
|
||||||
|
return command.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String doPingTest(final LibvirtComputingResource libvirtComputingResource, final String domRIp, final String vmIp) {
|
||||||
|
final Script command = new Script(libvirtComputingResource.getPingTestPath(), 10000, s_logger);
|
||||||
|
command.add("-i", domRIp);
|
||||||
|
command.add("-p", vmIp);
|
||||||
|
return command.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.Domain;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.PlugNicAnswer;
|
||||||
|
import com.cloud.agent.api.PlugNicCommand;
|
||||||
|
import com.cloud.agent.api.to.NicTO;
|
||||||
|
import com.cloud.exception.InternalErrorException;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.VifDriver;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtPlugNicCommandWrapper extends CommandWrapper<PlugNicCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtPlugNicCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final PlugNicCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final NicTO nic = command.getNic();
|
||||||
|
final String vmName = command.getVmName();
|
||||||
|
Domain vm = null;
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
|
||||||
|
vm = libvirtComputingResource.getDomain(conn, vmName);
|
||||||
|
|
||||||
|
final List<InterfaceDef> pluggedNics = libvirtComputingResource.getInterfaces(conn, vmName);
|
||||||
|
Integer nicnum = 0;
|
||||||
|
for (final InterfaceDef pluggedNic : pluggedNics) {
|
||||||
|
if (pluggedNic.getMacAddress().equalsIgnoreCase(nic.getMac())) {
|
||||||
|
s_logger.debug("found existing nic for mac " + pluggedNic.getMacAddress() + " at index " + nicnum);
|
||||||
|
return new PlugNicAnswer(command, true, "success");
|
||||||
|
}
|
||||||
|
nicnum++;
|
||||||
|
}
|
||||||
|
VifDriver vifDriver = libvirtComputingResource.getVifDriver(nic.getType());
|
||||||
|
InterfaceDef interfaceDef = vifDriver.plug(nic, "Other PV", "");
|
||||||
|
vm.attachDevice(interfaceDef.toString());
|
||||||
|
|
||||||
|
return new PlugNicAnswer(command, true, "success");
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
final String msg = " Plug Nic failed due to " + e.toString();
|
||||||
|
s_logger.warn(msg, e);
|
||||||
|
return new PlugNicAnswer(command, false, msg);
|
||||||
|
} catch (final InternalErrorException e) {
|
||||||
|
final String msg = " Plug Nic failed due to " + e.toString();
|
||||||
|
s_logger.warn(msg, e);
|
||||||
|
return new PlugNicAnswer(command, false, msg);
|
||||||
|
} finally {
|
||||||
|
if (vm != null) {
|
||||||
|
try {
|
||||||
|
vm.free();
|
||||||
|
} catch (final LibvirtException l) {
|
||||||
|
s_logger.trace("Ignoring libvirt error.", l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.PrepareForMigrationAnswer;
|
||||||
|
import com.cloud.agent.api.PrepareForMigrationCommand;
|
||||||
|
import com.cloud.agent.api.to.DiskTO;
|
||||||
|
import com.cloud.agent.api.to.NicTO;
|
||||||
|
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||||
|
import com.cloud.exception.InternalErrorException;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.storage.Volume;
|
||||||
|
|
||||||
|
public final class LibvirtPrepareForMigrationCommandWrapper extends CommandWrapper<PrepareForMigrationCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtPrepareForMigrationCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final PrepareForMigrationCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final VirtualMachineTO vm = command.getVirtualMachine();
|
||||||
|
if (s_logger.isDebugEnabled()) {
|
||||||
|
s_logger.debug("Preparing host for migrating " + vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
final NicTO[] nics = vm.getNics();
|
||||||
|
|
||||||
|
boolean skipDisconnect = false;
|
||||||
|
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vm.getName());
|
||||||
|
for (final NicTO nic : nics) {
|
||||||
|
libvirtComputingResource.getVifDriver(nic.getType()).plug(nic, null, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup disks, e.g for iso */
|
||||||
|
final DiskTO[] volumes = vm.getDisks();
|
||||||
|
for (final DiskTO volume : volumes) {
|
||||||
|
if (volume.getType() == Volume.Type.ISO) {
|
||||||
|
libvirtComputingResource.getVolumePath(conn, volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
skipDisconnect = true;
|
||||||
|
|
||||||
|
if (!storagePoolMgr.connectPhysicalDisksViaVmSpec(vm)) {
|
||||||
|
return new PrepareForMigrationAnswer(command, "failed to connect physical disks to host");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PrepareForMigrationAnswer(command);
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
return new PrepareForMigrationAnswer(command, e.toString());
|
||||||
|
} catch (final InternalErrorException e) {
|
||||||
|
return new PrepareForMigrationAnswer(command, e.toString());
|
||||||
|
} catch (final URISyntaxException e) {
|
||||||
|
return new PrepareForMigrationAnswer(command, e.toString());
|
||||||
|
} finally {
|
||||||
|
if (!skipDisconnect) {
|
||||||
|
storagePoolMgr.disconnectPhysicalDisksViaVmSpec(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
|
||||||
|
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
|
public final class LibvirtPrimaryStorageDownloadCommandWrapper extends CommandWrapper<PrimaryStorageDownloadCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final PrimaryStorageDownloadCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final String tmplturl = command.getUrl();
|
||||||
|
final int index = tmplturl.lastIndexOf("/");
|
||||||
|
final String mountpoint = tmplturl.substring(0, index);
|
||||||
|
String tmpltname = null;
|
||||||
|
|
||||||
|
if (index < tmplturl.length() - 1) {
|
||||||
|
tmpltname = tmplturl.substring(index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
KVMPhysicalDisk tmplVol = null;
|
||||||
|
KVMStoragePool secondaryPool = null;
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
try {
|
||||||
|
secondaryPool = storagePoolMgr.getStoragePoolByURI(mountpoint);
|
||||||
|
|
||||||
|
/* Get template vol */
|
||||||
|
if (tmpltname == null) {
|
||||||
|
secondaryPool.refresh();
|
||||||
|
final List<KVMPhysicalDisk> disks = secondaryPool.listPhysicalDisks();
|
||||||
|
if (disks == null || disks.isEmpty()) {
|
||||||
|
return new PrimaryStorageDownloadAnswer("Failed to get volumes from pool: " + secondaryPool.getUuid());
|
||||||
|
}
|
||||||
|
for (final KVMPhysicalDisk disk : disks) {
|
||||||
|
if (disk.getName().endsWith("qcow2")) {
|
||||||
|
tmplVol = disk;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmplVol == null) {
|
||||||
|
return new PrimaryStorageDownloadAnswer("Failed to get template from pool: " + secondaryPool.getUuid());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tmplVol = secondaryPool.getPhysicalDisk(tmpltname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy volume to primary storage */
|
||||||
|
final KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(command.getPool().getType(), command.getPoolUuid());
|
||||||
|
|
||||||
|
final KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(tmplVol, UUID.randomUUID().toString(), primaryPool, 0);
|
||||||
|
|
||||||
|
return new PrimaryStorageDownloadAnswer(primaryVol.getName(), primaryVol.getSize());
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
return new PrimaryStorageDownloadAnswer(e.toString());
|
||||||
|
} finally {
|
||||||
|
if (secondaryPool != null) {
|
||||||
|
storagePoolMgr.deleteStoragePool(secondaryPool.getType(), secondaryPool.getUuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,105 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.PvlanSetupCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
public final class LibvirtPvlanSetupCommandWrapper extends CommandWrapper<PvlanSetupCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtPvlanSetupCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final PvlanSetupCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final String primaryPvlan = command.getPrimary();
|
||||||
|
final String isolatedPvlan = command.getIsolated();
|
||||||
|
final String op = command.getOp();
|
||||||
|
final String dhcpName = command.getDhcpName();
|
||||||
|
final String dhcpMac = command.getDhcpMac();
|
||||||
|
final String dhcpIp = command.getDhcpIp();
|
||||||
|
final String vmMac = command.getVmMac();
|
||||||
|
boolean add = true;
|
||||||
|
|
||||||
|
String opr = "-A";
|
||||||
|
if (op.equals("delete")) {
|
||||||
|
opr = "-D";
|
||||||
|
add = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = null;
|
||||||
|
try {
|
||||||
|
final String guestBridgeName = libvirtComputingResource.getGuestBridgeName();
|
||||||
|
final int timeout = libvirtComputingResource.getTimeout();
|
||||||
|
|
||||||
|
if (command.getType() == PvlanSetupCommand.Type.DHCP) {
|
||||||
|
final String ovsPvlanDhcpHostPath = libvirtComputingResource.getOvsPvlanDhcpHostPath();
|
||||||
|
final Script script = new Script(ovsPvlanDhcpHostPath, timeout, s_logger);
|
||||||
|
|
||||||
|
if (add) {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(dhcpName);
|
||||||
|
|
||||||
|
final List<InterfaceDef> ifaces = libvirtComputingResource.getInterfaces(conn, dhcpName);
|
||||||
|
final InterfaceDef guestNic = ifaces.get(0);
|
||||||
|
script.add(opr, "-b", guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-n", dhcpName, "-d", dhcpIp, "-m", dhcpMac, "-I",
|
||||||
|
guestNic.getDevName());
|
||||||
|
} else {
|
||||||
|
script.add(opr, "-b", guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-n", dhcpName, "-d", dhcpIp, "-m", dhcpMac);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = script.execute();
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac);
|
||||||
|
return new Answer(command, false, result);
|
||||||
|
} else {
|
||||||
|
s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac);
|
||||||
|
}
|
||||||
|
} else if (command.getType() == PvlanSetupCommand.Type.VM) {
|
||||||
|
final String ovsPvlanVmPath = libvirtComputingResource.getOvsPvlanVmPath();
|
||||||
|
|
||||||
|
final Script script = new Script(ovsPvlanVmPath, timeout, s_logger);
|
||||||
|
script.add(opr, "-b", guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-v", vmMac);
|
||||||
|
result = script.execute();
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
s_logger.warn("Failed to program pvlan for vm with mac " + vmMac);
|
||||||
|
return new Answer(command, false, result);
|
||||||
|
} else {
|
||||||
|
s_logger.info("Programmed pvlan for vm with mac " + vmMac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.error("Error whislt executing OVS Setup command! ==> " + e.getMessage());
|
||||||
|
return new Answer(command, false, e.getMessage());
|
||||||
|
}
|
||||||
|
return new Answer(command, true, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.ReadyAnswer;
|
||||||
|
import com.cloud.agent.api.ReadyCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtReadyCommandWrapper extends CommandWrapper<ReadyCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final ReadyCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
return new ReadyAnswer(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.RebootAnswer;
|
||||||
|
import com.cloud.agent.api.RebootCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtRebootCommandWrapper extends CommandWrapper<RebootCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtRebootCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final RebootCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(command.getVmName());
|
||||||
|
final String result = libvirtComputingResource.rebootVM(conn, command.getVmName());
|
||||||
|
if (result == null) {
|
||||||
|
Integer vncPort = null;
|
||||||
|
try {
|
||||||
|
vncPort = libvirtComputingResource.getVncPort(conn, command.getVmName());
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.trace("Ignoring libvirt error.", e);
|
||||||
|
}
|
||||||
|
libvirtComputingResource.getRuleLogsForVms();
|
||||||
|
return new RebootAnswer(command, null, vncPort);
|
||||||
|
} else {
|
||||||
|
return new RebootAnswer(command, result, false);
|
||||||
|
}
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
return new RebootAnswer(command, e.getMessage(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.RebootCommand;
|
||||||
|
import com.cloud.agent.api.RebootRouterCommand;
|
||||||
|
import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtRebootRouterCommandWrapper extends CommandWrapper<RebootRouterCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final RebootRouterCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance();
|
||||||
|
|
||||||
|
final RebootCommand rebootCommand = new RebootCommand(command.getVmName());
|
||||||
|
final Answer answer = wrapper.execute(rebootCommand, libvirtComputingResource);
|
||||||
|
|
||||||
|
final VirtualRoutingResource virtualRouterResource = libvirtComputingResource.getVirtRouterResource();
|
||||||
|
if (virtualRouterResource.connect(command.getPrivateIpAddress())) {
|
||||||
|
libvirtComputingResource.networkUsage(command.getPrivateIpAddress(), "create", null);
|
||||||
|
|
||||||
|
return answer;
|
||||||
|
} else {
|
||||||
|
return new Answer(command, false, "Failed to connect to virtual router " + command.getVmName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,184 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.AttachIsoCommand;
|
||||||
|
import com.cloud.agent.api.AttachVolumeCommand;
|
||||||
|
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.CheckHealthCommand;
|
||||||
|
import com.cloud.agent.api.CheckNetworkCommand;
|
||||||
|
import com.cloud.agent.api.CheckOnHostCommand;
|
||||||
|
import com.cloud.agent.api.CheckVirtualMachineCommand;
|
||||||
|
import com.cloud.agent.api.CleanupNetworkRulesCmd;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
|
||||||
|
import com.cloud.agent.api.CreateStoragePoolCommand;
|
||||||
|
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.DeleteStoragePoolCommand;
|
||||||
|
import com.cloud.agent.api.FenceCommand;
|
||||||
|
import com.cloud.agent.api.GetHostStatsCommand;
|
||||||
|
import com.cloud.agent.api.GetStorageStatsCommand;
|
||||||
|
import com.cloud.agent.api.GetVmDiskStatsCommand;
|
||||||
|
import com.cloud.agent.api.GetVmStatsCommand;
|
||||||
|
import com.cloud.agent.api.GetVncPortCommand;
|
||||||
|
import com.cloud.agent.api.MaintainCommand;
|
||||||
|
import com.cloud.agent.api.ManageSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.MigrateCommand;
|
||||||
|
import com.cloud.agent.api.ModifySshKeysCommand;
|
||||||
|
import com.cloud.agent.api.ModifyStoragePoolCommand;
|
||||||
|
import com.cloud.agent.api.NetworkRulesSystemVmCommand;
|
||||||
|
import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand;
|
||||||
|
import com.cloud.agent.api.NetworkUsageCommand;
|
||||||
|
import com.cloud.agent.api.OvsCreateTunnelCommand;
|
||||||
|
import com.cloud.agent.api.OvsDestroyBridgeCommand;
|
||||||
|
import com.cloud.agent.api.OvsDestroyTunnelCommand;
|
||||||
|
import com.cloud.agent.api.OvsFetchInterfaceCommand;
|
||||||
|
import com.cloud.agent.api.OvsSetupBridgeCommand;
|
||||||
|
import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
|
||||||
|
import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand;
|
||||||
|
import com.cloud.agent.api.PingTestCommand;
|
||||||
|
import com.cloud.agent.api.PlugNicCommand;
|
||||||
|
import com.cloud.agent.api.PrepareForMigrationCommand;
|
||||||
|
import com.cloud.agent.api.PvlanSetupCommand;
|
||||||
|
import com.cloud.agent.api.ReadyCommand;
|
||||||
|
import com.cloud.agent.api.RebootCommand;
|
||||||
|
import com.cloud.agent.api.RebootRouterCommand;
|
||||||
|
import com.cloud.agent.api.SecurityGroupRulesCmd;
|
||||||
|
import com.cloud.agent.api.StartCommand;
|
||||||
|
import com.cloud.agent.api.StopCommand;
|
||||||
|
import com.cloud.agent.api.UnPlugNicCommand;
|
||||||
|
import com.cloud.agent.api.UpgradeSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.check.CheckSshCommand;
|
||||||
|
import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand;
|
||||||
|
import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
|
||||||
|
import com.cloud.agent.api.routing.NetworkElementCommand;
|
||||||
|
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||||
|
import com.cloud.agent.api.storage.CreateCommand;
|
||||||
|
import com.cloud.agent.api.storage.DestroyCommand;
|
||||||
|
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||||
|
import com.cloud.agent.api.storage.ResizeVolumeCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.resource.RequestWrapper;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
|
||||||
|
public class LibvirtRequestWrapper extends RequestWrapper {
|
||||||
|
|
||||||
|
private static LibvirtRequestWrapper instance;
|
||||||
|
|
||||||
|
static {
|
||||||
|
instance = new LibvirtRequestWrapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
private LibvirtRequestWrapper() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private void init() {
|
||||||
|
// LibvirtComputingResource commands
|
||||||
|
final Hashtable<Class<? extends Command>, CommandWrapper> linbvirtCommands = new Hashtable<Class<? extends Command>, CommandWrapper>();
|
||||||
|
|
||||||
|
linbvirtCommands.put(StopCommand.class, new LibvirtStopCommandWrapper());
|
||||||
|
linbvirtCommands.put(GetVmStatsCommand.class, new LibvirtGetVmStatsCommandWrapper());
|
||||||
|
linbvirtCommands.put(GetVmDiskStatsCommand.class, new LibvirtGetVmDiskStatsCommandWrapper());
|
||||||
|
linbvirtCommands.put(RebootRouterCommand.class, new LibvirtRebootRouterCommandWrapper());
|
||||||
|
linbvirtCommands.put(RebootCommand.class, new LibvirtRebootCommandWrapper());
|
||||||
|
linbvirtCommands.put(GetHostStatsCommand.class, new LibvirtGetHostStatsCommandWrapper());
|
||||||
|
linbvirtCommands.put(CheckHealthCommand.class, new LibvirtCheckHealthCommandWrapper());
|
||||||
|
linbvirtCommands.put(PrepareForMigrationCommand.class, new LibvirtPrepareForMigrationCommandWrapper());
|
||||||
|
linbvirtCommands.put(MigrateCommand.class, new LibvirtMigrateCommandWrapper());
|
||||||
|
linbvirtCommands.put(PingTestCommand.class, new LibvirtPingTestCommandWrapper());
|
||||||
|
linbvirtCommands.put(CheckVirtualMachineCommand.class, new LibvirtCheckVirtualMachineCommandWrapper());
|
||||||
|
linbvirtCommands.put(ReadyCommand.class, new LibvirtReadyCommandWrapper());
|
||||||
|
linbvirtCommands.put(AttachIsoCommand.class, new LibvirtAttachIsoCommandWrapper());
|
||||||
|
linbvirtCommands.put(AttachVolumeCommand.class, new LibvirtAttachVolumeCommandWrapper());
|
||||||
|
linbvirtCommands.put(WatchConsoleProxyLoadCommand.class, new LibvirtWatchConsoleProxyLoadCommandWrapper());
|
||||||
|
linbvirtCommands.put(CheckConsoleProxyLoadCommand.class, new LibvirtCheckConsoleProxyLoadCommandWrapper());
|
||||||
|
linbvirtCommands.put(GetVncPortCommand.class, new LibvirtGetVncPortCommandWrapper());
|
||||||
|
linbvirtCommands.put(ModifySshKeysCommand.class, new LibvirtModifySshKeysCommandWrapper());
|
||||||
|
linbvirtCommands.put(MaintainCommand.class, new LibvirtMaintainCommandWrapper());
|
||||||
|
linbvirtCommands.put(CreateCommand.class, new LibvirtCreateCommandWrapper());
|
||||||
|
linbvirtCommands.put(DestroyCommand.class, new LibvirtDestroyCommandWrapper());
|
||||||
|
linbvirtCommands.put(PrimaryStorageDownloadCommand.class, new LibvirtPrimaryStorageDownloadCommandWrapper());
|
||||||
|
linbvirtCommands.put(GetStorageStatsCommand.class, new LibvirtGetStorageStatsCommandWrapper());
|
||||||
|
linbvirtCommands.put(UpgradeSnapshotCommand.class, new LibvirtUpgradeSnapshotCommandWrapper());
|
||||||
|
linbvirtCommands.put(DeleteStoragePoolCommand.class, new LibvirtDeleteStoragePoolCommandWrapper());
|
||||||
|
linbvirtCommands.put(OvsSetupBridgeCommand.class, new LibvirtOvsSetupBridgeCommandWrapper());
|
||||||
|
linbvirtCommands.put(OvsDestroyBridgeCommand.class, new LibvirtOvsDestroyBridgeCommandWrapper());
|
||||||
|
linbvirtCommands.put(OvsFetchInterfaceCommand.class, new LibvirtOvsFetchInterfaceCommandWrapper());
|
||||||
|
linbvirtCommands.put(OvsVpcPhysicalTopologyConfigCommand.class, new LibvirtOvsVpcPhysicalTopologyConfigCommandWrapper());
|
||||||
|
linbvirtCommands.put(OvsVpcRoutingPolicyConfigCommand.class, new LibvirtOvsVpcRoutingPolicyConfigCommandWrapper());
|
||||||
|
linbvirtCommands.put(CreateStoragePoolCommand.class, new LibvirtCreateStoragePoolCommandWrapper());
|
||||||
|
linbvirtCommands.put(ModifyStoragePoolCommand.class, new LibvirtModifyStoragePoolCommandWrapper());
|
||||||
|
linbvirtCommands.put(CleanupNetworkRulesCmd.class, new LibvirtCleanupNetworkRulesCommandWrapper());
|
||||||
|
linbvirtCommands.put(NetworkRulesVmSecondaryIpCommand.class, new LibvirtNetworkRulesVmSecondaryIpCommandWrapper());
|
||||||
|
linbvirtCommands.put(NetworkRulesSystemVmCommand.class, new LibvirtNetworkRulesSystemVmCommandWrapper());
|
||||||
|
linbvirtCommands.put(CheckSshCommand.class, new LibvirtCheckSshCommandWrapper());
|
||||||
|
linbvirtCommands.put(CheckNetworkCommand.class, new LibvirtCheckNetworkCommandWrapper());
|
||||||
|
linbvirtCommands.put(OvsDestroyTunnelCommand.class, new LibvirtOvsDestroyTunnelCommandWrapper());
|
||||||
|
linbvirtCommands.put(CheckOnHostCommand.class, new LibvirtCheckOnHostCommandWrapper());
|
||||||
|
linbvirtCommands.put(OvsCreateTunnelCommand.class, new LibvirtOvsCreateTunnelCommandWrapper());
|
||||||
|
linbvirtCommands.put(CreateVolumeFromSnapshotCommand.class, new LibvirtCreateVolumeFromSnapshotCommandWrapper());
|
||||||
|
linbvirtCommands.put(FenceCommand.class, new LibvirtFenceCommandWrapper());
|
||||||
|
linbvirtCommands.put(SecurityGroupRulesCmd.class, new LibvirtSecurityGroupRulesCommandWrapper());
|
||||||
|
linbvirtCommands.put(PlugNicCommand.class, new LibvirtPlugNicCommandWrapper());
|
||||||
|
linbvirtCommands.put(UnPlugNicCommand.class, new LibvirtUnPlugNicCommandWrapper());
|
||||||
|
linbvirtCommands.put(NetworkUsageCommand.class, new LibvirtNetworkUsageCommandWrapper());
|
||||||
|
linbvirtCommands.put(CreatePrivateTemplateFromVolumeCommand.class, new LibvirtCreatePrivateTemplateFromVolumeCommandWrapper());
|
||||||
|
linbvirtCommands.put(ManageSnapshotCommand.class, new LibvirtManageSnapshotCommandWrapper());
|
||||||
|
linbvirtCommands.put(BackupSnapshotCommand.class, new LibvirtBackupSnapshotCommandWrapper());
|
||||||
|
linbvirtCommands.put(CreatePrivateTemplateFromSnapshotCommand.class, new LibvirtCreatePrivateTemplateFromSnapshotCommandWrapper());
|
||||||
|
linbvirtCommands.put(CopyVolumeCommand.class, new LibvirtCopyVolumeCommandWrapper());
|
||||||
|
linbvirtCommands.put(PvlanSetupCommand.class, new LibvirtPvlanSetupCommandWrapper());
|
||||||
|
linbvirtCommands.put(ResizeVolumeCommand.class, new LibvirtResizeVolumeCommandWrapper());
|
||||||
|
linbvirtCommands.put(NetworkElementCommand.class, new LibvirtNetworkElementCommandWrapper());
|
||||||
|
linbvirtCommands.put(StorageSubSystemCommand.class, new LibvirtStorageSubSystemCommandWrapper());
|
||||||
|
linbvirtCommands.put(StartCommand.class, new LibvirtStartCommandWrapper());
|
||||||
|
|
||||||
|
resources.put(LibvirtComputingResource.class, linbvirtCommands);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LibvirtRequestWrapper getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes" })
|
||||||
|
@Override
|
||||||
|
public Answer execute(final Command command, final ServerResource serverResource) {
|
||||||
|
final Class<? extends ServerResource> resourceClass = serverResource.getClass();
|
||||||
|
|
||||||
|
final Hashtable<Class<? extends Command>, CommandWrapper> resourceCommands = retrieveResource(command, resourceClass);
|
||||||
|
|
||||||
|
CommandWrapper<Command, Answer, ServerResource> commandWrapper = retrieveCommands(command.getClass(), resourceCommands);
|
||||||
|
|
||||||
|
while (commandWrapper == null) {
|
||||||
|
//Could not find the command in the given resource, will traverse the family tree.
|
||||||
|
commandWrapper = retryWhenAllFails(command, resourceClass, resourceCommands);
|
||||||
|
}
|
||||||
|
|
||||||
|
return commandWrapper.execute(command, serverResource);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,136 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
import org.libvirt.StorageVol;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.storage.ResizeVolumeAnswer;
|
||||||
|
import com.cloud.agent.api.storage.ResizeVolumeCommand;
|
||||||
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.utils.script.Script;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Uses a local script now, eventually support for virStorageVolResize() will maybe work on qcow2 and lvm and we can do this in libvirt calls
|
||||||
|
*/
|
||||||
|
public final class LibvirtResizeVolumeCommandWrapper extends CommandWrapper<ResizeVolumeCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtResizeVolumeCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final ResizeVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final String volid = command.getPath();
|
||||||
|
final long newSize = command.getNewSize();
|
||||||
|
final long currentSize = command.getCurrentSize();
|
||||||
|
final String vmInstanceName = command.getInstanceName();
|
||||||
|
final boolean shrinkOk = command.getShrinkOk();
|
||||||
|
final StorageFilerTO spool = command.getPool();
|
||||||
|
final String notifyOnlyType = "NOTIFYONLY";
|
||||||
|
|
||||||
|
if ( currentSize == newSize) {
|
||||||
|
// nothing to do
|
||||||
|
s_logger.info("No need to resize volume: current size " + currentSize + " is same as new size " + newSize);
|
||||||
|
return new ResizeVolumeAnswer(command, true, "success", currentSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
KVMStoragePool pool = storagePoolMgr.getStoragePool(spool.getType(), spool.getUuid());
|
||||||
|
|
||||||
|
final KVMPhysicalDisk vol = pool.getPhysicalDisk(volid);
|
||||||
|
final String path = vol.getPath();
|
||||||
|
String type = libvirtComputingResource.getResizeScriptType(pool, vol);
|
||||||
|
|
||||||
|
if (pool.getType() != StoragePoolType.RBD) {
|
||||||
|
if (type.equals("QCOW2") && shrinkOk) {
|
||||||
|
return new ResizeVolumeAnswer(command, false, "Unable to shrink volumes of type " + type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s_logger.debug("Volume " + path + " is on a RBD storage pool. No need to query for additional information.");
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.debug("Resizing volume: " + path + "," + currentSize + "," + newSize + "," + type + "," + vmInstanceName + "," + shrinkOk);
|
||||||
|
|
||||||
|
/* libvirt doesn't support resizing (C)LVM devices, and corrupts QCOW2 in some scenarios, so we have to do these via Bash script */
|
||||||
|
if (pool.getType() != StoragePoolType.CLVM && vol.getFormat() != PhysicalDiskFormat.QCOW2) {
|
||||||
|
s_logger.debug("Volume " + path + " can be resized by libvirt. Asking libvirt to resize the volume.");
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnection();
|
||||||
|
final StorageVol v = conn.storageVolLookupByPath(path);
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
if (conn.getLibVirVersion() > 1001000 && vol.getFormat() == PhysicalDiskFormat.RAW && pool.getType() != StoragePoolType.RBD) {
|
||||||
|
flags = 1;
|
||||||
|
}
|
||||||
|
if (shrinkOk) {
|
||||||
|
flags = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
v.resize(newSize, flags);
|
||||||
|
type = notifyOnlyType;
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
return new ResizeVolumeAnswer(command, false, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s_logger.debug("Invoking resize script to handle type " + type);
|
||||||
|
|
||||||
|
final Script resizecmd = new Script(libvirtComputingResource.getResizeVolumePath(), libvirtComputingResource.getCmdsTimeout(), s_logger);
|
||||||
|
resizecmd.add("-s", String.valueOf(newSize));
|
||||||
|
resizecmd.add("-c", String.valueOf(currentSize));
|
||||||
|
resizecmd.add("-p", path);
|
||||||
|
resizecmd.add("-t", type);
|
||||||
|
resizecmd.add("-r", String.valueOf(shrinkOk));
|
||||||
|
resizecmd.add("-v", vmInstanceName);
|
||||||
|
final String result = resizecmd.execute();
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
if(type.equals(notifyOnlyType)) {
|
||||||
|
return new ResizeVolumeAnswer(command, true, "Resize succeeded, but need reboot to notify guest");
|
||||||
|
} else {
|
||||||
|
return new ResizeVolumeAnswer(command, false, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fetch new size as seen from libvirt, don't want to assume anything */
|
||||||
|
pool = storagePoolMgr.getStoragePool(spool.getType(), spool.getUuid());
|
||||||
|
pool.refresh();
|
||||||
|
final long finalSize = pool.getPhysicalDisk(volid).getVirtualSize();
|
||||||
|
s_logger.debug("after resize, size reports as " + finalSize + ", requested " + newSize);
|
||||||
|
return new ResizeVolumeAnswer(command, true, "success", finalSize);
|
||||||
|
} catch (final CloudRuntimeException e) {
|
||||||
|
final String error = "Failed to resize volume: " + e.getMessage();
|
||||||
|
s_logger.debug(error);
|
||||||
|
return new ResizeVolumeAnswer(command, false, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.SecurityGroupRuleAnswer;
|
||||||
|
import com.cloud.agent.api.SecurityGroupRulesCmd;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtSecurityGroupRulesCommandWrapper extends CommandWrapper<SecurityGroupRulesCmd, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtSecurityGroupRulesCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final SecurityGroupRulesCmd command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
String vif = null;
|
||||||
|
String brname = null;
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(command.getVmName());
|
||||||
|
final List<InterfaceDef> nics = libvirtComputingResource.getInterfaces(conn, command.getVmName());
|
||||||
|
|
||||||
|
vif = nics.get(0).getDevName();
|
||||||
|
brname = nics.get(0).getBrName();
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
return new SecurityGroupRuleAnswer(command, false, e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean result = libvirtComputingResource.addNetworkRules(command.getVmName(), Long.toString(command.getVmId()), command.getGuestIp(), command.getSignature(),
|
||||||
|
Long.toString(command.getSeqNum()), command.getGuestMac(), command.stringifyRules(), vif, brname, command.getSecIpsString());
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
s_logger.warn("Failed to program network rules for vm " + command.getVmName());
|
||||||
|
return new SecurityGroupRuleAnswer(command, false, "programming network rules failed");
|
||||||
|
} else {
|
||||||
|
s_logger.debug("Programmed network rules for vm " + command.getVmName() + " guestIp=" + command.getGuestIp() + ",ingress numrules="
|
||||||
|
+ command.getIngressRuleSet().length + ",egress numrules=" + command.getEgressRuleSet().length);
|
||||||
|
return new SecurityGroupRuleAnswer(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,151 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.DomainInfo.DomainState;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.StartAnswer;
|
||||||
|
import com.cloud.agent.api.StartCommand;
|
||||||
|
import com.cloud.agent.api.to.NicTO;
|
||||||
|
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||||
|
import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource;
|
||||||
|
import com.cloud.exception.InternalErrorException;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef;
|
||||||
|
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||||
|
import com.cloud.network.Networks.IsolationType;
|
||||||
|
import com.cloud.network.Networks.TrafficType;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
|
||||||
|
public final class LibvirtStartCommandWrapper extends CommandWrapper<StartCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtStartCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final StartCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final VirtualMachineTO vmSpec = command.getVirtualMachine();
|
||||||
|
vmSpec.setVncAddr(command.getHostIp());
|
||||||
|
final String vmName = vmSpec.getName();
|
||||||
|
LibvirtVMDef vm = null;
|
||||||
|
|
||||||
|
DomainState state = DomainState.VIR_DOMAIN_SHUTOFF;
|
||||||
|
final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
Connect conn = null;
|
||||||
|
try {
|
||||||
|
final NicTO[] nics = vmSpec.getNics();
|
||||||
|
|
||||||
|
for (final NicTO nic : nics) {
|
||||||
|
if (vmSpec.getType() != VirtualMachine.Type.User) {
|
||||||
|
nic.setPxeDisable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vm = libvirtComputingResource.createVMFromSpec(vmSpec);
|
||||||
|
conn = libvirtUtilitiesHelper.getConnectionByType(vm.getHvsType());
|
||||||
|
libvirtComputingResource.createVbd(conn, vmSpec, vmName, vm);
|
||||||
|
|
||||||
|
if (!storagePoolMgr.connectPhysicalDisksViaVmSpec(vmSpec)) {
|
||||||
|
return new StartAnswer(command, "Failed to connect physical disks to host");
|
||||||
|
}
|
||||||
|
|
||||||
|
libvirtComputingResource.createVifs(vmSpec, vm);
|
||||||
|
|
||||||
|
s_logger.debug("starting " + vmName + ": " + vm.toString());
|
||||||
|
libvirtComputingResource.startVM(conn, vmName, vm.toString());
|
||||||
|
|
||||||
|
for (final NicTO nic : nics) {
|
||||||
|
if (nic.isSecurityGroupEnabled() || nic.getIsolationUri() != null && nic.getIsolationUri().getScheme().equalsIgnoreCase(IsolationType.Ec2.toString())) {
|
||||||
|
if (vmSpec.getType() != VirtualMachine.Type.User) {
|
||||||
|
libvirtComputingResource.configureDefaultNetworkRulesForSystemVm(conn, vmName);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
final List<String> nicSecIps = nic.getNicSecIps();
|
||||||
|
String secIpsStr;
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
if (nicSecIps != null) {
|
||||||
|
for (final String ip : nicSecIps) {
|
||||||
|
sb.append(ip).append(":");
|
||||||
|
}
|
||||||
|
secIpsStr = sb.toString();
|
||||||
|
} else {
|
||||||
|
secIpsStr = "0:";
|
||||||
|
}
|
||||||
|
libvirtComputingResource.defaultNetworkRules(conn, vmName, nic, vmSpec.getId(), secIpsStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass cmdline info to system vms
|
||||||
|
if (vmSpec.getType() != VirtualMachine.Type.User) {
|
||||||
|
//wait and try passCmdLine for 5 minutes at most for CLOUDSTACK-2823
|
||||||
|
String controlIp = null;
|
||||||
|
for (final NicTO nic : nics) {
|
||||||
|
if (nic.getType() == TrafficType.Control) {
|
||||||
|
controlIp = nic.getIp();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int count = 0; count < 30; count++) {
|
||||||
|
libvirtComputingResource.passCmdLine(vmName, vmSpec.getBootArgs());
|
||||||
|
//check router is up?
|
||||||
|
final VirtualRoutingResource virtRouterResource = libvirtComputingResource.getVirtRouterResource();
|
||||||
|
final boolean result = virtRouterResource.connect(controlIp, 1, 5000);
|
||||||
|
if (result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state = DomainState.VIR_DOMAIN_RUNNING;
|
||||||
|
return new StartAnswer(command);
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
s_logger.warn("LibvirtException ", e);
|
||||||
|
if (conn != null) {
|
||||||
|
libvirtComputingResource.handleVmStartFailure(conn, vmName, vm);
|
||||||
|
}
|
||||||
|
return new StartAnswer(command, e.getMessage());
|
||||||
|
} catch (final InternalErrorException e) {
|
||||||
|
s_logger.warn("InternalErrorException ", e);
|
||||||
|
if (conn != null) {
|
||||||
|
libvirtComputingResource.handleVmStartFailure(conn, vmName, vm);
|
||||||
|
}
|
||||||
|
return new StartAnswer(command, e.getMessage());
|
||||||
|
} catch (final URISyntaxException e) {
|
||||||
|
s_logger.warn("URISyntaxException ", e);
|
||||||
|
if (conn != null) {
|
||||||
|
libvirtComputingResource.handleVmStartFailure(conn, vmName, vm);
|
||||||
|
}
|
||||||
|
return new StartAnswer(command, e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (state != DomainState.VIR_DOMAIN_RUNNING) {
|
||||||
|
storagePoolMgr.disconnectPhysicalDisksViaVmSpec(vmSpec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.Domain;
|
||||||
|
import org.libvirt.DomainInfo.DomainState;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.StopAnswer;
|
||||||
|
import com.cloud.agent.api.StopCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.VifDriver;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtStopCommandWrapper extends CommandWrapper<StopCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtStopCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final StopCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final String vmName = command.getVmName();
|
||||||
|
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
if (command.checkBeforeCleanup()) {
|
||||||
|
try {
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
|
||||||
|
final Domain vm = conn.domainLookupByName(command.getVmName());
|
||||||
|
if (vm != null && vm.getInfo().state == DomainState.VIR_DOMAIN_RUNNING) {
|
||||||
|
return new StopAnswer(command, "vm is still running on host", false);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
s_logger.debug("Failed to get vm status in case of checkboforecleanup is true", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
|
||||||
|
|
||||||
|
final List<DiskDef> disks = libvirtComputingResource.getDisks(conn, vmName);
|
||||||
|
final List<InterfaceDef> ifaces = libvirtComputingResource.getInterfaces(conn, vmName);
|
||||||
|
|
||||||
|
libvirtComputingResource.destroyNetworkRulesForVM(conn, vmName);
|
||||||
|
final String result = libvirtComputingResource.stopVM(conn, vmName);
|
||||||
|
if (result == null) {
|
||||||
|
for (final DiskDef disk : disks) {
|
||||||
|
libvirtComputingResource.cleanupDisk(disk);
|
||||||
|
}
|
||||||
|
for (final InterfaceDef iface : ifaces) {
|
||||||
|
// We don't know which "traffic type" is associated with
|
||||||
|
// each interface at this point, so inform all vif drivers
|
||||||
|
for (final VifDriver vifDriver : libvirtComputingResource.getAllVifDrivers()) {
|
||||||
|
vifDriver.unplug(iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StopAnswer(command, result, true);
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
return new StopAnswer(command, e.getMessage(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.storage.resource.StorageSubsystemCommandHandler;
|
||||||
|
|
||||||
|
public final class LibvirtStorageSubSystemCommandWrapper extends CommandWrapper<StorageSubSystemCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final StorageSubSystemCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final StorageSubsystemCommandHandler handler = libvirtComputingResource.getStorageHandler();
|
||||||
|
return handler.handleStorageCommands(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.Domain;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.UnPlugNicAnswer;
|
||||||
|
import com.cloud.agent.api.UnPlugNicCommand;
|
||||||
|
import com.cloud.agent.api.to.NicTO;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.VifDriver;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtUnPlugNicCommandWrapper extends CommandWrapper<UnPlugNicCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(LibvirtUnPlugNicCommandWrapper.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final UnPlugNicCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
final NicTO nic = command.getNic();
|
||||||
|
final String vmName = command.getVmName();
|
||||||
|
Domain vm = null;
|
||||||
|
try {
|
||||||
|
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||||
|
|
||||||
|
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
|
||||||
|
vm = libvirtComputingResource.getDomain(conn, vmName);
|
||||||
|
final List<InterfaceDef> pluggedNics = libvirtComputingResource.getInterfaces(conn, vmName);
|
||||||
|
|
||||||
|
for (final InterfaceDef pluggedNic : pluggedNics) {
|
||||||
|
if (pluggedNic.getMacAddress().equalsIgnoreCase(nic.getMac())) {
|
||||||
|
vm.detachDevice(pluggedNic.toString());
|
||||||
|
// We don't know which "traffic type" is associated with
|
||||||
|
// each interface at this point, so inform all vif drivers
|
||||||
|
for (final VifDriver vifDriver : libvirtComputingResource.getAllVifDrivers()) {
|
||||||
|
vifDriver.unplug(pluggedNic);
|
||||||
|
}
|
||||||
|
return new UnPlugNicAnswer(command, true, "success");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new UnPlugNicAnswer(command, true, "success");
|
||||||
|
} catch (final LibvirtException e) {
|
||||||
|
final String msg = " Unplug Nic failed due to " + e.toString();
|
||||||
|
s_logger.warn(msg, e);
|
||||||
|
return new UnPlugNicAnswer(command, false, msg);
|
||||||
|
} finally {
|
||||||
|
if (vm != null) {
|
||||||
|
try {
|
||||||
|
vm.free();
|
||||||
|
} catch (final LibvirtException l) {
|
||||||
|
s_logger.trace("Ignoring libvirt error.", l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.UpgradeSnapshotCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
|
||||||
|
public final class LibvirtUpgradeSnapshotCommandWrapper extends CommandWrapper<UpgradeSnapshotCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final UpgradeSnapshotCommand command, final LibvirtComputingResource libvirtComputingResource) {
|
||||||
|
return new Answer(command, true, "success");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.libvirt.Connect;
|
||||||
|
import org.libvirt.LibvirtException;
|
||||||
|
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtConnection;
|
||||||
|
import com.cloud.storage.StorageLayer;
|
||||||
|
import com.cloud.storage.template.Processor;
|
||||||
|
import com.cloud.storage.template.QCOW2Processor;
|
||||||
|
import com.cloud.storage.template.TemplateLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to wrap the calls to several static methods. By doing so, we make easier to mock this class
|
||||||
|
* and the methods wrapped here.
|
||||||
|
*
|
||||||
|
* Please do not instantiate this class directly, but inject it using the {@code @Inject} annotation.
|
||||||
|
*/
|
||||||
|
public class LibvirtUtilitiesHelper {
|
||||||
|
|
||||||
|
public Connect getConnectionByVmName(final String vmName) throws LibvirtException {
|
||||||
|
return LibvirtConnection.getConnectionByVmName(vmName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connect getConnection() throws LibvirtException {
|
||||||
|
return LibvirtConnection.getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateLocation buildTemplateLocation(final StorageLayer storage, final String templatePath) {
|
||||||
|
final TemplateLocation location = new TemplateLocation(storage, templatePath);
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Processor buildQCOW2Processor(final StorageLayer storage) throws ConfigurationException {
|
||||||
|
final Map<String, Object> params = new HashMap<String, Object>();
|
||||||
|
params.put(StorageLayer.InstanceConfigKey, storage);
|
||||||
|
|
||||||
|
final Processor qcow2Processor = new QCOW2Processor();
|
||||||
|
qcow2Processor.configure("QCOW2 Processor", params);
|
||||||
|
|
||||||
|
return qcow2Processor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generatereUUIDName() {
|
||||||
|
return UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connect getConnectionByType(final String hvsType) throws LibvirtException {
|
||||||
|
return LibvirtConnection.getConnectionByType(hvsType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String retrieveSshKeysPath() {
|
||||||
|
return LibvirtComputingResource.SSHKEYSPATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String retrieveSshPubKeyPath() {
|
||||||
|
return LibvirtComputingResource.SSHPUBKEYPATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String retrieveSshPrvKeyPath() {
|
||||||
|
return LibvirtComputingResource.SSHPRVKEYPATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.kvm.resource.wrapper;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
|
||||||
|
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
|
||||||
|
public class LibvirtWatchConsoleProxyLoadCommandWrapper extends LibvirtConsoleProxyLoadCommandWrapper<WatchConsoleProxyLoadCommand, Answer, LibvirtComputingResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Answer execute(final Command command, final ServerResource serverResource) {
|
||||||
|
final WatchConsoleProxyLoadCommand cmd = (WatchConsoleProxyLoadCommand) command;
|
||||||
|
|
||||||
|
final long proxyVmId = cmd.getProxyVmId();
|
||||||
|
final String proxyVmName = cmd.getProxyVmName();
|
||||||
|
final String proxyManagementIp = cmd.getProxyManagementIp();
|
||||||
|
final int proxyCmdPort = cmd.getProxyCmdPort();
|
||||||
|
|
||||||
|
return executeProxyLoadScan(cmd, proxyVmId, proxyVmName, proxyManagementIp, proxyCmdPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -20,18 +20,21 @@
|
|||||||
package com.cloud.hypervisor.xenserver.resource.wrapper;
|
package com.cloud.hypervisor.xenserver.resource.wrapper;
|
||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand;
|
import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand;
|
||||||
import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase;
|
import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase;
|
||||||
import com.cloud.resource.CommandWrapper;
|
import com.cloud.resource.ServerResource;
|
||||||
|
|
||||||
public final class CitrixCheckConsoleProxyLoadCommandWrapper extends CommandWrapper<CheckConsoleProxyLoadCommand, Answer, CitrixResourceBase> {
|
public final class CitrixCheckConsoleProxyLoadCommandWrapper extends CitrixConsoleProxyLoadCommandWrapper<CheckConsoleProxyLoadCommand, Answer, CitrixResourceBase> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Answer execute(final CheckConsoleProxyLoadCommand command, final CitrixResourceBase citrixResourceBase) {
|
public Answer execute(final Command command, final ServerResource serverResource) {
|
||||||
final long proxyVmId = command.getProxyVmId();
|
final CheckConsoleProxyLoadCommand cmd = (CheckConsoleProxyLoadCommand) command;
|
||||||
final String proxyVmName = command.getProxyVmName();
|
|
||||||
final String proxyManagementIp = command.getProxyManagementIp();
|
final long proxyVmId = cmd.getProxyVmId();
|
||||||
final int cmdPort = command.getProxyCmdPort();
|
final String proxyVmName = cmd.getProxyVmName();
|
||||||
|
final String proxyManagementIp = cmd.getProxyManagementIp();
|
||||||
|
final int cmdPort = cmd.getProxyCmdPort();
|
||||||
|
|
||||||
return executeProxyLoadScan(command, proxyVmId, proxyVmName, proxyManagementIp, cmdPort);
|
return executeProxyLoadScan(command, proxyVmId, proxyVmName, proxyManagementIp, cmdPort);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// 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.hypervisor.xenserver.resource.wrapper;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer;
|
||||||
|
import com.cloud.resource.CommandWrapper;
|
||||||
|
import com.cloud.resource.ServerResource;
|
||||||
|
|
||||||
|
public abstract class CitrixConsoleProxyLoadCommandWrapper<T extends Command, A extends Answer, R extends ServerResource> extends CommandWrapper<Command, Answer, ServerResource> {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(CitrixConsoleProxyLoadCommandWrapper.class);
|
||||||
|
|
||||||
|
protected Answer executeProxyLoadScan(final Command cmd, final long proxyVmId, final String proxyVmName, final String proxyManagementIp, final int cmdPort) {
|
||||||
|
String result = null;
|
||||||
|
|
||||||
|
final StringBuffer sb = new StringBuffer();
|
||||||
|
sb.append("http://").append(proxyManagementIp).append(":" + cmdPort).append("/cmd/getstatus");
|
||||||
|
|
||||||
|
boolean success = true;
|
||||||
|
try {
|
||||||
|
final URL url = new URL(sb.toString());
|
||||||
|
final URLConnection conn = url.openConnection();
|
||||||
|
|
||||||
|
// setting TIMEOUTs to avoid possible waiting until death situations
|
||||||
|
conn.setConnectTimeout(5000);
|
||||||
|
conn.setReadTimeout(5000);
|
||||||
|
|
||||||
|
final InputStream is = conn.getInputStream();
|
||||||
|
final BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charset.defaultCharset()));
|
||||||
|
final StringBuilder sb2 = new StringBuilder();
|
||||||
|
String line = null;
|
||||||
|
try {
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
sb2.append(line + "\n");
|
||||||
|
}
|
||||||
|
result = sb2.toString();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
success = false;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
is.close();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
s_logger.warn("Exception when closing , console proxy address : " + proxyManagementIp);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (final IOException e) {
|
||||||
|
s_logger.warn("Unable to open console proxy command port url, console proxy address : " + proxyManagementIp);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ConsoleProxyLoadAnswer(cmd, proxyVmId, proxyVmName, success, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -107,12 +107,7 @@ public class CitrixRequestWrapper extends RequestWrapper {
|
|||||||
instance = new CitrixRequestWrapper();
|
instance = new CitrixRequestWrapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private final Hashtable<Class<? extends ServerResource>, Hashtable<Class<? extends Command>, CommandWrapper>> resources;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private CitrixRequestWrapper() {
|
private CitrixRequestWrapper() {
|
||||||
resources = new Hashtable<Class<? extends ServerResource>, Hashtable<Class<? extends Command>, CommandWrapper>>();
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,73 +227,4 @@ public class CitrixRequestWrapper extends RequestWrapper {
|
|||||||
|
|
||||||
return commandWrapper.execute(command, serverResource);
|
return commandWrapper.execute(command, serverResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
|
||||||
protected Hashtable<Class<? extends Command>, CommandWrapper> retrieveResource(final Command command, final Class<? extends ServerResource> resourceClass) {
|
|
||||||
Class<? extends ServerResource> keepResourceClass = resourceClass;
|
|
||||||
Hashtable<Class<? extends Command>, CommandWrapper> resource = resources.get(keepResourceClass);
|
|
||||||
while (resource == null) {
|
|
||||||
try {
|
|
||||||
final Class<? extends ServerResource> keepResourceClass2 = (Class<? extends ServerResource>) keepResourceClass.getSuperclass();
|
|
||||||
resource = resources.get(keepResourceClass2);
|
|
||||||
|
|
||||||
keepResourceClass = keepResourceClass2;
|
|
||||||
} catch (final ClassCastException e) {
|
|
||||||
throw new NullPointerException("No key found for '" + command.getClass() + "' in the Map!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
|
||||||
protected CommandWrapper<Command, Answer, ServerResource> retrieveCommands(final Class<? extends Command> commandClass,
|
|
||||||
final Hashtable<Class<? extends Command>, CommandWrapper> resourceCommands) {
|
|
||||||
|
|
||||||
Class<? extends Command> keepCommandClass = commandClass;
|
|
||||||
CommandWrapper<Command, Answer, ServerResource> commandWrapper = resourceCommands.get(keepCommandClass);
|
|
||||||
while (commandWrapper == null) {
|
|
||||||
try {
|
|
||||||
final Class<? extends Command> commandClass2 = (Class<? extends Command>) keepCommandClass.getSuperclass();
|
|
||||||
|
|
||||||
if (commandClass2 == null) {
|
|
||||||
throw new NullPointerException("All the COMMAND hierarchy tree has been visited but no compliant key has been found for '" + commandClass +"'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
commandWrapper = resourceCommands.get(commandClass2);
|
|
||||||
|
|
||||||
keepCommandClass = commandClass2;
|
|
||||||
} catch (final NullPointerException e) {
|
|
||||||
// Will now traverse all the resource hierarchy. Returning null is not a problem.
|
|
||||||
// It is all being nicely checked and in case we do not have a resource, an Unsupported answer will be thrown by the base class.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return commandWrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
|
||||||
protected CommandWrapper<Command, Answer, ServerResource> retryWhenAllFails(final Command command, final Class<? extends ServerResource> resourceClass,
|
|
||||||
final Hashtable<Class<? extends Command>, CommandWrapper> resourceCommands) {
|
|
||||||
|
|
||||||
Class<? extends ServerResource> keepResourceClass = resourceClass;
|
|
||||||
CommandWrapper<Command, Answer, ServerResource> commandWrapper = resourceCommands.get(command.getClass());
|
|
||||||
while (commandWrapper == null) {
|
|
||||||
//Could not find the command in the given resource, will traverse the family tree.
|
|
||||||
try {
|
|
||||||
final Class<? extends ServerResource> resourceClass2 = (Class<? extends ServerResource>) keepResourceClass.getSuperclass();
|
|
||||||
|
|
||||||
if (resourceClass2 == null) {
|
|
||||||
throw new NullPointerException("All the SERVER-RESOURCE hierarchy tree has been visited but no compliant key has been found for '" + command.getClass() +"'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Hashtable<Class<? extends Command>, CommandWrapper> resourceCommands2 = retrieveResource(command, (Class<? extends ServerResource>) keepResourceClass.getSuperclass());
|
|
||||||
keepResourceClass = resourceClass2;
|
|
||||||
|
|
||||||
commandWrapper = retrieveCommands(command.getClass(), resourceCommands2);
|
|
||||||
} catch (final NullPointerException e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return commandWrapper;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -20,18 +20,21 @@
|
|||||||
package com.cloud.hypervisor.xenserver.resource.wrapper;
|
package com.cloud.hypervisor.xenserver.resource.wrapper;
|
||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
|
import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
|
||||||
import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase;
|
import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase;
|
||||||
import com.cloud.resource.CommandWrapper;
|
import com.cloud.resource.ServerResource;
|
||||||
|
|
||||||
public final class CitrixWatchConsoleProxyLoadCommandWrapper extends CommandWrapper<WatchConsoleProxyLoadCommand, Answer, CitrixResourceBase> {
|
public final class CitrixWatchConsoleProxyLoadCommandWrapper extends CitrixConsoleProxyLoadCommandWrapper<WatchConsoleProxyLoadCommand, Answer, CitrixResourceBase> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Answer execute(final WatchConsoleProxyLoadCommand command, final CitrixResourceBase citrixResourceBase) {
|
public Answer execute(final Command command, final ServerResource serverResource) {
|
||||||
final long proxyVmId = command.getProxyVmId();
|
final WatchConsoleProxyLoadCommand cmd = (WatchConsoleProxyLoadCommand) command;
|
||||||
final String proxyVmName = command.getProxyVmName();
|
|
||||||
final String proxyManagementIp = command.getProxyManagementIp();
|
final long proxyVmId = cmd.getProxyVmId();
|
||||||
final int cmdPort = command.getProxyCmdPort();
|
final String proxyVmName = cmd.getProxyVmName();
|
||||||
|
final String proxyManagementIp = cmd.getProxyManagementIp();
|
||||||
|
final int cmdPort = cmd.getProxyCmdPort();
|
||||||
|
|
||||||
return executeProxyLoadScan(command, proxyVmId, proxyVmName, proxyManagementIp, cmdPort);
|
return executeProxyLoadScan(command, proxyVmId, proxyVmName, proxyManagementIp, cmdPort);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,7 +42,6 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.powermock.api.mockito.PowerMockito;
|
import org.powermock.api.mockito.PowerMockito;
|
||||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
|
||||||
import org.powermock.modules.junit4.PowerMockRunner;
|
import org.powermock.modules.junit4.PowerMockRunner;
|
||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
@ -136,7 +135,6 @@ import com.xensource.xenapi.Types.BadServerResponse;
|
|||||||
import com.xensource.xenapi.Types.XenAPIException;
|
import com.xensource.xenapi.Types.XenAPIException;
|
||||||
|
|
||||||
@RunWith(PowerMockRunner.class)
|
@RunWith(PowerMockRunner.class)
|
||||||
@PrepareForTest({ Connection.class, Host.Record.class })
|
|
||||||
public class CitrixRequestWrapperTest {
|
public class CitrixRequestWrapperTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
@ -279,7 +277,7 @@ public class CitrixRequestWrapperTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStopCommandCommand() {
|
public void testStopCommand() {
|
||||||
final StopCommand stopCommand = new StopCommand("Test", false, false);
|
final StopCommand stopCommand = new StopCommand("Test", false, false);
|
||||||
|
|
||||||
final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance();
|
final CitrixRequestWrapper wrapper = CitrixRequestWrapper.getInstance();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user