Another merge from master. This is just getting laborious

This commit is contained in:
Alex Huang 2013-07-01 11:29:57 -07:00
commit 57bafc8fe9
238 changed files with 7404 additions and 4003 deletions

View File

@ -1,504 +0,0 @@
// 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.agent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.Agent.ExitStatus;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.StartupVMMAgentCommand;
import com.cloud.agent.dao.StorageComponent;
import com.cloud.agent.dao.impl.PropertiesStorage;
import com.cloud.agent.transport.Request;
import com.cloud.resource.ServerResource;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.backoff.BackoffAlgorithm;
import com.cloud.utils.backoff.impl.ConstantTimeBackoff;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.MacAddress;
import com.cloud.utils.nio.HandlerFactory;
import com.cloud.utils.nio.Link;
import com.cloud.utils.nio.NioServer;
import com.cloud.utils.nio.Task;
/**
* Implementation of agent shell to run the agents on System Center Virtual Machine manager
**/
public class VmmAgentShell implements IAgentShell, HandlerFactory {
private static final Logger s_logger = Logger.getLogger(VmmAgentShell.class.getName());
private final Properties _properties = new Properties();
private final Map<String, Object> _cmdLineProperties = new HashMap<String, Object>();
private StorageComponent _storage;
private BackoffAlgorithm _backoff;
private String _version;
private String _zone;
private String _pod;
private String _cluster;
private String _host;
private String _privateIp;
private int _port;
private int _proxyPort;
private int _workers;
private String _guid;
static private NioServer _connection;
static private int _listenerPort=9000;
private int _nextAgentId = 1;
private volatile boolean _exit = false;
private int _pingRetries;
private final Thread _consoleProxyMain = null;
private final List<Agent> _agents = new ArrayList<Agent>();
public VmmAgentShell() {
}
@Override
public Properties getProperties() {
return _properties;
}
@Override
public BackoffAlgorithm getBackoffAlgorithm() {
return _backoff;
}
@Override
public int getPingRetries() {
return _pingRetries;
}
@Override
public String getZone() {
return _zone;
}
@Override
public String getPod() {
return _pod;
}
@Override
public String getHost() {
return _host;
}
@Override
public String getPrivateIp() {
return _privateIp;
}
@Override
public int getPort() {
return _port;
}
@Override
public int getProxyPort() {
return _proxyPort;
}
@Override
public int getWorkers() {
return _workers;
}
@Override
public String getGuid() {
return _guid;
}
@Override
public void upgradeAgent(String url) {
// TODO Auto-generated method stub
}
@Override
public String getVersion() {
return _version;
}
@Override
public Map<String, Object> getCmdLineProperties() {
// TODO Auto-generated method stub
return _cmdLineProperties;
}
public String getProperty(String prefix, String name) {
if(prefix != null)
return _properties.getProperty(prefix + "." + name);
return _properties.getProperty(name);
}
@Override
public String getPersistentProperty(String prefix, String name) {
if(prefix != null)
return _storage.get(prefix + "." + name);
return _storage.get(name);
}
@Override
public void setPersistentProperty(String prefix, String name, String value) {
if(prefix != null)
_storage.persist(prefix + "." + name, value);
else
_storage.persist(name, value);
}
private void loadProperties() throws ConfigurationException {
final File file = PropertiesUtil.findConfigFile("agent.properties");
if (file == null) {
throw new ConfigurationException("Unable to find agent.properties.");
}
s_logger.info("agent.properties found at " + file.getAbsolutePath());
try {
_properties.load(new FileInputStream(file));
} catch (final FileNotFoundException ex) {
throw new CloudRuntimeException("Cannot find the file: " + file.getAbsolutePath(), ex);
} catch (final IOException ex) {
throw new CloudRuntimeException("IOException in reading " + file.getAbsolutePath(), ex);
}
}
protected boolean parseCommand(final String[] args) throws ConfigurationException {
String host = null;
String workers = null;
String port = null;
String zone = null;
String pod = null;
String guid = null;
for (int i = 0; i < args.length; i++) {
final String[] tokens = args[i].split("=");
if (tokens.length != 2) {
System.out.println("Invalid Parameter: " + args[i]);
continue;
}
// save command line properties
_cmdLineProperties.put(tokens[0], tokens[1]);
if (tokens[0].equalsIgnoreCase("port")) {
port = tokens[1];
} else if (tokens[0].equalsIgnoreCase("threads")) {
workers = tokens[1];
} else if (tokens[0].equalsIgnoreCase("host")) {
host = tokens[1];
} else if(tokens[0].equalsIgnoreCase("zone")) {
zone = tokens[1];
} else if(tokens[0].equalsIgnoreCase("pod")) {
pod = tokens[1];
} else if(tokens[0].equalsIgnoreCase("guid")) {
guid = tokens[1];
} else if(tokens[0].equalsIgnoreCase("eth1ip")) {
_privateIp = tokens[1];
}
}
if (port == null) {
port = getProperty(null, "port");
}
_port = NumbersUtil.parseInt(port, 8250);
_proxyPort = NumbersUtil.parseInt(getProperty(null, "consoleproxy.httpListenPort"), 443);
if (workers == null) {
workers = getProperty(null, "workers");
}
_workers = NumbersUtil.parseInt(workers, 5);
if (host == null) {
host = getProperty(null, "host");
}
if (host == null) {
host = "localhost";
}
_host = host;
if(zone != null)
_zone = zone;
else
_zone = getProperty(null, "zone");
if (_zone == null || (_zone.startsWith("@") && _zone.endsWith("@"))) {
_zone = "default";
}
if(pod != null)
_pod = pod;
else
_pod = getProperty(null, "pod");
if (_pod == null || (_pod.startsWith("@") && _pod.endsWith("@"))) {
_pod = "default";
}
if (_host == null || (_host.startsWith("@") && _host.endsWith("@"))) {
throw new ConfigurationException("Host is not configured correctly: " + _host);
}
final String retries = getProperty(null, "ping.retries");
_pingRetries = NumbersUtil.parseInt(retries, 5);
String value = getProperty(null, "developer");
boolean developer = Boolean.parseBoolean(value);
if(guid != null)
_guid = guid;
else
_guid = getProperty(null, "guid");
if (_guid == null) {
if (!developer) {
throw new ConfigurationException("Unable to find the guid");
}
_guid = MacAddress.getMacAddress().toString(":");
}
return true;
}
private void launchAgentFromTypeInfo() throws ConfigurationException {
String typeInfo = getProperty(null, "type");
if (typeInfo == null) {
s_logger.error("Unable to retrieve the type");
throw new ConfigurationException("Unable to retrieve the type of this agent.");
}
s_logger.trace("Launching agent based on type=" + typeInfo);
}
private void launchAgent() throws ConfigurationException {
String resourceClassNames = getProperty(null, "resource");
s_logger.trace("resource=" + resourceClassNames);
if(resourceClassNames != null) {
launchAgentFromClassInfo(resourceClassNames);
return;
}
launchAgentFromTypeInfo();
}
private void init(String[] args) throws ConfigurationException{
final Class<?> c = this.getClass();
_version = c.getPackage().getImplementationVersion();
if (_version == null) {
throw new CloudRuntimeException("Unable to find the implementation version of this agent");
}
s_logger.info("Implementation Version is " + _version);
parseCommand(args);
s_logger.info("Defaulting to using properties file for storage");
_storage = new PropertiesStorage();
_storage.configure("Storage", new HashMap<String, Object>());
// merge with properties from command line to let resource access command line parameters
for(Map.Entry<String, Object> cmdLineProp : getCmdLineProperties().entrySet()) {
_properties.put(cmdLineProp.getKey(), cmdLineProp.getValue());
}
s_logger.info("Defaulting to the constant time backoff algorithm");
_backoff = new ConstantTimeBackoff();
_backoff.configure("ConstantTimeBackoff", new HashMap<String, Object>());
}
private void launchAgentFromClassInfo(String resourceClassNames) throws ConfigurationException {
String[] names = resourceClassNames.split("\\|");
for(String name: names) {
Class<?> impl;
try {
impl = Class.forName(name);
final Constructor<?> constructor = impl.getDeclaredConstructor();
constructor.setAccessible(true);
ServerResource resource = (ServerResource)constructor.newInstance();
launchAgent(getNextAgentId(), resource);
} catch (final ClassNotFoundException e) {
throw new ConfigurationException("Resource class not found: " + name);
} catch (final SecurityException e) {
throw new ConfigurationException("Security excetion when loading resource: " + name);
} catch (final NoSuchMethodException e) {
throw new ConfigurationException("Method not found excetion when loading resource: " + name);
} catch (final IllegalArgumentException e) {
throw new ConfigurationException("Illegal argument excetion when loading resource: " + name);
} catch (final InstantiationException e) {
throw new ConfigurationException("Instantiation excetion when loading resource: " + name);
} catch (final IllegalAccessException e) {
throw new ConfigurationException("Illegal access exception when loading resource: " + name);
} catch (final InvocationTargetException e) {
throw new ConfigurationException("Invocation target exception when loading resource: " + name);
}
}
}
private void launchAgent(int localAgentId, ServerResource resource) throws ConfigurationException {
// we don't track agent after it is launched for now
Agent agent = new Agent(this, localAgentId, resource);
_agents.add(agent);
agent.start();
}
public synchronized int getNextAgentId() {
return _nextAgentId++;
}
private void run(String[] args) {
try {
System.setProperty("java.net.preferIPv4Stack","true");
loadProperties();
init(args);
String instance = getProperty(null, "instance");
if (instance == null) {
instance = "";
} else {
instance += ".";
}
// TODO need to do this check. For Agentshell running on windows needs different approach
//final String run = "agent." + instance + "pid";
//s_logger.debug("Checking to see if " + run + "exists.");
//ProcessUtil.pidCheck(run);
// TODO: For Hyper-V agent.properties need to be revamped to support multiple agents
// corresponding to multiple clusters but running on a SCVMM host
// read the persistent storage and launch the agents
//launchAgent();
// FIXME get rid of this approach of agent listening for boot strap commands from the management server
// now listen for bootstrap request from the management server and launch agents
_connection = new NioServer("VmmAgentShell", _listenerPort, 1, this);
_connection.start();
s_logger.info("SCVMM agent is listening on port " +_listenerPort + " for bootstrap command from management server");
while(_connection.isRunning());
} catch(final ConfigurationException e) {
s_logger.error("Unable to start agent: " + e.getMessage());
System.out.println("Unable to start agent: " + e.getMessage());
System.exit(ExitStatus.Configuration.value());
} catch (final Exception e) {
s_logger.error("Unable to start agent: ", e);
System.out.println("Unable to start agent: " + e.getMessage());
System.exit(ExitStatus.Error.value());
}
}
@Override
public Task create(com.cloud.utils.nio.Task.Type type, Link link,
byte[] data) {
return new AgentBootStrapHandler(type, link, data);
}
public void stop() {
_exit = true;
if(_consoleProxyMain != null) {
_consoleProxyMain.interrupt();
}
}
public static void main(String[] args) {
VmmAgentShell shell = new VmmAgentShell();
Runtime.getRuntime().addShutdownHook(new ShutdownThread(shell));
shell.run(args);
}
// class to handle the bootstrap command from the management server
private class AgentBootStrapHandler extends Task {
public AgentBootStrapHandler(Task.Type type, Link link, byte[] data) {
super(type, link, data);
}
@Override
protected void doTask(Task task) throws Exception {
final Type type = task.getType();
s_logger.info("recieved task of type "+ type.toString() +" to handle in BootStrapTakHandler");
if (type == Task.Type.DATA)
{
final byte[] data = task.getData();
final Request request = Request.parse(data);
final Command cmd = request.getCommand();
if (cmd instanceof StartupVMMAgentCommand) {
StartupVMMAgentCommand vmmCmd = (StartupVMMAgentCommand) cmd;
_zone = Long.toString(vmmCmd.getDataCenter());
_cmdLineProperties.put("zone", _zone);
_pod = Long.toString(vmmCmd.getPod());
_cmdLineProperties.put("pod", _pod);
_cluster = vmmCmd.getClusterName();
_cmdLineProperties.put("cluster", _cluster);
_guid = vmmCmd.getGuid();
_cmdLineProperties.put("guid", _guid);
_host = vmmCmd.getManagementServerIP();
_port = NumbersUtil.parseInt(vmmCmd.getport(), 8250);
s_logger.info("Recieved boot strap command from management server with parameters " +
" Zone:"+ _zone + " "+
" Cluster:"+ _cluster + " "+
" pod:"+_pod + " "+
" host:"+ _host +" "+
" port:"+_port);
launchAgentFromClassInfo("com.cloud.hypervisor.hyperv.resource.HypervResource");
// TODO: persist the info in agent.properties for agent restarts
}
}
}
}
private static class ShutdownThread extends Thread {
VmmAgentShell _shell;
public ShutdownThread(VmmAgentShell shell) {
this._shell = shell;
}
@Override
public void run() {
_shell.stop();
}
}
}

View File

@ -23,14 +23,16 @@ import com.cloud.storage.Volume;
public class DiskTO {
private DataTO data;
private Long diskSeq;
private String vdiUuid;
private Volume.Type type;
public DiskTO() {
}
public DiskTO(DataTO data, Long diskSeq, Volume.Type type) {
public DiskTO(DataTO data, Long diskSeq, String vdiUuid, Volume.Type type) {
this.data = data;
this.diskSeq = diskSeq;
this.vdiUuid = vdiUuid;
this.type = type;
}
@ -50,6 +52,14 @@ public class DiskTO {
this.diskSeq = diskSeq;
}
public String getVdiUuid() {
return vdiUuid;
}
public void setVdiUuid(String vdiUuid) {
this.vdiUuid = vdiUuid;
}
public Volume.Type getType() {
return type;
}

View File

@ -108,6 +108,12 @@ public class FirewallRuleTO implements InternalIdentity {
this.trafficType = trafficType;
}
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, FirewallRule.Purpose purpose, FirewallRule.TrafficType trafficType, boolean defaultEgressPolicy) {
this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, purpose,rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
this.trafficType = trafficType;
this.defaultEgressPolicy = defaultEgressPolicy;
}
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, FirewallRule.Purpose purpose, boolean revokeState, boolean alreadyAdded) {
this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), revokeState, alreadyAdded, purpose,rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
}

View File

@ -276,4 +276,6 @@ public interface NetworkModel {
Nic getNicInNetworkIncludingRemoved(long vmId, long networkId);
boolean getExecuteInSeqNtwkElmtCmd();
boolean isNetworkReadyForGc(long networkId);
}

View File

@ -47,12 +47,24 @@ public interface DiskOffering extends InfrastructureEntity, Identity, InternalId
Date getCreated();
long getDiskSize();
boolean isCustomized();
void setDiskSize(long diskSize);
long getDiskSize();
void setCustomizedIops(Boolean customizedIops);
Boolean isCustomizedIops();
void setMinIops(Long minIops);
Long getMinIops();
void setMaxIops(Long maxIops);
Long getMaxIops();
void setBytesReadRate(Long bytesReadRate);
Long getBytesReadRate();

View File

@ -26,6 +26,7 @@ public class Storage {
VHD(true, true, true, "vhd"),
ISO(false, false, false, "iso"),
OVA(true, true, true, "ova"),
VHDX(true, true, true, "vhdx"),
BAREMETAL(false, false, false, "BAREMETAL"),
TAR(false, false, false, "tar");

View File

@ -60,6 +60,8 @@ public interface StoragePool extends Identity, InternalIdentity {
*/
long getUsedBytes();
Long getCapacityIops();
Long getClusterId();
/**

View File

@ -122,6 +122,12 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba
*/
Long getSize();
Long getMinIops();
Long getMaxIops();
String get_iScsiName();
/**
* @return the vm instance id
*/

View File

@ -51,6 +51,9 @@ public class ApiConstants {
public static final String CPU_OVERCOMMIT_RATIO="cpuovercommitratio";
public static final String CREATED = "created";
public static final String CUSTOMIZED = "customized";
public static final String CUSTOMIZED_IOPS = "customizediops";
public static final String MIN_IOPS = "miniops";
public static final String MAX_IOPS = "maxiops";
public static final String DESCRIPTION = "description";
public static final String DESTINATION_ZONE_ID = "destzoneid";
public static final String DETAILS = "details";
@ -326,6 +329,9 @@ public class ApiConstants {
public static final String SERVICE_CAPABILITY_LIST = "servicecapabilitylist";
public static final String CAN_CHOOSE_SERVICE_CAPABILITY = "canchooseservicecapability";
public static final String PROVIDER = "provider";
public static final String MANAGED = "managed";
public static final String CAPACITY_BYTES = "capacitybytes";
public static final String CAPACITY_IOPS = "capacityiops";
public static final String NETWORK_SPEED = "networkspeed";
public static final String BROADCAST_DOMAIN_RANGE = "broadcastdomainrange";
public static final String ISOLATION_METHODS = "isolationmethods";

View File

@ -53,7 +53,7 @@ public class CreateDiskOfferingCmd extends BaseCmd {
@Parameter(name=ApiConstants.TAGS, type=CommandType.STRING, description="tags for the disk offering", length=4096)
private String tags;
@Parameter(name=ApiConstants.CUSTOMIZED, type=CommandType.BOOLEAN, description="whether disk offering is custom or not")
@Parameter(name=ApiConstants.CUSTOMIZED, type=CommandType.BOOLEAN, description="whether disk offering size is custom or not")
private Boolean customized;
@Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
@ -63,6 +63,9 @@ public class CreateDiskOfferingCmd extends BaseCmd {
@Parameter(name=ApiConstants.STORAGE_TYPE, type=CommandType.STRING, description="the storage type of the disk offering. Values are local and shared.")
private String storageType = ServiceOffering.StorageType.shared.toString();
@Parameter(name=ApiConstants.DISPLAY_OFFERING, type=CommandType.BOOLEAN, description="an optional field, whether to display the offering to the end user or not.")
private Boolean displayOffering;
@Parameter(name=ApiConstants.BYTES_READ_RATE, type=CommandType.LONG, required=false, description="bytes read rate of the disk offering")
private Long bytesReadRate;
@ -75,8 +78,14 @@ public class CreateDiskOfferingCmd extends BaseCmd {
@Parameter(name=ApiConstants.IOPS_WRITE_RATE, type=CommandType.LONG, required=false, description="io requests write rate of the disk offering")
private Long iopsWriteRate;
@Parameter(name=ApiConstants.DISPLAY_OFFERING, type=CommandType.BOOLEAN, description="an optional field, whether to display the offering to the end user or not.")
private Boolean displayOffering;
@Parameter(name=ApiConstants.CUSTOMIZED_IOPS, type=CommandType.BOOLEAN, required=false, description="whether disk offering iops is custom or not")
private Boolean customizedIops;
@Parameter(name=ApiConstants.MIN_IOPS, type=CommandType.LONG, required=false, description="min iops of the disk offering")
private Long minIops;
@Parameter(name=ApiConstants.MAX_IOPS, type=CommandType.LONG, required=false, description="max iops of the disk offering")
private Long maxIops;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -102,6 +111,18 @@ public class CreateDiskOfferingCmd extends BaseCmd {
return customized;
}
public Boolean isCustomizedIops() {
return customizedIops;
}
public Long getMinIops() {
return minIops;
}
public Long getMaxIops() {
return maxIops;
}
public Long getDomainId(){
return domainId;
}

View File

@ -81,6 +81,18 @@ public class CreateStoragePoolCmd extends BaseCmd {
required=false, description="the scope of the storage: cluster or zone")
private String scope;
@Parameter(name=ApiConstants.MANAGED, type=CommandType.BOOLEAN,
required=false, description="whether the storage should be managed by CloudStack")
private Boolean managed;
@Parameter(name=ApiConstants.CAPACITY_IOPS, type=CommandType.LONG,
required=false, description="IOPS CloudStack can provision from this storage pool")
private Long capacityIops;
@Parameter(name=ApiConstants.CAPACITY_BYTES, type=CommandType.LONG,
required=false, description="bytes CloudStack can provision from this storage pool")
private Long capacityBytes;
@Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, required=false,
description="hypervisor type of the hosts in zone that will be attached to this storage pool. KVM, VMware supported as of now.")
private String hypervisor;
@ -125,6 +137,18 @@ public class CreateStoragePoolCmd extends BaseCmd {
return this.scope;
}
public Boolean isManaged() {
return managed;
}
public Long getCapacityIops() {
return capacityIops;
}
public Long getCapacityBytes() {
return capacityBytes;
}
public String getHypervisor() {
return hypervisor;
}

View File

@ -213,7 +213,7 @@ public class RegisterTemplateCmd extends BaseCmd {
}
public Boolean isRoutingType() {
return isRoutingType == null ? false : isRoutingType;
return isRoutingType;
}
/////////////////////////////////////////////////////

View File

@ -69,6 +69,12 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd {
@Parameter(name=ApiConstants.SIZE, type=CommandType.LONG, description="Arbitrary volume size")
private Long size;
@Parameter(name=ApiConstants.MIN_IOPS, type=CommandType.LONG, description="min iops")
private Long minIops;
@Parameter(name=ApiConstants.MAX_IOPS, type=CommandType.LONG, description="max iops")
private Long maxIops;
@Parameter(name=ApiConstants.SNAPSHOT_ID, type=CommandType.UUID, entityType=SnapshotResponse.class,
description="the snapshot ID for the disk volume. Either diskOfferingId or snapshotId must be passed in.")
private Long snapshotId;
@ -105,6 +111,14 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd {
return size;
}
public Long getMinIops() {
return minIops;
}
public Long getMaxIops() {
return maxIops;
}
public Long getSnapshotId() {
return snapshotId;
}

View File

@ -53,6 +53,15 @@ public class DiskOfferingResponse extends BaseResponse {
@SerializedName("iscustomized") @Param(description="true if disk offering uses custom size, false otherwise")
private Boolean customized;
@SerializedName("iscustomizediops") @Param(description="true if disk offering uses custom iops, false otherwise")
private Boolean customizedIops;
@SerializedName(ApiConstants.MIN_IOPS) @Param(description="the min iops of the disk offering")
private Long minIops;
@SerializedName(ApiConstants.MAX_IOPS) @Param(description="the max iops of the disk offering")
private Long maxIops;
@SerializedName(ApiConstants.TAGS) @Param(description="the tags for the disk offering")
private String tags;
@ -155,6 +164,30 @@ public class DiskOfferingResponse extends BaseResponse {
this.customized = customized;
}
public Boolean isCustomizedIops() {
return customizedIops;
}
public void setCustomizedIops(Boolean customizedIops) {
this.customizedIops = customizedIops;
}
public Long getMinIops() {
return minIops;
}
public void setMinIops(Long minIops) {
this.minIops = minIops;
}
public Long getMaxIops() {
return maxIops;
}
public void setMaxIops(Long maxIops) {
this.maxIops = maxIops;
}
public String getStorageType() {
return storageType;
}

View File

@ -76,6 +76,9 @@ public class StoragePoolResponse extends BaseResponse {
@SerializedName("disksizeused") @Param(description="the host's currently used disk size")
private Long diskSizeUsed;
@SerializedName("capacityiops") @Param(description="IOPS CloudStack can provision from this storage pool")
private Long capacityIops;
@SerializedName("tags") @Param(description="the tags for the storage pool")
private String tags;
@ -239,6 +242,14 @@ public class StoragePoolResponse extends BaseResponse {
this.diskSizeUsed = diskSizeUsed;
}
public Long getCapacityIops() {
return capacityIops;
}
public void setCapacityIops(Long capacityIops) {
this.capacityIops = capacityIops;
}
public String getTags() {
return tags;
}

View File

@ -16,6 +16,8 @@
// under the License.
package org.apache.cloudstack.api.response;
import java.util.Date;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
@ -29,6 +31,15 @@ public class TemplateZoneResponse extends BaseResponse {
@SerializedName(ApiConstants.ZONE_NAME) @Param(description="the name of the zone for the template")
private String zoneName;
@SerializedName(ApiConstants.STATUS) @Param(description="the status of the template")
private String status;
@SerializedName(ApiConstants.IS_READY) // propName="ready" (FIXME: this used to be part of Param annotation, do we need it?)
@Param(description="true if the template is ready to be deployed from, false otherwise.")
private boolean isReady;
@SerializedName(ApiConstants.CREATED) @Param(description="the date this template was created")
private Date created;
public TemplateZoneResponse(){
super();
@ -58,6 +69,31 @@ public class TemplateZoneResponse extends BaseResponse {
this.zoneName = zoneName;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public boolean isReady() {
return isReady;
}
public void setReady(boolean isReady) {
this.isReady = isReady;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
@Override
public int hashCode() {
final int prime = 31;
@ -69,21 +105,26 @@ public class TemplateZoneResponse extends BaseResponse {
@Override
public boolean equals(Object obj) {
if (this == obj)
if (this == obj) {
return true;
if (obj == null)
}
if (obj == null) {
return false;
if (getClass() != obj.getClass())
}
if (getClass() != obj.getClass()) {
return false;
}
TemplateZoneResponse other = (TemplateZoneResponse) obj;
String oid = this.getZoneId();
if (oid == null) {
if (other.getZoneId() != null)
if (other.getZoneId() != null) {
return false;
} else if (!oid.equals(other.getZoneId()))
}
} else if (!oid.equals(other.getZoneId())) {
return false;
else if ( this.getZoneName().equals(other.getZoneName()))
} else if ( this.getZoneName().equals(other.getZoneName())) {
return false;
}
return true;
}

View File

@ -76,6 +76,14 @@ public class VolumeResponse extends BaseResponse implements ControlledViewEntity
@Param(description = "size of the disk volume")
private Long size;
@SerializedName(ApiConstants.MIN_IOPS)
@Param(description = "min iops of the disk volume")
private Long minIops;
@SerializedName(ApiConstants.MAX_IOPS)
@Param(description = "max iops of the disk volume")
private Long maxIops;
@SerializedName(ApiConstants.CREATED)
@Param(description = "the date the disk volume was created")
private Date created;
@ -241,6 +249,14 @@ public class VolumeResponse extends BaseResponse implements ControlledViewEntity
this.size = size;
}
public void setMinIops(Long minIops) {
this.minIops = minIops;
}
public void setMaxIops(Long maxIops) {
this.maxIops = maxIops;
}
public void setCreated(Date created) {
this.created = created;
}

View File

@ -849,9 +849,9 @@ public class EC2Engine extends ManagerBase {
CloudStackAccount caller = getCurrentAccount();
CloudStackZone zone = findZone();
CloudStackNetwork net = findNetwork(zone);
//CloudStackNetwork net = findNetwork(zone);
// CloudStackIpAddress resp = getApi().associateIpAddress(null, null, null, "0036952d-48df-4422-9fd0-94b0885e18cb");
CloudStackIpAddress resp = getApi().associateIpAddress(zone.getId(), caller.getName(), caller.getDomainId(), net != null ? net.getId():null);
CloudStackIpAddress resp = getApi().associateIpAddress(zone.getId(), caller.getName(), caller.getDomainId(), null);
ec2Address.setAssociatedInstanceId(resp.getId());
if (resp.getIpAddress() == null) {
@ -1399,14 +1399,14 @@ public class EC2Engine extends ManagerBase {
CloudStackZone zone = zones.get(0);
// network
CloudStackNetwork network = findNetwork(zone);
//CloudStackNetwork network = findNetwork(zone);
// now actually deploy the vms
for( int i=0; i < createInstances; i++ ) {
try{
CloudStackUserVm resp = getApi().deployVirtualMachine(svcOffering.getId(),
request.getTemplateId(), zoneId, null, null, null, null,
null, null, null, request.getKeyName(), null, (network != null ? network.getId() : null),
request.getTemplateId(), zoneId, null, null, null, null,
null, null, null, request.getKeyName(), null, null,
null, constructList(request.getGroupSet()), request.getSize().longValue(), request.getUserData());
EC2Instance vm = new EC2Instance();
vm.setId(resp.getId().toString());
@ -1744,16 +1744,8 @@ public class EC2Engine extends ManagerBase {
private CloudStackServiceOfferingVO getCSServiceOfferingId(String instanceType) throws Exception {
try {
// list of valid values for AWS EC2 instanceType
String[] validInstanceTypes = {"t1.micro", "m1.small", "m1.medium", "m1.large", "m1.xlarge",
"c1.medium", "c1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge",
"m3.xlarge", "m3.2xlarge", "hi1.4xlarge", "cc1.4xlarge", "cg1.4xlarge", "cc2.8xlarge"};
if (instanceType == null)
instanceType = "m1.small"; // default value
else if ( !Arrays.asList(validInstanceTypes).contains(instanceType)) {
throw new Exception("Specified instance type is invalid");
}
return scvoDao.getSvcOfferingByName(instanceType);
} catch(Exception e) {
logger.error( "Error while retrieving ServiceOffering information by name - ", e);

View File

@ -14,6 +14,10 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
label.custom.disk.iops=Custom IOPS
label.disk.iops.min=Min IOPS
label.disk.iops.max=Max IOPS
label.disk.iops.total=IOPS Total
label.view.secondary.ips=View secondary IPs
message.acquire.ip.nic=Please confirm that you would like to acquire a new secondary IP for this NIC.<br/>NOTE: You need to manually configure the newly-acquired secondary IP inside the virtual machine.
message.select.affinity.groups=Please select any affinity groups you want this VM to belong to:
@ -395,7 +399,7 @@ label.code=Code
label.community=Community
label.compute.and.storage=Compute and Storage
label.compute.offering=Compute offering
label.compute.offerings=Compute offerings
label.compute.offerings=Compute Offerings
label.compute=Compute
label.configuration=Configuration
label.configure.network.ACLs=Configure Network ACLs
@ -1046,6 +1050,7 @@ label.stopped.vms=Stopped VMs
label.storage.tags=Storage Tags
label.storage.traffic=Storage Traffic
label.storage.type=Storage Type
label.qos.type=QoS Type
label.storage=Storage
label.subdomain.access=Subdomain Access
label.submit=Submit

View File

@ -20,6 +20,11 @@
<version>4.2.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-storage-volume-solidfire</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-server</artifactId>
@ -268,7 +273,12 @@
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-storage-image-swift</artifactId>
<version>${project.version}</version>
</dependency>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-storage-image-simulator</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-syslog-alerts</artifactId>

View File

@ -19,14 +19,12 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
@ -533,10 +531,6 @@
<property name="name" value="Lxc Discover"/>
</bean>
<bean id="HypervServerDiscoverer" class="com.cloud.hypervisor.hyperv.HypervServerDiscoverer">
<property name="name" value="SCVMMServer"/>
</bean>
<bean id="OvmDiscoverer" class="com.cloud.ovm.hypervisor.OvmDiscoverer">
<property name="name" value="Ovm Discover"/>
</bean>
@ -614,6 +608,95 @@
<property name="name" value="OvmGuru"/>
</bean>
<!--=====================================================================================================-->
<!-- -->
<!-- Storage Subsystem Components and Helpers -->
<!-- -->
<!--=====================================================================================================-->
<!--Filesystem types-->
<bean id="iSCSI" class="org.apache.cloudstack.storage.datastore.type.ISCSI" />
<bean id="networkFileSystem" class="org.apache.cloudstack.storage.datastore.type.NetworkFileSystem" />
<!--Image formats-->
<bean id="ISO" class="org.apache.cloudstack.storage.image.format.ISO" />
<bean id="OVA" class="org.apache.cloudstack.storage.image.format.OVA" />
<bean id="QCOW2" class="org.apache.cloudstack.storage.image.format.QCOW2" />
<bean id="VHD" class="org.apache.cloudstack.storage.image.format.VHD" />
<bean id="unknown" class="org.apache.cloudstack.storage.image.format.Unknown" />
<!--Data Store Services -->
<bean id="snapshotServiceImpl" class="org.apache.cloudstack.storage.snapshot.SnapshotServiceImpl"
depends-on="snapshotStateMachineManagerImpl, snapshotDataFactoryImpl, dataStoreManagerImpl, dataMotionServiceImpl, objectInDataStoreManagerImpl"/>
<bean id="templateServiceImpl" class="org.apache.cloudstack.storage.image.TemplateServiceImpl"
depends-on="dataObjectManagerImpl, dataStoreManagerImpl, dataMotionServiceImpl, objectInDataStoreManagerImpl, defaultEndPointSelector, templateDataFactoryImpl"/>
<bean id="volumeServiceImpl" class="org.apache.cloudstack.storage.volume.VolumeServiceImpl"
depends-on="snapshotManagerImpl, dataMotionServiceImpl"/>
<bean id="xenserverSnapshotStrategy" class="org.apache.cloudstack.storage.snapshot.XenserverSnapshotStrategy" />
<!--Data Store Factory-->
<bean id="templateDataFactoryImpl" class="org.apache.cloudstack.storage.image.TemplateDataFactoryImpl" />
<bean id="snapshotDataFactoryImpl" class="org.apache.cloudstack.storage.snapshot.SnapshotDataFactoryImpl"
depends-on="dataStoreManagerImpl, snapshotDataStoreDaoImpl, volumeDataFactoryImpl"/>
<bean id="volumeDataFactoryImpl" class="org.apache.cloudstack.storage.volume.VolumeDataFactoryImpl" />
<bean id="objectInDataStoreManagerImpl" class="org.apache.cloudstack.storage.datastore.ObjectInDataStoreManagerImpl" />
<bean id="dataObjectManagerImpl" class="org.apache.cloudstack.storage.datastore.DataObjectManagerImpl" />
<!--Data Store Helpers-->
<bean id="primaryDataStoreHelper" class="org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper" />
<bean id="imageStoreHelper" class="org.apache.cloudstack.storage.image.datastore.ImageStoreHelper" />
<bean id="imageFormatHelper" class="org.apache.cloudstack.storage.image.format.ImageFormatHelper" />
<bean id="storageCacheRandomAllocator" class="org.apache.cloudstack.storage.cache.allocator.StorageCacheRandomAllocator" />
<bean id="storageCacheManagerImpl" class="org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl" />
<bean id="StorageCacheReplacementAlgorithm" class="org.apache.cloudstack.storage.cache.manager.StorageCacheReplacementAlgorithmLRU" />
<bean id="snapshotStateMachineManagerImpl" class="org.apache.cloudstack.storage.snapshot.SnapshotStateMachineManagerImpl" />
<bean id="defaultEndPointSelector" class="org.apache.cloudstack.storage.endpoint.DefaultEndPointSelector" />
<bean id="ancientDataMotionStrategy" class="org.apache.cloudstack.storage.motion.AncientDataMotionStrategy" />
<bean id="xenserverStorageMotionStrategy" class="org.apache.cloudstack.storage.motion.XenServerStorageMotionStrategy" />
<!--Data Motion Services-->
<bean id="dataMotionServiceImpl" class="org.apache.cloudstack.storage.motion.DataMotionServiceImpl">
<property name="strategies">
<list>
<ref local="ancientDataMotionStrategy"/>
<ref local="xenserverStorageMotionStrategy"/>
</list>
</property>
</bean>
<!--
Data Store Provider Manager
-->
<bean id="primaryDataStoreProviderMgr"
class="org.apache.cloudstack.storage.datastore.manager.PrimaryDataStoreProviderManagerImpl"/>
<bean id="imageStoreProviderMgr" class="org.apache.cloudstack.storage.image.manager.ImageStoreProviderManagerImpl"/>
<bean id="dataStoreManagerImpl" class="org.apache.cloudstack.storage.datastore.DataStoreManagerImpl"
depends-on="dataStoreProviderManager">
<property name="primaryStoreMgr" ref="primaryDataStoreProviderMgr"/>
<property name="imageDataStoreMgr" ref="imageStoreProviderMgr"/>
</bean>
<bean id="cloudStackPrimaryDataStoreProviderImpl"
class="org.apache.cloudstack.storage.datastore.provider.CloudStackPrimaryDataStoreProviderImpl"/>
<bean id="dataStoreProviderManager"
class="org.apache.cloudstack.storage.datastore.provider.DataStoreProviderManagerImpl">
<property name="providers">
<list>
<!--Data Store Providers-->
<ref bean="cloudStackPrimaryDataStoreProviderImpl"/>
</list>
</property>
</bean>
<!--
Managers
-->
@ -682,10 +765,10 @@
<bean id="capacityManagerImpl" class="com.cloud.capacity.CapacityManagerImpl" />
<bean id="clusterFenceManagerImpl" class="com.cloud.cluster.ClusterFenceManagerImpl" />
<bean id="configurationManagerImpl" class="com.cloud.configuration.ConfigurationManagerImpl" />
<bean id="dataStoreProviderManagerImpl" class="org.apache.cloudstack.storage.datastore.provider.DataStoreProviderManagerImpl" />
<bean id="elasticLoadBalancerManagerImpl" class="com.cloud.network.lb.ElasticLoadBalancerManagerImpl" />
<bean id="entityManagerImpl" class="com.cloud.dao.EntityManagerImpl" />
<bean id="externalLoadBalancerUsageManagerImpl" class="com.cloud.network.ExternalLoadBalancerUsageManagerImpl" />
<bean id="externalDeviceUsageManagerImpl" class="com.cloud.network.ExternalDeviceUsageManagerImpl" />
<bean id="externalNetworkDeviceManagerImpl" class="com.cloud.network.ExternalNetworkDeviceManagerImpl" />
<bean id="firewallManagerImpl" class="com.cloud.network.firewall.FirewallManagerImpl" />
<bean id="hypervisorGuruManagerImpl" class="com.cloud.hypervisor.HypervisorGuruManagerImpl" />
@ -721,17 +804,14 @@
<bean id="vpcVirtualNetworkApplianceManagerImpl" class="com.cloud.network.router.VpcVirtualNetworkApplianceManagerImpl" />
<bean id="usageServerMonitor" class="com.cloud.usage.UsageServerMonitor" />
<!--
Misc components
-->
<bean id="actionEventUtils" class="com.cloud.event.ActionEventUtils" />
<bean id="agentMonitor" class="com.cloud.agent.manager.AgentMonitor" />
<bean id="alertGenerator" class="com.cloud.event.AlertGenerator" />
<bean id="ancientDataMotionStrategy" class="org.apache.cloudstack.storage.motion.AncientDataMotionStrategy" />
<bean id="storageCacheManagerImpl" class="org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl" />
<bean id="storageCacheRandomAllocator" class="org.apache.cloudstack.storage.cache.allocator.StorageCacheRandomAllocator" />
<bean id="xenserverSnapshotStrategy" class="org.apache.cloudstack.storage.snapshot.XenserverSnapshotStrategy" />
<bean id="xenserverStorageMotionStrategy" class="org.apache.cloudstack.storage.motion.XenServerStorageMotionStrategy" />
<bean id="apiDBUtils" class="com.cloud.api.ApiDBUtils" />
<bean id="apiDiscoveryServiceImpl" class="org.apache.cloudstack.discovery.ApiDiscoveryServiceImpl" />
<bean id="apiDispatcher" class="com.cloud.api.ApiDispatcher" />
@ -744,44 +824,22 @@
<bean id="consoleProxyServlet" class="com.cloud.servlet.ConsoleProxyServlet" />
<bean id="dataCenterResourceManagerImpl" class="org.apache.cloudstack.engine.datacenter.entity.DataCenterResourceManagerImpl" />
<bean id="dataDisk" class="org.apache.cloudstack.engine.subsystem.api.storage.type.DataDisk" />
<bean id="dataMotionServiceImpl" class="org.apache.cloudstack.storage.motion.DataMotionServiceImpl" />
<bean id="dataObjectManagerImpl" class="org.apache.cloudstack.storage.datastore.DataObjectManagerImpl" />
<bean id="dataStoreManagerImpl" class="org.apache.cloudstack.storage.datastore.DataStoreManagerImpl" />
<bean id="defaultEndPointSelector" class="org.apache.cloudstack.storage.endpoint.DefaultEndPointSelector" />
<bean id="primaryDataStoreProviderManagerImpl" class="org.apache.cloudstack.storage.datastore.manager.PrimaryDataStoreProviderManagerImpl" />
<bean id="imageStoreProviderManagerImpl" class="org.apache.cloudstack.storage.image.manager.ImageStoreProviderManagerImpl" />
<bean id="eventUtils" class="com.cloud.event.EventUtils" />
<bean id="iSCSI" class="org.apache.cloudstack.storage.datastore.type.ISCSI" />
<bean id="ISO" class="org.apache.cloudstack.storage.image.format.ISO" />
<bean id="templateDataFactoryImpl" class="org.apache.cloudstack.storage.image.TemplateDataFactoryImpl" />
<bean id="imageStoreHelper" class="org.apache.cloudstack.storage.image.datastore.ImageStoreHelper" />
<bean id="imageFormatHelper" class="org.apache.cloudstack.storage.image.format.ImageFormatHelper" />
<bean id="templateServiceImpl" class="org.apache.cloudstack.storage.image.TemplateServiceImpl" />
<bean id="iso" class="org.apache.cloudstack.engine.subsystem.api.storage.type.Iso" />
<bean id="networkFileSystem" class="org.apache.cloudstack.storage.datastore.type.NetworkFileSystem" />
<bean id="networkRestService" class="org.apache.cloudstack.engine.rest.service.api.NetworkRestService" />
<bean id="OVA" class="org.apache.cloudstack.storage.image.format.OVA" />
<bean id="objectInDataStoreManagerImpl" class="org.apache.cloudstack.storage.datastore.ObjectInDataStoreManagerImpl" />
<bean id="podRestService" class="org.apache.cloudstack.engine.rest.service.api.PodRestService" />
<bean id="primaryDataStoreHelper" class="org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper" />
<bean id="iso" class="org.apache.cloudstack.engine.subsystem.api.storage.type.Iso" />
<bean id="networkRestService" class="org.apache.cloudstack.engine.rest.service.api.NetworkRestService" />
<bean id="provisioningServiceImpl" class="org.apache.cloudstack.engine.service.api.ProvisioningServiceImpl" />
<bean id="QCOW2" class="org.apache.cloudstack.storage.image.format.QCOW2" />
<bean id="registerCompleteServlet" class="com.cloud.servlet.RegisterCompleteServlet" />
<bean id="rootDisk" class="org.apache.cloudstack.engine.subsystem.api.storage.type.RootDisk" />
<bean id="snapshotDataFactoryImpl" class="org.apache.cloudstack.storage.snapshot.SnapshotDataFactoryImpl" />
<bean id="snapshotServiceImpl" class="org.apache.cloudstack.storage.snapshot.SnapshotServiceImpl" />
<bean id="snapshotStateMachineManagerImpl" class="org.apache.cloudstack.storage.snapshot.SnapshotStateMachineManagerImpl" />
<bean id="registerCompleteServlet" class="com.cloud.servlet.RegisterCompleteServlet" />
<bean id="statsCollector" class="com.cloud.server.StatsCollector" />
<bean id="storagePoolAutomationImpl" class="com.cloud.storage.StoragePoolAutomationImpl" />
<bean id="unknown" class="org.apache.cloudstack.storage.image.format.Unknown" />
<bean id="usageEventUtils" class="com.cloud.event.UsageEventUtils" />
<bean id="VHD" class="org.apache.cloudstack.storage.image.format.VHD" />
<bean id="vMEntityManagerImpl" class="org.apache.cloudstack.engine.vm.VMEntityManagerImpl" />
<bean id="virtualMachineEntityImpl" class="org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntityImpl" />
<bean id="virtualMachineRestService" class="org.apache.cloudstack.engine.rest.service.api.VirtualMachineRestService" />
<bean id="volumeDataFactoryImpl" class="org.apache.cloudstack.storage.volume.VolumeDataFactoryImpl" />
<bean id="volumeRestService" class="org.apache.cloudstack.engine.rest.service.api.VolumeRestService" />
<bean id="volumeServiceImpl" class="org.apache.cloudstack.storage.volume.VolumeServiceImpl" />
<bean id="volumeTypeHelper" class="org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeTypeHelper" />
<bean id="zoneRestService" class="org.apache.cloudstack.engine.rest.service.api.ZoneRestService" />
<bean id="cloudZonesStartupProcessor" class="com.cloud.hypervisor.CloudZonesStartupProcessor" />
@ -791,19 +849,18 @@
<bean id="downloadMonitorImpl" class="com.cloud.storage.download.DownloadMonitorImpl" />
<bean id="lBHealthCheckManagerImpl" class="com.cloud.network.lb.LBHealthCheckManagerImpl" />
<bean id="mockAgentManagerImpl" class="com.cloud.agent.manager.MockAgentManagerImpl" />
<bean id="volumeManagerImpl" class="com.cloud.storage.VolumeManagerImpl" />
<bean id="ApplicationLoadBalancerService" class="org.apache.cloudstack.network.lb.ApplicationLoadBalancerManagerImpl" />
<bean id="InternalLoadBalancerVMManager" class="org.apache.cloudstack.network.lb.InternalLoadBalancerVMManagerImpl" />
<!--Simulator Components-->
<!--<bean id="simulatorImageStoreProvider" class="org.apache.cloudstack.storage.datastore.provider.SimulatorImageStoreProviderImpl" />-->
<bean id="mockStorageManagerImpl" class="com.cloud.agent.manager.MockStorageManagerImpl" />
<bean id="mockVmManagerImpl" class="com.cloud.agent.manager.MockVmManagerImpl" />
<bean id="mockNetworkManagerImpl" class="com.cloud.agent.manager.MockNetworkManagerImpl" />
<bean id="simulatorManagerImpl" class="com.cloud.agent.manager.SimulatorManagerImpl" />
<bean id="vMSnapshotManagerImpl" class="com.cloud.vm.snapshot.VMSnapshotManagerImpl" />
<bean id="volumeManagerImpl" class="com.cloud.storage.VolumeManagerImpl" />
<bean id="ClassicalPrimaryDataStoreProvider" class="org.apache.cloudstack.storage.datastore.provider.CloudStackPrimaryDataStoreProviderImpl" />
<bean id="cloudStackImageStoreProviderImpl" class="org.apache.cloudstack.storage.datastore.provider.CloudStackImageStoreProviderImpl" />
<bean id="s3ImageStoreProviderImpl" class="org.apache.cloudstack.storage.datastore.provider.S3ImageStoreProviderImpl" />
<bean id="swiftImageStoreProviderImpl" class="org.apache.cloudstack.storage.datastore.provider.SwiftImageStoreProviderImpl" />
<bean id="ApplicationLoadBalancerService" class="org.apache.cloudstack.network.lb.ApplicationLoadBalancerManagerImpl" />
<bean id="InternalLoadBalancerVMManager" class="org.apache.cloudstack.network.lb.InternalLoadBalancerVMManagerImpl" />
<bean id="StorageCacheReplacementAlgorithm" class="org.apache.cloudstack.storage.cache.manager.StorageCacheReplacementAlgorithmLRU" />
<bean id="VirtualMachinePowerStateSyncImpl" class="com.cloud.vm.VirtualMachinePowerStateSyncImpl" />
@ -876,6 +933,8 @@
<bean id="baremetalDhcpDaoImpl" class="com.cloud.baremetal.database.BaremetalDhcpDaoImpl" />
<bean id="baremetalPxeDaoImpl" class="com.cloud.baremetal.database.BaremetalPxeDaoImpl" />
<bean id="UcsManager" class="com.cloud.ucs.manager.UcsManagerImpl" />
<bean id="AffinityGroupServiceImpl" class="org.apache.cloudstack.affinity.AffinityGroupServiceImpl"/>
<bean id="DeploymentPlanningManager" class="com.cloud.deploy.DeploymentPlanningManagerImpl">
<property name="Planners" value="#{deploymentPlanners.Adapters}" />

View File

@ -606,6 +606,12 @@ addBaremetalPxeKickStartServer=1
addBaremetalPxePingServer=1
addBaremetalDhcp=1
#### UCS commands
addUcsManager=1
listUcsProfile=1
listUcsBlade=1
associatesUcsProfileToBlade=1
#### New Load Balancer commands
createLoadBalancer=15
listLoadBalancers=15

View File

@ -31,6 +31,8 @@
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<!--
@ -73,17 +75,21 @@
<!--
Stratosphere SSP support components
-->
<!--
<bean id="sspCredentialDaoImpl" class="com.cloud.network.dao.SspCredentialDaoImpl"/>
<bean id="sspTenantDaoImpl" class="com.cloud.network.dao.SspTenantDaoImpl"/>
<bean id="sspUuidDaoImpl" class="com.cloud.network.dao.SspUuidDaoImpl"/>
<bean id="SspGuestNetworkGuru" class="com.cloud.network.guru.SspGuestNetworkGuru">
<bean id="sspCredentialDaoImpl" class="org.apache.cloudstack.network.dao.SspCredentialDaoImpl"/>
<bean id="sspTenantDaoImpl" class="org.apache.cloudstack.network.dao.SspTenantDaoImpl"/>
<bean id="sspUuidDaoImpl" class="org.apache.cloudstack.network.dao.SspUuidDaoImpl"/>
<bean id="SspGuestNetworkGuru" class="org.apache.cloudstack.network.guru.SspGuestNetworkGuru">
<property name="name" value="SspGuestNetworkGuru"/>
</bean>
<bean id="StratosphereSsp" class="com.cloud.network.element.SspElement">
<bean id="StratosphereSsp" class="org.apache.cloudstack.network.element.SspElement">
<property name="name" value="StratosphereSsp"/>
</bean>
<!--
UCS support components
-->
<bean id="ucsBladeDaoImpl" class="com.cloud.ucs.database.UcsBladeDaoImpl" />
<bean id="ucsManagerDaoImpl" class="com.cloud.ucs.database.UcsManagerDaoImpl" />
<!--
@ -92,6 +98,28 @@
It determines whether or not a adapter is activated or how it is loaded in order in its managing provider,
-->
<bean id="cloudStackImageStoreProviderImpl"
class="org.apache.cloudstack.storage.datastore.provider.CloudStackImageStoreProviderImpl"/>
<bean id="s3ImageStoreProviderImpl"
class="org.apache.cloudstack.storage.datastore.provider.S3ImageStoreProviderImpl"/>
<bean id="swiftImageStoreProviderImpl"
class="org.apache.cloudstack.storage.datastore.provider.SwiftImageStoreProviderImpl"/>
<bean id="solidFireDataStoreProvider"
class="org.apache.cloudstack.storage.datastore.provider.SolidfirePrimaryDataStoreProvider"/>
<!--Storage Providers-->
<bean id="dataStoreProviderManager"
class="org.apache.cloudstack.storage.datastore.provider.DataStoreProviderManagerImpl">
<property name="providers">
<list merge="true">
<ref bean="cloudStackPrimaryDataStoreProviderImpl"/>
<ref local="cloudStackImageStoreProviderImpl"/>
<ref local="s3ImageStoreProviderImpl"/>
<ref local="swiftImageStoreProviderImpl"/>
<ref local="solidFireDataStoreProvider"/>
</list>
</property>
</bean>
<!-- Security adapters -->
<bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList">

View File

@ -80,7 +80,6 @@
<bean id="VmwareDatacenterDaoImpl" class="com.cloud.hypervisor.vmware.dao.VmwareDatacenterDaoImpl" />
<bean id="VmwareDatacenterZoneMapDaoImpl" class="com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDaoImpl" />
<bean id="LegacyZoneDaoImpl" class="com.cloud.hypervisor.vmware.dao.LegacyZoneDaoImpl" />
<bean id="vmwareStorageMotionStrategy" class="org.apache.cloudstack.storage.motion.VmwareStorageMotionStrategy"/>
<!--
Nicira support components
@ -170,6 +169,12 @@
</bean>
<!--
UCS support components
-->
<bean id="ucsBladeDaoImpl" class="com.cloud.ucs.database.UcsBladeDaoImpl" />
<bean id="ucsManagerDaoImpl" class="com.cloud.ucs.database.UcsManagerDaoImpl" />
<!--
Deployment configurations of various adapters
@ -178,6 +183,40 @@
-->
<!--Motion Strategies-->
<bean id="vmwareStorageMotionStrategy" class="org.apache.cloudstack.storage.motion.VmwareStorageMotionStrategy" />
<bean id="dataMotionServiceImpl" class="org.apache.cloudstack.storage.motion.DataMotionServiceImpl">
<property name="strategies">
<list>
<ref bean="ancientDataMotionStrategy"/>
<ref bean="xenserverStorageMotionStrategy"/>
<ref local="vmwareStorageMotionStrategy"/>
</list>
</property>
</bean>
<bean id="cloudStackImageStoreProviderImpl"
class="org.apache.cloudstack.storage.datastore.provider.CloudStackImageStoreProviderImpl"/>
<bean id="s3ImageStoreProviderImpl"
class="org.apache.cloudstack.storage.datastore.provider.S3ImageStoreProviderImpl"/>
<bean id="swiftImageStoreProviderImpl"
class="org.apache.cloudstack.storage.datastore.provider.SwiftImageStoreProviderImpl"/>
<bean id="solidFireDataStoreProvider"
class="org.apache.cloudstack.storage.datastore.provider.SolidfirePrimaryDataStoreProvider"/>
<!--Storage Providers-->
<bean id="dataStoreProviderManager"
class="org.apache.cloudstack.storage.datastore.provider.DataStoreProviderManagerImpl">
<property name="providers">
<list merge="true">
<ref bean="cloudStackPrimaryDataStoreProviderImpl"/>
<ref bean="cloudStackImageStoreProviderImpl"/>
<ref bean="s3ImageStoreProviderImpl"/>
<ref bean="solidFireDataStoreProvider"/>
</list>
</property>
</bean>
<!-- Security adapters -->
<bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList">
<property name="Adapters">

View File

@ -18,17 +18,8 @@
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!--
OSS deployment component configuration
@ -36,10 +27,6 @@
<bean id="databaseUpgradeChecker" class="com.cloud.upgrade.DatabaseUpgradeChecker"/>
<bean id="configurationDaoImpl" class="com.cloud.configuration.dao.ConfigurationDaoImpl"/>
<!-- simulator components -->
<bean id="SimulatorSecondaryDiscoverer" class="com.cloud.resource.SimulatorSecondaryDiscoverer">
<property name="name" value="SecondaryStorage"/>
</bean>
<bean id="SimulatorDiscoverer" class="com.cloud.resource.SimulatorDiscoverer">
<property name="name" value="Simulator Agent"/>
</bean>
@ -47,6 +34,23 @@
<property name="name" value="Simulator Guru"/>
</bean>
<bean id="SimulatorImageStoreProviderImpl"
class="org.apache.cloudstack.storage.datastore.provider.SimulatorImageStoreProviderImpl"/>
<!--Storage Providers-->
<!--<bean id="dataStoreProviderManagerChild" parent="dataStoreProviderManager">-->
<bean id="dataStoreProviderManager"
class="org.apache.cloudstack.storage.datastore.provider.DataStoreProviderManagerImpl">
<property name="providers">
<!--Override the cloudstack default image store provider to use simulator defined provider-->
<list>
<!--Data Store Providers-->
<ref bean="cloudStackPrimaryDataStoreProviderImpl"/>
<ref bean="SimulatorImageStoreProviderImpl"/>
</list>
</property>
</bean>
<!--
Managers & pluggable adapters configuration under OSS deployment
-->
@ -85,7 +89,6 @@
<property name="Adapters">
<list>
<ref bean="SimulatorDiscoverer"/>
<ref bean="SimulatorSecondaryDiscoverer"/>
<ref bean="XcpServerDiscoverer"/>
<ref bean="SecondaryStorageDiscoverer"/>
<ref bean="KvmServerDiscoverer"/>
@ -124,10 +127,6 @@
<ref bean="FirstFitPlanner"/>
<ref bean="UserDispersingPlanner"/>
<ref bean="UserConcentratedPodPlanner"/>
<!--
<ref bean="BareMetalPlanner" />
-->
</list>
</property>
</bean>
@ -175,9 +174,6 @@
<list>
<ref bean="VirtualRouter"/>
<ref bean="VpcVirtualRouter"/>
<!--
<ref bean="BareMetalDhcp"/>
-->
</list>
</property>
</bean>
@ -206,15 +202,16 @@
<ref bean="SecurityGroupProvider"/>
<ref bean="VpcVirtualRouter"/>
<ref bean="InternalLbVm"/>
<!--
<ref bean="BareMetalDhcp"/>
<ref bean="BareMetalPxe"/>
<ref bean="BareMetalUserdata"/>
-->
</list>
</property>
</bean>
<!--
UCS support components
-->
<bean id="ucsBladeDaoImpl" class="com.cloud.ucs.database.UcsBladeDaoImpl"/>
<bean id="ucsManagerDaoImpl" class="com.cloud.ucs.database.UcsManagerDaoImpl"/>
<bean id="GlobalLoadBalancingRulesServiceImpl"
class="org.apache.cloudstack.region.gslb.GlobalLoadBalancingRulesServiceImpl"/>
@ -239,5 +236,4 @@
<property name="name" value="ExplicitDedicationProcessor"/>
<property name="type" value="ExplicitDedication"/>
</bean>
</beans>

View File

@ -19,35 +19,33 @@ package com.cloud.agent.api;
public class AttachVolumeAnswer extends Answer {
private Long deviceId;
private String vdiUuid;
private String chainInfo;
protected AttachVolumeAnswer() {
}
public AttachVolumeAnswer(AttachVolumeCommand cmd, String result) {
super(cmd, false, result);
this.deviceId = null;
}
public AttachVolumeAnswer(AttachVolumeCommand cmd, Long deviceId) {
public AttachVolumeAnswer(AttachVolumeCommand cmd, Long deviceId, String vdiUuid) {
super(cmd);
this.deviceId = deviceId;
this.vdiUuid = vdiUuid;
}
public AttachVolumeAnswer(AttachVolumeCommand cmd) {
super(cmd);
this.deviceId = null;
}
/**
* @return the deviceId
*/
public Long getDeviceId() {
return deviceId;
}
public String getVdiUuid() {
return vdiUuid;
}
public void setChainInfo(String chainInfo) {
this.chainInfo = chainInfo;
}

View File

@ -19,29 +19,37 @@ package com.cloud.agent.api;
import com.cloud.storage.Storage.StoragePoolType;
public class AttachVolumeCommand extends Command {
boolean attach;
String vmName;
StoragePoolType pooltype;
String poolUuid;
String volumeFolder;
String volumePath;
String volumeName;
Long deviceId;
String chainInfo;
Long bytesReadRate;
Long bytesWriteRate;
Long iopsReadRate;
Long iopsWriteRate;
private boolean attach;
private boolean _managed;
private String vmName;
private StoragePoolType pooltype;
private String volumePath;
private String volumeName;
private Long deviceId;
private String chainInfo;
private String poolUuid;
private String _storageHost;
private int _storagePort;
private String _iScsiName;
private String _chapInitiatorUsername;
private String _chapInitiatorPassword;
private String _chapTargetUsername;
private String _chapTargetPassword;
private Long bytesReadRate;
private Long bytesWriteRate;
private Long iopsReadRate;
private Long iopsWriteRate;
protected AttachVolumeCommand() {
}
public AttachVolumeCommand(boolean attach, String vmName, StoragePoolType pooltype, String volumeFolder, String volumePath, String volumeName, Long deviceId, String chainInfo) {
public AttachVolumeCommand(boolean attach, boolean managed, String vmName,
StoragePoolType pooltype, String volumePath, String volumeName,
Long deviceId, String chainInfo) {
this.attach = attach;
this._managed = managed;
this.vmName = vmName;
this.pooltype = pooltype;
this.volumeFolder = volumeFolder;
this.volumePath = volumePath;
this.volumeName = volumeName;
this.deviceId = deviceId;
@ -54,7 +62,7 @@ public class AttachVolumeCommand extends Command {
}
public boolean getAttach() {
return attach;
return attach;
}
public String getVmName() {
@ -69,16 +77,12 @@ public class AttachVolumeCommand extends Command {
this.pooltype = pooltype;
}
public String getVolumeFolder() {
return volumeFolder;
}
public String getVolumePath() {
return volumePath;
}
public String getVolumeName() {
return volumeName;
return volumeName;
}
public Long getDeviceId() {
@ -90,17 +94,77 @@ public class AttachVolumeCommand extends Command {
}
public String getPoolUuid() {
return poolUuid;
return poolUuid;
}
public void setPoolUuid(String poolUuid) {
this.poolUuid = poolUuid;
this.poolUuid = poolUuid;
}
public String getChainInfo() {
return chainInfo;
return chainInfo;
}
public void setStorageHost(String storageHost) {
_storageHost = storageHost;
}
public String getStorageHost() {
return _storageHost;
}
public void setStoragePort(int storagePort) {
_storagePort = storagePort;
}
public int getStoragePort() {
return _storagePort;
}
public boolean isManaged() {
return _managed;
}
public void set_iScsiName(String iScsiName) {
this._iScsiName = iScsiName;
}
public String get_iScsiName() {
return _iScsiName;
}
public void setChapInitiatorUsername(String chapInitiatorUsername) {
_chapInitiatorUsername = chapInitiatorUsername;
}
public String getChapInitiatorUsername() {
return _chapInitiatorUsername;
}
public void setChapInitiatorPassword(String chapInitiatorPassword) {
_chapInitiatorPassword = chapInitiatorPassword;
}
public String getChapInitiatorPassword() {
return _chapInitiatorPassword;
}
public void setChapTargetUsername(String chapTargetUsername) {
_chapTargetUsername = chapTargetUsername;
}
public String getChapTargetUsername() {
return _chapTargetUsername;
}
public void setChapTargetPassword(String chapTargetPassword) {
_chapTargetPassword = chapTargetPassword;
}
public String getChapTargetPassword() {
return _chapTargetPassword;
}
public void setBytesReadRate(Long bytesReadRate) {
this.bytesReadRate = bytesReadRate;
}

View File

@ -1,979 +0,0 @@
// 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.hyperv.resource;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.IAgentControl;
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.Command;
import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
import com.cloud.agent.api.DeleteStoragePoolCommand;
import com.cloud.agent.api.GetHostStatsAnswer;
import com.cloud.agent.api.GetHostStatsCommand;
import com.cloud.agent.api.GetStorageStatsAnswer;
import com.cloud.agent.api.GetStorageStatsCommand;
import com.cloud.agent.api.GetVmStatsCommand;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.HostStatsEntry;
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.ModifyStoragePoolAnswer;
import com.cloud.agent.api.ModifyStoragePoolCommand;
import com.cloud.agent.api.NetworkUsageCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PingTestCommand;
import com.cloud.agent.api.PoolEjectCommand;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.RebootRouterCommand;
import com.cloud.agent.api.SetupCommand;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.ValidateSnapshotCommand;
import com.cloud.agent.api.check.CheckSshAnswer;
import com.cloud.agent.api.check.CheckSshCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.api.routing.VpnUsersCfgCommand;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.CreateAnswer;
import com.cloud.agent.api.storage.CreateCommand;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.host.Host.Type;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.utils.ssh.SshHelper;
import com.cloud.resource.ServerResource;
import com.cloud.resource.ServerResourceBase;
import com.cloud.serializer.GsonHelper;
import com.cloud.storage.Volume;
import com.cloud.storage.template.TemplateProp;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.VirtualMachine.PowerState;
import com.cloud.vm.VirtualMachine.State;
import com.google.gson.Gson;
/**
* Implementation of resource base class for Hyper-V hypervisor
**/
@Local(value={ServerResource.class})
public class HypervResource extends ServerResourceBase implements ServerResource{
private String _dcId;
private String _podId;
private String _clusterId;
private String _guid;
private String _name;
private static final Logger s_logger = Logger.getLogger(HypervResource.class);
private IAgentControl agentControl;
private volatile Boolean _wakeUp = false;
protected Gson _gson;
protected HashMap<String, State> _vms = new HashMap<String, State>(512);
protected final int DEFAULT_DOMR_SSHPORT = 3922;
public HypervResource()
{
_gson = GsonHelper.getGsonLogger();
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof CreateCommand) {
return execute((CreateCommand) cmd);
} else if (cmd instanceof SetPortForwardingRulesCommand) {
s_logger.info("SCVMM agent recived command SetPortForwardingRulesCommand");
//return execute((SetPortForwardingRulesCommand) cmd);
} else if (cmd instanceof SetStaticNatRulesCommand) {
s_logger.info("SCVMM agent recived command SetStaticNatRulesCommand");
//return execute((SetStaticNatRulesCommand) cmd);
}else if (cmd instanceof LoadBalancerConfigCommand) {
s_logger.info("SCVMM agent recived command SetStaticNatRulesCommand");
//return execute((LoadBalancerConfigCommand) cmd);
} else if (cmd instanceof IpAssocCommand) {
s_logger.info("SCVMM agent recived command IPAssocCommand");
//return execute((IPAssocCommand) cmd);
} else if (cmd instanceof SavePasswordCommand) {
s_logger.info("SCVMM agent recived command SavePasswordCommand");
//return execute((SavePasswordCommand) cmd);
} else if (cmd instanceof DhcpEntryCommand) {
return execute((DhcpEntryCommand) cmd);
} else if (cmd instanceof VmDataCommand) {
//return execute((VmDataCommand) cmd);
} else if (cmd instanceof ReadyCommand) {
s_logger.info("SCVMM agent recived ReadyCommand: " + _gson.toJson(cmd));
return new ReadyAnswer((ReadyCommand) cmd);
} else if (cmd instanceof GetHostStatsCommand) {
return execute((GetHostStatsCommand) cmd);
} else if (cmd instanceof GetVmStatsCommand) {
s_logger.info("SCVMM agent recived command GetVmStatsCommand");
//return execute((GetVmStatsCommand) cmd);
} else if (cmd instanceof CheckHealthCommand) {
//return execute((CheckHealthCommand) cmd);
} else if (cmd instanceof StopCommand) {
//return execute((StopCommand) cmd);
} else if (cmd instanceof RebootRouterCommand) {
//return execute((RebootRouterCommand) cmd);
} else if (cmd instanceof RebootCommand) {
//return execute((RebootCommand) cmd);
} else if (cmd instanceof CheckVirtualMachineCommand) {
s_logger.info("SCVMM agent recived command CheckVirtualMachineCommand");
//return execute((CheckVirtualMachineCommand) cmd);
} else if (cmd instanceof PrepareForMigrationCommand) {
//return execute((PrepareForMigrationCommand) cmd);
} else if (cmd instanceof MigrateCommand) {
//return execute((MigrateCommand) cmd);
} else if (cmd instanceof DestroyCommand) {
//return execute((DestroyCommand) cmd);
} else if (cmd instanceof ModifyStoragePoolCommand) {
return execute((ModifyStoragePoolCommand) cmd);
} else if (cmd instanceof DeleteStoragePoolCommand) {
s_logger.info("SCVMM agent recived command DeleteStoragePoolCommand");
Answer answer = new Answer(cmd, true, "success");
return answer;
//return execute((DeleteStoragePoolCommand) cmd);
} else if (cmd instanceof CopyVolumeCommand) {
s_logger.info("SCVMM agent recived command CopyVolumeCommand");
//return execute((CopyVolumeCommand) cmd);
} else if (cmd instanceof AttachVolumeCommand) {
s_logger.info("SCVMM agent recived command AttachVolumeCommand");
//return execute((AttachVolumeCommand) cmd);
} else if (cmd instanceof AttachIsoCommand) {
//return execute((AttachIsoCommand) cmd);
} else if (cmd instanceof ValidateSnapshotCommand) {
//return execute((ValidateSnapshotCommand) cmd);
} else if (cmd instanceof ManageSnapshotCommand) {
//return execute((ManageSnapshotCommand) cmd);
} else if (cmd instanceof BackupSnapshotCommand) {
//return execute((BackupSnapshotCommand) cmd);
} else if (cmd instanceof CreateVolumeFromSnapshotCommand) {
//return execute((CreateVolumeFromSnapshotCommand) cmd);
} else if (cmd instanceof CreatePrivateTemplateFromVolumeCommand) {
//return execute((CreatePrivateTemplateFromVolumeCommand) cmd);
} else if (cmd instanceof CreatePrivateTemplateFromSnapshotCommand) {
//return execute((CreatePrivateTemplateFromSnapshotCommand) cmd);
} else if (cmd instanceof GetStorageStatsCommand) {
return execute((GetStorageStatsCommand) cmd);
} else if (cmd instanceof PrimaryStorageDownloadCommand) {
s_logger.info("SCVMM agent recived command PrimaryStorageDownloadCommand");
return execute((PrimaryStorageDownloadCommand) cmd);
} else if (cmd instanceof GetVncPortCommand) {
//return execute((GetVncPortCommand) cmd);
} else if (cmd instanceof SetupCommand) {
//return execute((SetupCommand) cmd);
} else if (cmd instanceof MaintainCommand) {
//return execute((MaintainCommand) cmd);
} else if (cmd instanceof PingTestCommand) {
s_logger.info("SCVMM agent recived command PingTestCommand");
//return execute((PingTestCommand) cmd);
} else if (cmd instanceof CheckOnHostCommand) {
s_logger.info("SCVMM agent recived command CheckOnHostCommand");
//return execute((CheckOnHostCommand) cmd);
} else if (cmd instanceof ModifySshKeysCommand) {
//return execute((ModifySshKeysCommand) cmd);
} else if (cmd instanceof PoolEjectCommand) {
//return execute((PoolEjectCommand) cmd);
} else if (cmd instanceof NetworkUsageCommand) {
//return execute((NetworkUsageCommand) cmd);
} else if (cmd instanceof StartCommand) {
return execute((StartCommand) cmd);
} else if (cmd instanceof RemoteAccessVpnCfgCommand) {
//return execute((RemoteAccessVpnCfgCommand) cmd);
} else if (cmd instanceof VpnUsersCfgCommand) {
//return execute((VpnUsersCfgCommand) cmd);
} else if (cmd instanceof CheckSshCommand) {
return execute((CheckSshCommand)cmd);
} else if (cmd instanceof CheckNetworkCommand) {
//return execute((CheckNetworkCommand) cmd);
} else {
s_logger.info("SCVMM agent recived unimplemented command: " + _gson.toJson(cmd));
return Answer.createUnsupportedCommandAnswer(cmd);
}
return Answer.createUnsupportedCommandAnswer(cmd);
}
public PrimaryStorageDownloadAnswer execute(PrimaryStorageDownloadCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource PrimaryStorageDownloadCommand: " + _gson.toJson(cmd));
}
try {
String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
String primaryStroageUrl = cmd.getPrimaryStorageUrl();
String templateUuidName =null;
assert ((primaryStroageUrl != null) && (secondaryStorageUrl != null));
// FIXME: paths and system vm name are hard coded
String templateUrl = cmd.getUrl();
String templatePath = templateUrl.replace('/', '\\');
templatePath = templatePath.substring(4);
if (!templatePath.endsWith(".vhd")) {
String templateName = cmd.getName();
templateUuidName = UUID.nameUUIDFromBytes((templateName + "@" + cmd.getPoolUuid()).getBytes()).toString();
if (!templatePath.endsWith("\\")) {
templatePath = templatePath + "\\";
}
//templatePath = templatePath + templateUuidName + ".vhd";
templatePath = templatePath + "systemvm.vhd";
}
s_logger.info("template URL: "+ templateUrl + "template name: "+ cmd.getName() + " sec storage " + secondaryStorageUrl+ " pri storage" + primaryStroageUrl);
StringBuilder cmdStr = new StringBuilder("cmd /c powershell.exe ");
cmdStr.append("copy-item '");
cmdStr.append(templatePath.toCharArray());
cmdStr.append("' 'C:\\programdata\\Virtual Machine Manager Library Files\\VHDs\\';");
s_logger.info("Running command: " + cmdStr);
Process p = Runtime.getRuntime().exec(cmdStr.toString());
p.getOutputStream().close();
InputStreamReader temperrReader = new InputStreamReader(new BufferedInputStream(p.getErrorStream()));
BufferedReader errreader = new BufferedReader(temperrReader);
if (errreader.ready()) {
String errorOutput = new String("");
s_logger.info("errors found while running cmdlet: " + cmdStr.toString());
while (true){
String errline = errreader.readLine();
if (errline == null) {
break;
}
errorOutput = errorOutput + errline;
}
s_logger.info(errorOutput);
}
p.getErrorStream().close();
InputStreamReader tempReader = new InputStreamReader(new BufferedInputStream(p.getInputStream()));
BufferedReader reader = new BufferedReader(tempReader);
String output = new String("");
while (true){
String line = reader.readLine();
if (line == null) {
break;
}
output = output + line;
}
p.getInputStream().close();
s_logger.info("Command output: "+ output);
if (output.contains("FullyQualifiedErrorId") || output.contains("Error") || output.contains("Exception")) {
return new PrimaryStorageDownloadAnswer("Failed to copy template to SCVMM library share from secondary storage.");
}
return new PrimaryStorageDownloadAnswer(templateUuidName, 0);
} catch (Exception e)
{
s_logger.info("Exception caught: "+e.getMessage());
return new PrimaryStorageDownloadAnswer("Failed to copy template to SCVMM library share from secondary storage.");
}
}
protected Answer execute(CreateCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource CreateCommand: " + _gson.toJson(cmd));
}
try {
long volId = cmd.getVolumeId();
String templateUrl = cmd.getTemplateUrl();;
StorageFilerTO pool = cmd.getPool();
DiskProfile diskchar = cmd.getDiskCharacteristics();
if (diskchar.getType() == Volume.Type.ROOT) {
if (cmd.getTemplateUrl() == null) {
//create root volume
VolumeTO vol = new VolumeTO(cmd.getVolumeId(),
diskchar.getType(),
pool.getType(), pool.getUuid(), cmd.getDiskCharacteristics().getName(),
pool.getPath(), cmd.getDiskCharacteristics().getName(), cmd.getDiskCharacteristics().getSize(),
null);
return new CreateAnswer(cmd, vol);
} else {
VolumeTO vol = new VolumeTO(cmd.getVolumeId(),
diskchar.getType(),
pool.getType(), pool.getUuid(), cmd.getDiskCharacteristics().getName(),
pool.getPath(), cmd.getDiskCharacteristics().getName(), cmd.getDiskCharacteristics().getSize(), null);
return new CreateAnswer(cmd, vol);
}
} else {
//create data volume
String volumeUuid = "cloud.worker." + UUID.randomUUID().toString();
VolumeTO vol = new VolumeTO(cmd.getVolumeId(),
diskchar.getType(),
pool.getType(), pool.getUuid(), cmd.getDiskCharacteristics().getName(),
pool.getPath(), volumeUuid, cmd.getDiskCharacteristics().getSize(), null);
return new CreateAnswer(cmd, vol);
}
} catch (Exception ex) {
return null;
}
}
protected StartAnswer execute(StartCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource StartCommand: " + _gson.toJson(cmd));
}
VirtualMachineTO vmSpec = cmd.getVirtualMachine();
String vmName = vmSpec.getName();
State state = State.Stopped;
String scriptFileName = vmName+ ".ps1";
String newLine = System.getProperty("line.separator");
String bootArgsDiskName = vmName+"-bootparams.vhd";
String bootArgsDiskPath = "C:\\ProgramData\\Virtual Machine Manager Library Files\\VHDs\\"+bootArgsDiskName;
try {
// mark VM as starting state so that sync() can know not to report stopped too early
synchronized (_vms) {
_vms.put(vmName, State.Starting);
{
// create and attach boot parameter disk
String diskpartScriptName = vmName+"-Diskpart.txt";
StringBuilder cmdDiskpart = new StringBuilder("create vdisk file=\"");cmdDiskpart.append(bootArgsDiskPath.toCharArray());cmdDiskpart.append("\" maximum=10 type=expandable" + newLine);
cmdDiskpart.append("select vdisk file=\"");cmdDiskpart.append(bootArgsDiskPath.toCharArray());cmdDiskpart.append("\"" + newLine);
cmdDiskpart.append("attach vdisk" + newLine);
cmdDiskpart.append("create partition primary" + newLine);
cmdDiskpart.append("format fs=ntfs label=\"test vhd\" quick" + newLine);
cmdDiskpart.append("assign letter="+vmName.toCharArray()[0]+ newLine);
cmdDiskpart.append("attach vdisk" + newLine);
File f=new File(diskpartScriptName);
FileOutputStream fop=new FileOutputStream(f);
fop.write(cmdDiskpart.toString().getBytes());
fop.flush();
fop.close();
s_logger.info("Running diskpart attach command");
Process p = Runtime.getRuntime().exec("cmd.exe /c diskpart.exe /s "+diskpartScriptName);
p.getOutputStream().close();
InputStreamReader temperrReader = new InputStreamReader(new BufferedInputStream(p.getErrorStream()));
BufferedReader errreader = new BufferedReader(temperrReader);
if (errreader.ready()) {
String errorOutput = new String("");
while (true){
String errline = errreader.readLine();
if (errline == null) {
break;
}
errorOutput = errorOutput + errline;
}
s_logger.info("errors found while running diskpart command: " + errorOutput);
}
p.getErrorStream().close();
InputStreamReader tempReader = new InputStreamReader(new BufferedInputStream(p.getInputStream()));
BufferedReader reader = new BufferedReader(tempReader);
String output = new String("");
while (true){
String line = reader.readLine();
if (line == null) {
break;
}
output = output + line;
}
p.getInputStream().close();
s_logger.info("diskpart detahc command output: "+ output);
}
// wait for a while so that disk formatting is done
Thread.sleep(60000);
//create boot args on the disk
String bootArgs = vmSpec.getBootArgs();
String Drive = vmName.substring(0,1);
File fBootargs =new File(Drive+":\\cmdline");
FileOutputStream fopBoot=new FileOutputStream(fBootargs);
fopBoot.write(bootArgs.toString().getBytes());
fopBoot.flush();
fopBoot.close();
//detach the boot parameter disk
{
String diskpartDetachScriptName = vmName+"-Detach-Diskpart.txt";
StringBuilder cmdDetachDiskpart = new StringBuilder("select vdisk file=\"");
cmdDetachDiskpart.append(bootArgsDiskPath.toCharArray());cmdDetachDiskpart.append("\"" + newLine);
cmdDetachDiskpart.append("detach vdisk" + newLine);
File fd=new File(diskpartDetachScriptName);
FileOutputStream fdop=new FileOutputStream(fd);
fdop.write(cmdDetachDiskpart.toString().getBytes());
fdop.flush();
fdop.close();
s_logger.info("Running diskpart detach command");
Process pd = Runtime.getRuntime().exec("cmd.exe /c diskpart.exe /s "+diskpartDetachScriptName);
pd.getOutputStream().close();
InputStreamReader temperrReader1 = new InputStreamReader(new BufferedInputStream(pd.getErrorStream()));
BufferedReader errreader1 = new BufferedReader(temperrReader1);
if (errreader1.ready()) {
String errorOutput = new String("");
while (true){
String errline = errreader1.readLine();
if (errline == null) {
break;
}
errorOutput = errorOutput + errline;
}
s_logger.info("errors found while running diskpart detach command: " + errorOutput);
}
pd.getErrorStream().close();
InputStreamReader tempReader1 = new InputStreamReader(new BufferedInputStream(pd.getInputStream()));
BufferedReader reader1 = new BufferedReader(tempReader1);
String output1 = new String("");
while (true){
String line = reader1.readLine();
if (line == null) {
break;
}
output1 = output1 + line;
}
pd.getInputStream().close();
s_logger.info("diskpart detach command output: "+ output1);
}
}
UUID id = UUID.randomUUID();
String hwProfileId = id.toString();
StringBuilder cmdStr = new StringBuilder("Add-PSSnapin Microsoft.SystemCenter.VirtualMachineManager;" + newLine);
cmdStr.append("Get-VMMServer -ComputerName localhost;" + newLine);
cmdStr.append("$JobGroupId = [Guid]::NewGuid().ToString();" + newLine);
cmdStr.append("$hwProfileId = [Guid]::NewGuid().ToString(); " + newLine);
cmdStr.append("$CPUType = Get-CPUType -VMMServer localhost | where {$_.Name -eq " + "'1.20 GHz Athlon MP'}; " + newLine);
cmdStr.append("$ISO = Get-ISO -VMMServer localhost | where { $_.Name -match \"systemvm\" }; " + newLine);
cmdStr.append("$VMHost = Get-VMHost -VMMServer localhost | where {$_.Name -eq \"HYPERVHOST.hypervdc.intranet.lab.vmops.com\"}; " + newLine);
cmdStr.append("$VNetwork = Get-VirtualNetwork -VMHost $VMHost -Name \"public\"; " + newLine);
cmdStr.append("New-VirtualNetworkAdapter -VMMServer localhost -JobGroup $JobGroupID -PhysicalAddressType Dynamic -VirtualNetwork $vnetwork; " + newLine);
cmdStr.append("New-VirtualNetworkAdapter -VMMServer localhost -JobGroup $JobGroupID -PhysicalAddressType Dynamic -VirtualNetwork $vnetwork; " + newLine);
cmdStr.append("New-VirtualNetworkAdapter -VMMServer localhost -JobGroup $JobGroupID -PhysicalAddressType Dynamic -VirtualNetwork $vnetwork; " + newLine);
cmdStr.append("New-VirtualDVDDrive -VMMServer localhost -JobGroup $JobGroupID -Bus 1 -LUN 0 -ISO $ISO ; " + newLine);
cmdStr.append("New-HardwareProfile -VMMServer localhost -JobGroup $JobGroupID -Owner \"HYPERVDC\\Administrator\" -CPUType $CPUType -Name $hwProfileId");
cmdStr.append(" -Description \"Profile used to create a VM/Template\"" +
" -CPUCount 1 -MemoryMB 512 -RelativeWeight 100 -HighlyAvailable $true -NumLock $false -BootOrder \"CD\", " +
"\"IdeHardDrive\", \"PxeBoot\", \"Floppy\" -LimitCPUFunctionality $false -LimitCPUForMigration $false; " + newLine);
cmdStr.append("$JobGroupId = [Guid]::NewGuid().ToString(); " + newLine);
//refresh library share
cmdStr.append("$share = Get-LibraryShare;"+newLine);
cmdStr.append("Refresh-LibraryShare -LibraryShare $share;"+newLine);
// create root disk
cmdStr.append("$VirtualHardDisk1 = Get-VirtualHardDisk -VMMServer localhost | where {$_.Location -eq \"\\\\scvmm.hypervdc.intranet.lab.vmops.com\\MSSCVMMLibrary\\VHDs\\systemvm.vhd\"} | where {$_.HostName -eq \"scvmm.hypervdc.intranet.lab.vmops.com\"}" + newLine);
cmdStr.append("New-VirtualDiskDrive -VMMServer localhost -JobGroup $JobGroupID -IDE -Bus 0 -LUN 0 -VirtualHardDisk $VirtualHardDisk1 -Filename \"");
cmdStr.append(vmName.toCharArray());
cmdStr.append("-systemvm.vhd\"; " + newLine);
// create boot param data disk
cmdStr.append("$VirtualHardDisk2 = Get-VirtualHardDisk -VMMServer localhost " +
" | where {$_.Location -eq \"\\\\scvmm.hypervdc.intranet.lab.vmops.com\\MSSCVMMLibrary\\VHDs\\");
cmdStr.append(bootArgsDiskName.toCharArray());
cmdStr.append("\" } | where {$_.HostName -eq \"scvmm.hypervdc.intranet.lab.vmops.com\"}" + newLine);
cmdStr.append("New-VirtualDiskDrive -VMMServer localhost -JobGroup $JobGroupID -IDE -Bus 0 -LUN 1 -VirtualHardDisk $VirtualHardDisk2 -Filename \"");
cmdStr.append(bootArgsDiskName.toCharArray());
cmdStr.append("\";"+newLine);
cmdStr.append("$HardwareProfile = Get-HardwareProfile -VMMServer localhost | where {$_.Name -eq $hwProfileId};" + newLine);
cmdStr.append("$OperatingSystem = Get-OperatingSystem -VMMServer localhost | where {$_.Name -eq 'Other Linux (32 bit)'};" + newLine);
cmdStr.append("New-VM -VMMServer localhost -Name \"");
cmdStr.append(vmName.toCharArray());
cmdStr.append("\" -Description \"\" -Owner \"HYPERVDC\\Administrator\" -VMHost $VMHost -Path \"C:\\ClusterStorage\\Volume1\" -HardwareProfile $HardwareProfile " +
" -JobGroup $JobGroupID" +
" -OperatingSystem $OperatingSystem -RunAsSystem -StartVM -StartAction NeverAutoTurnOnVM -StopAction SaveVM;" + newLine);
File f=new File(scriptFileName);
FileOutputStream fop=new FileOutputStream(f);
fop.write(cmdStr.toString().getBytes());
fop.flush();
fop.close();
s_logger.info("Running command: " + cmdStr);
Process p = Runtime.getRuntime().exec("cmd.exe /c Powershell -Command \" & '.\\" + scriptFileName +"'\"");
p.getOutputStream().close();
InputStreamReader temperrReader = new InputStreamReader(new BufferedInputStream(p.getErrorStream()));
BufferedReader errreader = new BufferedReader(temperrReader);
if (errreader.ready()) {
String errorOutput = new String("");
while (true){
String errline = errreader.readLine();
if (errline == null) {
break;
}
errorOutput = errorOutput + errline;
}
s_logger.info("errors found while running cmdlet to create VM: " + errorOutput);
}
p.getErrorStream().close();
InputStreamReader tempReader = new InputStreamReader(new BufferedInputStream(p.getInputStream()));
BufferedReader reader = new BufferedReader(tempReader);
String output = new String("");
while (true){
String line = reader.readLine();
if (line == null) {
break;
}
output = output + line;
}
p.getInputStream().close();
s_logger.info("vm create cmmdlet output: "+ output);
if (output.contains("FullyQualifiedErrorId") || output.contains("Error") || output.contains("Exception")) {
s_logger.info("No errors found in running cmdlet "+ cmdStr.toString());
return new StartAnswer(cmd, "Failed to start VM");
}
state = State.Running;
return new StartAnswer(cmd);
} catch (Exception e){
return new StartAnswer(cmd, "Failed to start VM");
} finally {
//delete the PS script file
//File f=new File(".\\"+scriptFileName);
//f.delete();
synchronized (_vms) {
if (state != State.Stopped) {
_vms.put(vmName, state);
} else {
_vms.remove(vmName);
}
}
}
}
protected Answer execute(DhcpEntryCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource DhcpEntryCommand: " + _gson.toJson(cmd));
}
String args = " " + cmd.getVmMac();
args += " " + cmd.getVmIpAddress();
args += " " + cmd.getVmName();
if (s_logger.isDebugEnabled()) {
s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /root/edithosts.sh " + args);
}
try {
Pair<Boolean, String> result = SshHelper.sshExecute(cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP), DEFAULT_DOMR_SSHPORT, "root",
new File("id_rsa.cloud"), null, "/root/edithosts.sh " + args);
if (!result.first()) {
s_logger.error("dhcp_entry command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP)
+ " failed, message: " + result.second());
return new Answer(cmd, false, "DhcpEntry failed due to " + result.second());
}
if (s_logger.isInfoEnabled()) {
s_logger.info("dhcp_entry command on domain router " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + " completed");
}
} catch (Throwable e) {
s_logger.error("Unexpected exception ", e);
return new Answer(cmd, false, "DhcpEntry failed due to exception");
}
return new Answer(cmd);
}
protected CheckSshAnswer execute(CheckSshCommand cmd) {
String vmName = cmd.getName();
String privateIp = cmd.getIp();
int cmdPort = cmd.getPort();
if (s_logger.isInfoEnabled()) {
s_logger.info("Ping VM:" + cmd.getName() + " IP:" + privateIp + " port:" + cmdPort);
}
return new CheckSshAnswer(cmd);
}
@Override
public void setAgentControl(IAgentControl agentControl) {
this.agentControl = agentControl;
}
@Override
public Type getType() {
// TODO Auto-generated method stub
return null;
}
@Override
public StartupCommand[] initialize() {
s_logger.info("recieved initialize request for cluster:" + _clusterId);
List<String> vmHostList = getHostsInCluster(_clusterId);
if (vmHostList.size() == 0) {
s_logger.info("cluster is not recognized or zero instances in the cluster");
}
StartupCommand[] answerCmds = new StartupCommand[vmHostList.size()];
int index =0;
for (String hostName: vmHostList) {
s_logger.info("Node :" + hostName);
StartupRoutingCommand cmd = new StartupRoutingCommand();
answerCmds[index] = cmd;
fillHostInfo(cmd,hostName);
index++;
}
s_logger.info("response sent to initialize request for cluster:" + _clusterId);
return answerCmds;
}
protected void fillHostInfo(StartupRoutingCommand cmd, String hostName) {
Map<String, String> details = cmd.getHostDetails();
if (details == null) {
details = new HashMap<String, String>();
}
try {
fillHostHardwareInfo(cmd);
fillHostNetworkInfo(cmd);
fillHostDetailsInfo(details);
} catch (Exception e) {
s_logger.error("Exception while retrieving host info ", e);
throw new CloudRuntimeException("Exception while retrieving host info");
}
cmd.setName(hostName);
cmd.setHostDetails(details);
cmd.setGuid(_guid);
cmd.setDataCenter(_dcId);
cmd.setPod(_podId);
cmd.setCluster(_clusterId);
cmd.setHypervisorType(HypervisorType.Hyperv);
}
private void fillHostDetailsInfo(Map<String, String> details) throws Exception {
}
private Answer execute(GetHostStatsCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource GetHostStatsCommand: " + _gson.toJson(cmd));
}
try {
// FIXME: get the actual host stats by running powershell cmdlet. This is just for prototype.
HostStatsEntry hostStats = new HostStatsEntry(cmd.getHostId(), 0, 10000, 10000,
"host", 2*1024*1024, 1*1024*1024, 1*1024*1024, 0);
s_logger.info("returning stats :" + 2*1024*1024 + " " + 1*1024*1024 + " " + 1*1024*1024);
return new GetHostStatsAnswer(cmd, hostStats);
} catch (Exception e) {
HostStatsEntry hostStats = new HostStatsEntry(cmd.getHostId(), 0, 0, 0,
"host", 0, 0, 0, 0);
String msg = "Unable to execute GetHostStatsCommand due to exception " + e.getMessage();
s_logger.error(msg, e);
return new GetHostStatsAnswer(cmd, hostStats);
}
}
protected Answer execute(ModifyStoragePoolCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource ModifyStoragePoolCommand: " + _gson.toJson(cmd));
}
try {
StorageFilerTO pool = cmd.getPool();
s_logger.info("Primary storage pool details: " + pool.getHost() + " " + pool.getPath());
Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>();
// FIXME: get the actual storage capacity and storage stats of CSV volume
// by running powershell cmdlet. This hardcoding just for prototype.
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd,
1024*1024*1024*1024L, 512*1024*1024*1024L, tInfo);
return answer;
} catch (Throwable e) {
return new Answer(cmd, false, "Unable to execute ModifyStoragePoolCommand due to exception " + e.getMessage());
}
}
protected Answer execute(GetStorageStatsCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing GetStorageStatsCommand command: " + _gson.toJson(cmd));
}
// FIXME: get the actual storage capacity and storage stats of CSV volume
return new GetStorageStatsAnswer(cmd, 1024*1024*1024*1024L, 512*1024*1024*1024L);
}
private void fillHostHardwareInfo(StartupRoutingCommand cmd) throws RemoteException {
try {
// FIXME: get the actual host capacity by running cmdlet.This hardcoding just for prototype
cmd.setCaps("hvm");
cmd.setDom0MinMemory(0);
cmd.setSpeed(100000);
cmd.setCpus(6);
long ram = new Long("211642163904");
cmd.setMemory(ram);
} catch (Throwable e) {
s_logger.error("Unable to query host network info due to exception ", e);
throw new CloudRuntimeException("Unable to query host network info due to exception");
}
}
private void fillHostNetworkInfo(StartupRoutingCommand cmd) throws RemoteException {
try {
// FIXME: get the actual host and storage IP by running cmdlet.This hardcoding just for prototype
cmd.setPrivateIpAddress("192.168.154.236");
cmd.setPrivateNetmask("255.255.255.0");
cmd.setPrivateMacAddress("00:16:3e:77:e2:a0");
cmd.setStorageIpAddress("192.168.154.36");
cmd.setStorageNetmask("255.255.255.0");
cmd.setStorageMacAddress("00:16:3e:77:e2:a0");
} catch (Throwable e) {
s_logger.error("Unable to query host network info due to exception ", e);
throw new CloudRuntimeException("Unable to query host network info due to exception");
}
}
private List <String> getHostsInCluster(String clusterName)
{
List<String> hypervHosts = new ArrayList<String>();
try {
//StringBuilder cmd = new StringBuilder("cmd /c powershell.exe -OutputFormat XML ");
StringBuilder cmd = new StringBuilder("cmd /c powershell.exe ");
cmd.append("-Command Add-PSSnapin Microsoft.SystemCenter.VirtualMachineManager; ");
cmd.append("Get-VMMServer -ComputerName localhost; ");
cmd.append("Get-VMHostCluster ");
cmd.append(clusterName.toCharArray());
Process p = Runtime.getRuntime().exec(cmd.toString());
p.getOutputStream().close();
InputStreamReader temperrReader = new InputStreamReader(new BufferedInputStream(p.getErrorStream()));
BufferedReader errreader = new BufferedReader(temperrReader);
if (errreader.ready()) {
String errorOutput = new String("");
s_logger.info("errors found while running cmdlet Get-VMHostCluster");
while (true){
String errline = errreader.readLine();
if (errline == null) {
break;
}
errorOutput = errorOutput + errline;
}
s_logger.info(errorOutput);
} else {
s_logger.info("No errors found in running cmdlet:" + cmd);
}
p.getErrorStream().close();
/*
InputStream in = (InputStream) p.getInputStream();
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader parser = factory.createXMLStreamReader(in);
while(parser.hasNext()) {
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
// Do something
break;
case END_ELEMENT:
// Do something
break;
// And so on ...
}
}
parser.close();
*/
InputStreamReader tempReader = new InputStreamReader(new BufferedInputStream(p.getInputStream()));
BufferedReader reader = new BufferedReader(tempReader);
String output = new String("");
while (true){
String line = reader.readLine();
if (line == null) {
break;
}
output = output + line;
}
String nodesListStr = output.substring(output.indexOf("Nodes"));
nodesListStr = nodesListStr.substring(nodesListStr.indexOf('{', 0)+1, nodesListStr.indexOf('}', 0));
String[] nodesList = nodesListStr.split(",");
for (String node : nodesList) {
hypervHosts.add(node);
}
p.getInputStream().close();
} catch (Exception e)
{
s_logger.info("Exception caught: "+e.getMessage());
}
return hypervHosts;
}
protected HashMap<String, PowerState> sync() {
HashMap<String, PowerState> changes = new HashMap<String, PowerState>();
try {
synchronized (_vms) {
}
} catch (Throwable e) {
s_logger.error("Unable to perform sync information collection process at this point due to exception ", e);
return null;
}
return changes;
}
@Override
public PingCommand getCurrentStatus(long id) {
HashMap<String, PowerState> newStates = sync();
if (newStates == null) {
newStates = new HashMap<String, PowerState>();
}
PingRoutingCommand cmd = new PingRoutingCommand(com.cloud.host.Host.Type.Routing, id, newStates);
return cmd;
}
@Override
public boolean configure(String name, Map<String, Object> params)
throws ConfigurationException {
_dcId = params.get("zone").toString();
_podId= params.get("pod").toString();
_clusterId = params.get("cluster").toString();
_guid = params.get("guid").toString();
boolean success = super.configure(name, params);
if (! success) {
return false;
}
return true;
}
@Override
protected String getDefaultScriptsDir() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
}
@Override
public void setConfigParams(Map<String, Object> params) {
// TODO Auto-generated method stub
}
@Override
public Map<String, Object> getConfigParams() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getRunLevel() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void setRunLevel(int level) {
// TODO Auto-generated method stub
}
}

View File

@ -32,7 +32,7 @@ public interface StorageProcessor {
public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd);
public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd);
public Answer createTemplateFromVolume(CopyCommand cmd);
public Answer backupSnasphot(CopyCommand cmd);
public Answer backupSnapshot(CopyCommand cmd);
public Answer attachIso(AttachCommand cmd);
public Answer attachVolume(AttachCommand cmd);
public Answer dettachIso(DettachCommand cmd);

View File

@ -81,7 +81,7 @@ public class StorageSubsystemCommandHandlerBase implements StorageSubsystemComma
return processor.createTemplateFromVolume(cmd);
}
} else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
return processor.backupSnasphot(cmd);
return processor.backupSnapshot(cmd);
} else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType() == DataObjectType.VOLUME) {
return processor.createVolumeFromSnapshot(cmd);
}

View File

@ -26,14 +26,14 @@ import com.cloud.agent.api.AttachVolumeCommand;
import com.cloud.storage.Storage.StoragePoolType;
public class AttachVolumeAnswerTest {
AttachVolumeCommand avc = new AttachVolumeCommand(true, "vmname",
StoragePoolType.Filesystem, "vFolder", "vPath", "vName",
AttachVolumeCommand avc = new AttachVolumeCommand(true, false, "vmname",
StoragePoolType.Filesystem, "vPath", "vName",
123456789L, "chainInfo");
AttachVolumeAnswer ava1 = new AttachVolumeAnswer(avc);
String results = "";
AttachVolumeAnswer ava2 = new AttachVolumeAnswer(avc, results);
Long deviceId = 10L;
AttachVolumeAnswer ava3 = new AttachVolumeAnswer(avc, deviceId);
AttachVolumeAnswer ava3 = new AttachVolumeAnswer(avc, deviceId, "");
@Test
public void testGetDeviceId() {

View File

@ -25,8 +25,8 @@ import com.cloud.agent.api.AttachVolumeCommand;
import com.cloud.storage.Storage.StoragePoolType;
public class AttachVolumeCommandTest {
AttachVolumeCommand avc = new AttachVolumeCommand(true, "vmname",
StoragePoolType.Filesystem, "vFolder", "vPath", "vName",
AttachVolumeCommand avc = new AttachVolumeCommand(true, false, "vmname",
StoragePoolType.Filesystem, "vPath", "vName",
123456789L, "chainInfo");
@Test
@ -65,12 +65,6 @@ public class AttachVolumeCommandTest {
assertTrue(pt.equals(StoragePoolType.Iscsi));
}
@Test
public void testGetVolumeFolder() {
String vFolder = avc.getVolumeFolder();
assertTrue(vFolder.equals("vFolder"));
}
@Test
public void testGetVolumePath() {
String vPath = avc.getVolumePath();

View File

@ -87,6 +87,11 @@ public class BackupSnapshotCommandTest {
return 0L;
};
@Override
public Long getCapacityIops() {
return 0L;
}
@Override
public Long getClusterId() {
return 0L;

View File

@ -125,6 +125,11 @@ public class CheckNetworkAnswerTest {
return 0L;
};
@Override
public Long getCapacityIops() {
return 0L;
};
@Override
public Long getClusterId() {
return 0L;

View File

@ -78,6 +78,10 @@ public class SnapshotCommandTest {
return 0L;
};
public Long getCapacityIops() {
return 0L;
};
public Long getClusterId() {
return 0L;
};

View File

@ -58,6 +58,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-storage-image-simulator</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>install</defaultGoal>

View File

@ -21,24 +21,41 @@
specific language governing permissions and limitations
under the License.
-->
<section id="attaching-volume">
<title>Attaching a Volume</title>
<para>You can attach a volume to a guest VM to provide extra disk storage. Attach a volume when you first create a new volume, when you are moving an existing volume from one VM to another, or after you have migrated a volume from one storage pool to another.</para>
<orderedlist>
<listitem><para>Log in to the &PRODUCT; UI as a user or admin.</para></listitem>
<listitem><para>In the left navigation, click Storage.</para></listitem>
<listitem><para>In Select View, choose Volumes.</para></listitem>
<listitem><para>4. Click the volume name in the Volumes list, then click the Attach Disk button<inlinemediaobject>
<imageobject>
<imagedata fileref="./images/attach-disk-icon.png" />
</imageobject>
<textobject><phrase>AttachDiskButton.png: button to attach a volume</phrase></textobject>
</inlinemediaobject>
</para></listitem>
<listitem><para>In the Instance popup, choose the VM to which you want to attach the volume. You will only see instances to which you are allowed to attach volumes; for example, a user will see only instances created by that user, but the administrator will have more choices.</para>
<!-- <para>If the VM is running in the OVM hypervisor, the VM must be stopped before a new volume can be attached to it.</para> -->
</listitem>
<listitem><para>When the volume has been attached, you should be able to see it by clicking Instances, the instance name, and View Volumes.</para></listitem>
</orderedlist>
</section>
<title>Attaching a Volume</title>
<para>You can attach a volume to a guest VM to provide extra disk storage. Attach a volume when
you first create a new volume, when you are moving an existing volume from one VM to another, or
after you have migrated a volume from one storage pool to another.</para>
<orderedlist>
<listitem>
<para>Log in to the &PRODUCT; UI as a user or admin.</para>
</listitem>
<listitem>
<para>In the left navigation, click Storage.</para>
</listitem>
<listitem>
<para>In Select View, choose Volumes.</para>
</listitem>
<listitem>
<para>4. Click the volume name in the Volumes list, then click the Attach Disk button<inlinemediaobject>
<imageobject>
<imagedata fileref="./images/attach-disk-icon.png"/>
</imageobject>
<textobject>
<phrase>AttachDiskButton.png: button to attach a volume</phrase>
</textobject>
</inlinemediaobject>
</para>
</listitem>
<listitem>
<para>In the Instance popup, choose the VM to which you want to attach the volume. You will
only see instances to which you are allowed to attach volumes; for example, a user will see
only instances created by that user, but the administrator will have more choices.</para>
<!-- <para>If the VM is running in the OVM hypervisor, the VM must be stopped before a new volume can be attached to it.</para> -->
</listitem>
<listitem>
<para>When the volume has been attached, you should be able to see it by clicking Instances,
the instance name, and View Volumes.</para>
</listitem>
</orderedlist>
</section>

View File

@ -0,0 +1,29 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "cloudstack.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<chapter id="plugin-development">
<title>Plugin Development</title>
<para>This chapter will detail different elements related to the development of plugins within Cloudstack</para>
<xi:include href="creating-my-first-plugin.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</chapter>

View File

@ -0,0 +1,216 @@
<?xml version='1.0' encoding='utf-8'?>
<!-- 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.
-->
<section id="creating-my-first-plugin">
<title>Creating my first plugin</title>
<para>This is a brief walk through of creating a simple plugin that adds an additional command to the API to return the message "Hello World".</para>
<section id="letting-cloudstack-know-about-the-plugin">
<title>Letting Cloudstack know about the plugin</title>
<para>Before we can being we need to tell Cloudstack about the existance of our plugin. In order to do this we are required to edit some files related to the cloud-client-ui module</para>
<orderedlist>
<listitem>
<para>Navigate to the folder called client</para>
</listitem>
<listitem>
<para>Open pom.xml and add a dependency, this will look something like the following: </para>
<example>
<title>client/pom.xml</title>
<programlisting language="XML">&lt;dependency&gt;
&lt;groupId&gt;org.apache.cloudstack&lt;/groupId&gt;
&lt;artifactId&gt;cloud-plugin-api-helloworld&lt;/artifactId&gt;
&lt;version&gt;${project.version}&lt;/version&gt;
&lt;/dependency&gt;</programlisting>
</example>
</listitem>
<listitem>
<para>Continuing with client as your working directory open up tomcatconf/applicationContext.xml.in</para>
</listitem>
<listitem>
<para>Within this file we must insert a bean to load our class:</para>
<example>
<title>client/tomcatconf/applicationContext.xml.in</title>
<programlisting language="XML">&lt;bean id="helloWorldImpl" class="org.apache.cloudstack.helloworld.HelloWorldImpl" /&gt;</programlisting>
</example>
</listitem>
<listitem>
<para>Finally we need to register the additional API commands we add. Again with client as your working directory this is done by modifying tomcatconf/commands.properties.in</para>
</listitem>
<listitem>
<para>Within the file we simply add the names of the API commands we want to create followed by a permission number. 1 = admin, 2 = resource domain admin, 4 = domain admin, 8 = user.</para>
<example>
<title>tomcatconf/commands.properties.in</title>
<programlisting>helloWorld=8</programlisting>
</example>
</listitem>
</orderedlist>
</section>
<section id="creating-the-plugin">
<title>Creating the plugin</title>
<para>Within the Cloudstack filing structure all plugins live under the plugins folder. Since the sample plugin for this document is going to be API related it will live in plugins/api/helloworld. Along with this we will need a standard maven package layout, so lets create all the required folders:</para>
<programlisting language="Bash">$ mkdir -p plugins/api/helloworld/{src,target,test}
$ mkdir -p plugins/api/helloworld/src/org/apache/cloudstack/{api,helloworld}
$ mkdir -p plugins/api/helloworld/src/org/apache/cloudstack/api/{command,response}
$ mkdir -p plugins/api/helloworld/src/org/apache/cloudstack/api/command/user/helloworld</programlisting>
<para>With helloworld as our working directory we should have a tree layout like the following:</para>
<programlisting language="Bash">$ cd plugins/api/helloworld
$ tree
.
|-- src
| `-- org
| `-- apache
| `-- cloudstack
| |-- api
| | |-- command
| | | `-- user
| | | `-- helloworld
| | |-- response
| `-- helloworld
|-- target
`-- test
12 directories, 0 files</programlisting>
<para>First we will create a pom.xml for our plugin:</para>
<example>
<title>plugins/api/helloworld/pom.xml</title>
<programlisting language="XML">&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
&lt;artifactId&gt;cloud-plugin-api-helloworld&lt;/artifactId&gt;
&lt;name&gt;Apache CloudStack Plugin - Hello World Plugin&lt;/name&gt;
&lt;parent&gt;
&lt;groupId&gt;org.apache.cloudstack&lt;/groupId&gt;
&lt;artifactId&gt;cloudstack-plugins&lt;/artifactId&gt;
&lt;version&gt;4.2.0-SNAPSHOT&lt;/version&gt;
&lt;relativePath&gt;../../pom.xml&lt;/relativePath&gt;
&lt;/parent&gt;
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.cloudstack&lt;/groupId&gt;
&lt;artifactId&gt;cloud-api&lt;/artifactId&gt;
&lt;version&gt;${project.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.cloudstack&lt;/groupId&gt;
&lt;artifactId&gt;cloud-utils&lt;/artifactId&gt;
&lt;version&gt;${project.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
&lt;defaultGoal&gt;install&lt;/defaultGoal&gt;
&lt;sourceDirectory&gt;src&lt;/sourceDirectory&gt;
&lt;testSourceDirectory&gt;test&lt;/testSourceDirectory&gt;
&lt;/build&gt;
&lt;/project&gt;</programlisting>
</example>
<para>Next we need to make the root plugin pom aware of our plugin to do this simply edit plugins/pom.xml inserting a line like the following:</para>
<programlisting language="XML">......
&lt;module&gt;api/helloworld&lt;/module&gt;
......</programlisting>
<para>Finally we will being to create code for your plugin. Create an interface called HelloWorld that will extend PluggableService within src/org/apache/cloudstack/hellowold</para>
<programlisting language="Java">package org.apache.cloudstack.helloworld;
import com.cloud.utils.component.PluggableService;
public interface HelloWorld extends PluggableService { }</programlisting>
<para>Create an implementation of HelloWorld called HelloWorldImpl:</para>
<programlisting language="Java">package org.apache.cloudstack.helloworld;
import org.apache.cloudstack.api.command.user.helloworld.HelloWorldCmd;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import javax.ejb.Local;
import java.util.*;
@Component
@Local(value = HelloWorld.class)
public class HelloWorldImpl implements HelloWorld {
private static final Logger s_logger = Logger.getLogger(HelloWorldImpl.class);
public HelloWorldImpl() {
super();
}
/**
* This informs cloudstack of the API commands you are creating.
*/
@Override
public List&lt;Class&lt;?&gt;&gt; getCommands() {
List&lt;Class&lt;?&gt;&gt; cmdList = new ArrayList&lt;Class&lt;?&gt;&gt;();
cmdList.add(HelloWorldCmd.class);
return cmdList;
}
}</programlisting>
<para>Next we will create our API command navigate to src/org/apache/cloudstack/api/command/user/helloworld and open up HelloWorldCmd.java, create it as follows</para>
<programlisting language="Java">package org.apache.cloudstack.api.command.user.helloworld;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.response.HelloWorldResponse;
import org.apache.log4j.Logger;
// Note this name matches the name you inserted into client/tomcatconf/commands.properties.in
@APICommand(name = "helloWorld", responseObject = HelloWorldResponse.class, description = "Returns a hello world message", since = "4.2.0")
public class HelloWorldCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(HelloWorldCmd.class.getName());
private static final String s_name = "helloworldresponse";
@Override
public void execute()
{
HelloWorldResponse response = new HelloWorldResponse();
response.setObjectName("helloworld");
response.setResponseName(getCommandName());
this.setResponseObject(response);
}
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return 0;
}
}</programlisting>
<para>Finally we need to create our HelloWorldResponse class, this will exist within src/org/apache/cloudstack/api/response/</para>
<programlisting language="Java">package org.apache.cloudstack.api.response;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param;
@SuppressWarnings("unused")
public class HelloWorldResponse extends BaseResponse {
@SerializedName("HelloWorld") @Param(description="HelloWorld Response")
private String HelloWorld;
public HelloWorldResponse(){
this.HelloWorld = "Hello World";
}
}</programlisting>
</section>
<section id="compiling-your-plugin">
<title>Compiling your plugin:</title>
<para>Within the directory of your plugin i.e. plugins/api/helloworld run mvn clean install.</para>
<para>After this we need to recompile the client-cloud-ui to do this come back to the cloudstack base directory and execute mvn -pl client clean install</para>
</section>
<section id="starting-cloudstack-and-testing">
<title>Starting Cloudstack and Testing:</title>
<para>Start up cloudstack with the normal mvn pl :client-cloud-ui jetty:run, wait a few moments for it to start up then head over to: localhost:8096/client/api?command=helloWorld and you should see your HelloWorld message.</para>
</section>
</section>

View File

@ -20,44 +20,65 @@
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
-->
<section id="creating-new-volumes">
<title>Creating a New Volume</title>
<para>You can add more data disk volumes to a guest VM at any time, up to the limits of your storage capacity. Both &PRODUCT; administrators and users can add volumes to VM instances. When you create a new volume, it is stored as an entity in &PRODUCT;, but the actual storage resources are not allocated on the physical storage device until you attach the volume. This optimization allows the &PRODUCT; to provision the volume nearest to the guest that will use it when the first attachment is made.</para>
<section id="local-storage-data-volumes">
<title>Using Local Storage for Data Volumes</title>
<para>You can create data volumes on local storage (supported with XenServer, KVM, and VMware).
The data volume is placed on the same
host as the VM instance that is attached to the data volume. These
local data volumes can be attached to virtual machines, detached, re-attached,
and deleted just as with the other types of data volume.</para>
<para>Local storage is ideal for scenarios where persistence of data volumes and HA
is not required. Some of the benefits include reduced disk I/O latency and cost
reduction from using inexpensive local disks.</para>
<para>In order for local volumes to be used, the feature must be enabled for the
zone.</para>
<para>You can create a data disk offering for local storage. When a user creates a
new VM, they can select this disk offering in order to cause the data disk
volume to be placed in local storage.</para>
<para>You can not migrate a VM that has a volume in local storage to a different
host, nor migrate the volume itself away to a different host. If you want to put
a host into maintenance mode, you must first stop any VMs with local data
volumes on that host.</para>
</section>
<section id="creating-new-volume-steps">
<title>To Create a New Volume</title>
<orderedlist>
<listitem><para>Log in to the &PRODUCT; UI as a user or admin.</para></listitem>
<listitem><para>In the left navigation bar, click Storage.</para></listitem>
<listitem><para>In Select View, choose Volumes.</para></listitem>
<listitem><para>To create a new volume, click Add Volume, provide the following details, and click OK.</para>
<itemizedlist>
<listitem><para>Name. Give the volume a unique name so you can find it later.</para></listitem>
<listitem><para>Availability Zone. Where do you want the storage to reside? This should be close to the VM that will use the volume.</para></listitem>
<listitem><para>Disk Offering. Choose the characteristics of the storage.</para></listitem>
</itemizedlist>
<para>The new volume appears in the list of volumes with the state “Allocated.” The volume data is stored in &PRODUCT;, but the volume is not yet ready for use</para></listitem>
<listitem><para>To start using the volume, continue to Attaching a Volume </para></listitem>
</orderedlist>
</section>
<title>Creating a New Volume</title>
<para>You can add more data disk volumes to a guest VM at any time, up to the limits of your
storage capacity. Both &PRODUCT; administrators and users can add volumes to VM instances. When
you create a new volume, it is stored as an entity in &PRODUCT;, but the actual storage
resources are not allocated on the physical storage device until you attach the volume. This
optimization allows the &PRODUCT; to provision the volume nearest to the guest that will use it
when the first attachment is made.</para>
<section id="local-storage-data-volumes">
<title>Using Local Storage for Data Volumes</title>
<para>You can create data volumes on local storage (supported with XenServer, KVM, and VMware).
The data volume is placed on the same host as the VM instance that is attached to the data
volume. These local data volumes can be attached to virtual machines, detached, re-attached,
and deleted just as with the other types of data volume.</para>
<para>Local storage is ideal for scenarios where persistence of data volumes and HA is not
required. Some of the benefits include reduced disk I/O latency and cost reduction from using
inexpensive local disks.</para>
<para>In order for local volumes to be used, the feature must be enabled for the zone.</para>
<para>You can create a data disk offering for local storage. When a user creates a new VM, they
can select this disk offering in order to cause the data disk volume to be placed in local
storage.</para>
<para>You can not migrate a VM that has a volume in local storage to a different host, nor
migrate the volume itself away to a different host. If you want to put a host into maintenance
mode, you must first stop any VMs with local data volumes on that host.</para>
</section>
<section id="creating-new-volume-steps">
<title>To Create a New Volume</title>
<orderedlist>
<listitem>
<para>Log in to the &PRODUCT; UI as a user or admin.</para>
</listitem>
<listitem>
<para>In the left navigation bar, click Storage.</para>
</listitem>
<listitem>
<para>In Select View, choose Volumes.</para>
</listitem>
<listitem>
<para>To create a new volume, click Add Volume, provide the following details, and click
OK.</para>
<itemizedlist>
<listitem>
<para>Name. Give the volume a unique name so you can find it later.</para>
</listitem>
<listitem>
<para>Availability Zone. Where do you want the storage to reside? This should be close
to the VM that will use the volume.</para>
</listitem>
<listitem>
<para>Disk Offering. Choose the characteristics of the storage.</para>
</listitem>
</itemizedlist>
<para>The new volume appears in the list of volumes with the state “Allocated.” The volume
data is stored in &PRODUCT;, but the volume is not yet ready for use</para>
</listitem>
<listitem>
<para>To start using the volume, continue to Attaching a Volume </para>
</listitem>
</orderedlist>
</section>
</section>

View File

@ -22,25 +22,39 @@
under the License.
-->
<section id="detach-move-volumes">
<title>Detaching and Moving Volumes</title>
<note><para>This procedure is different from moving disk volumes from one storage pool to another. See VM Storage Migration </para></note>
<para>A volume can be detached from a guest VM and attached to another guest. Both &PRODUCT; administrators and users can detach volumes from VMs and move them to other VMs.</para>
<para>If the two VMs are in different clusters, and the volume is large, it may take several minutes for the volume to be moved to the new VM.</para>
<!-- <para>If the destination VM is running in the OVM hypervisor, the VM must be stopped before a new volume can be attached to it.</para> -->
<orderedlist>
<listitem><para>Log in to the &PRODUCT; UI as a user or admin.</para></listitem>
<listitem><para>In the left navigation bar, click Storage, and choose Volumes in Select View. Alternatively, if you know which VM the volume is attached to, you can click Instances, click the VM name, and click View Volumes.</para></listitem>
<listitem><para>Click the name of the volume you want to detach, then click the Detach Disk button. <inlinemediaobject>
<imageobject>
<imagedata fileref="./images/detach-disk-icon.png"/>
</imageobject>
<textobject>
<phrase>DetachDiskButton.png: button to detach a volume</phrase>
</textobject>
</inlinemediaobject>
</para></listitem>
<listitem><para>To move the volume to another VM, follow the steps in <xref linkend="attaching-volume"
/>.</para></listitem>
</orderedlist>
</section>
<title>Detaching and Moving Volumes</title>
<note>
<para>This procedure is different from moving disk volumes from one storage pool to another. See
VM Storage Migration </para>
</note>
<para>A volume can be detached from a guest VM and attached to another guest. Both &PRODUCT;
administrators and users can detach volumes from VMs and move them to other VMs.</para>
<para>If the two VMs are in different clusters, and the volume is large, it may take several
minutes for the volume to be moved to the new VM.</para>
<!-- <para>If the destination VM is running in the OVM hypervisor, the VM must be stopped before a new volume can be attached to it.</para> -->
<orderedlist>
<listitem>
<para>Log in to the &PRODUCT; UI as a user or admin.</para>
</listitem>
<listitem>
<para>In the left navigation bar, click Storage, and choose Volumes in Select View.
Alternatively, if you know which VM the volume is attached to, you can click Instances,
click the VM name, and click View Volumes.</para>
</listitem>
<listitem>
<para>Click the name of the volume you want to detach, then click the Detach Disk button. <inlinemediaobject>
<imageobject>
<imagedata fileref="./images/detach-disk-icon.png"/>
</imageobject>
<textobject>
<phrase>DetachDiskButton.png: button to detach a volume</phrase>
</textobject>
</inlinemediaobject>
</para>
</listitem>
<listitem>
<para>To move the volume to another VM, follow the steps in <xref linkend="attaching-volume"
/>.</para>
</listitem>
</orderedlist>
</section>

View File

@ -48,6 +48,7 @@
<xi:include href="dns-dhcp.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="vpn.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="elastic-ip.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="portable-ip.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="pvlan.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="inter-vlan-routing.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="configure-vpc.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>

View File

@ -0,0 +1,28 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "cloudstack.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<chapter id="plugin-development">
<title>Plugin Development</title>
<xi:include href="creating-my-first-plugin.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</chapter>

View File

@ -22,13 +22,35 @@
<title>Portable IPs</title>
<section id="about-pip">
<title>About Portable IP</title>
<para>Portable IPs in &PRODUCT; are nothing but elastic IPs that can be transferred across
geographically separated zones. As an administrator, you can provision a pool of portable IPs
at region level and are available for user consumption. The users can acquire portable IPs if
admin has provisioned portable public IPs at the region level they are part of. These IPs can
be use for any service within an advanced zone. You can also use portable IPs for EIP service
in basic zones. Additionally, a portable IP can be transferred from one network to another
network.</para>
<para>Portable IPs in &PRODUCT; are region-level pool of IPs, which are elastic in nature, that
can be transferred across geographically separated zones. As an administrator, you can
provision a pool of portable IPs at region level and are available for user consumption. The
users can acquire portable IPs if admin has provisioned portable public IPs at the region
level they are part of. These IPs can be use for any service within an advanced zone. You can
also use portable IPs for EIP services in basic zones. </para>
<para>The salient features of Portable IP are as follows:<itemizedlist>
<listitem>
<para>IP is statically allocated </para>
</listitem>
<listitem>
<para>IP need not be associated with a network </para>
</listitem>
<listitem>
<para>Network association is transferable across networks </para>
</listitem>
<listitem>
<para>IP is transferable across both Basic and Advanced zones </para>
</listitem>
<listitem>
<para>IP is transferable across VPC, non-VPC Isolated and Shared networks </para>
</listitem>
<listitem>
<para/>
</listitem>
<listitem>
<para/>
</listitem>
</itemizedlist></para>
</section>
<section id="config-pip">
<title>Configuring Portable IPs</title>
@ -73,7 +95,9 @@
</listitem>
</itemizedlist>
</listitem>
<listitem><para>Click OK.</para></listitem>
<listitem>
<para>Click OK.</para>
</listitem>
</orderedlist>
</section>
<section id="acquire-pip">

View File

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "cloudstack.ent">
%BOOK_ENTITIES;
]>
@ -21,12 +21,11 @@
specific language governing permissions and limitations
under the License.
-->
<chapter id="storage">
<title>Working With Storage</title>
<xi:include href="storage-overview.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="primary-storage.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="secondary-storage.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="working-with-volumes.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="working-with-snapshots.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<title>Working With Storage</title>
<xi:include href="storage-overview.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="primary-storage.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="secondary-storage.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="working-with-volumes.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="working-with-snapshots.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
</chapter>

View File

@ -21,56 +21,91 @@
specific language governing permissions and limitations
under the License.
-->
<section id="upload-existing-volume-to-vm">
<title>Uploading an Existing Volume to a Virtual Machine</title>
<para>Existing data can be made accessible to a virtual machine. This is called uploading a volume to the VM. For example, this is useful to upload data from a local file system and attach it to a VM. Root administrators, domain administrators, and end users can all upload existing volumes to VMs.</para>
<para>The upload is performed using HTTP. The uploaded volume is placed in the zone's secondary storage</para>
<para>You cannot upload a volume if the preconfigured volume limit has already been reached. The default limit for the cloud is set in the global configuration parameter max.account.volumes, but administrators can also set per-domain limits that are different from the global default. See Setting Usage Limits </para>
<para>To upload a volume:</para>
<orderedlist>
<listitem id="optional-hash"><para>(Optional) Create an MD5 hash (checksum) of the disk image file that you are going to upload. After uploading the data disk, &PRODUCT; will use this value to verify that no data corruption has occurred.</para></listitem>
<listitem><para>Log in to the &PRODUCT; UI as an administrator or user</para></listitem>
<listitem><para>In the left navigation bar, click Storage.</para></listitem>
<listitem><para>Click Upload Volume.</para></listitem>
<listitem><para>Provide the following:</para>
<itemizedlist>
<listitem><para>Name and Description. Any desired name and a brief description that can be shown in the UI.</para></listitem>
<listitem><para>Availability Zone. Choose the zone where you want to store the volume. VMs running on hosts in this zone can attach the volume.</para></listitem>
<listitem><para>Format. Choose one of the following to indicate the disk image format of the volume.</para>
<informaltable>
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<thead>
<row>
<entry><para>Hypervisor</para></entry>
<entry><para>Disk Image Format</para></entry>
</row>
</thead>
<tbody>
<row>
<entry><para>XenServer</para></entry>
<entry><para>VHD</para></entry>
</row>
<row>
<entry><para>VMware</para></entry>
<entry><para>OVA</para></entry>
</row>
<row>
<entry><para>KVM</para></entry>
<entry><para>QCOW2</para></entry>
</row>
<!-- <row>
<title>Uploading an Existing Volume to a Virtual Machine</title>
<para>Existing data can be made accessible to a virtual machine. This is called uploading a volume
to the VM. For example, this is useful to upload data from a local file system and attach it to
a VM. Root administrators, domain administrators, and end users can all upload existing volumes
to VMs.</para>
<para>The upload is performed using HTTP. The uploaded volume is placed in the zone's secondary
storage</para>
<para>You cannot upload a volume if the preconfigured volume limit has already been reached. The
default limit for the cloud is set in the global configuration parameter max.account.volumes,
but administrators can also set per-domain limits that are different from the global default.
See Setting Usage Limits </para>
<para>To upload a volume:</para>
<orderedlist>
<listitem>
<para>(Optional) Create an MD5 hash (checksum) of the disk image file that you are going to
upload. After uploading the data disk, &PRODUCT; will use this value to verify that no data
corruption has occurred.</para>
</listitem>
<listitem>
<para>Log in to the &PRODUCT; UI as an administrator or user</para>
</listitem>
<listitem>
<para>In the left navigation bar, click Storage.</para>
</listitem>
<listitem>
<para>Click Upload Volume.</para>
</listitem>
<listitem>
<para>Provide the following:</para>
<itemizedlist>
<listitem>
<para>Name and Description. Any desired name and a brief description that can be shown in
the UI.</para>
</listitem>
<listitem>
<para>Availability Zone. Choose the zone where you want to store the volume. VMs running
on hosts in this zone can attach the volume.</para>
</listitem>
<listitem>
<para>Format. Choose one of the following to indicate the disk image format of the
volume.</para>
<informaltable>
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<thead>
<row>
<entry><para>Hypervisor</para></entry>
<entry><para>Disk Image Format</para></entry>
</row>
</thead>
<tbody>
<row>
<entry><para>XenServer</para></entry>
<entry><para>VHD</para></entry>
</row>
<row>
<entry><para>VMware</para></entry>
<entry><para>OVA</para></entry>
</row>
<row>
<entry><para>KVM</para></entry>
<entry><para>QCOW2</para></entry>
</row>
<!-- <row>
<entry><para>OVM</para></entry>
<entry><para>RAW</para></entry>
</row> -->
</tbody>
</tgroup>
</informaltable></listitem>
<listitem><para>URL. The secure HTTP or HTTPS URL that &PRODUCT; can use to access your disk. The type of file at the URL must match the value chosen in Format. For example, if Format is VHD, the URL might look like the following:</para>
<para>http://yourFileServerIP/userdata/myDataDisk.vhd</para></listitem>
<listitem><para>MD5 checksum. (Optional) Use the hash that you created in step <xref linkend="optional-hash"/>.</para></listitem>
</itemizedlist>
</tbody>
</tgroup>
</informaltable>
</listitem>
<listitem><para>Wait until the status of the volume shows that the upload is complete. Click Instances - Volumes, find the name you specified in step <xref linkend="optional-hash"/>, and make sure the status is Uploaded.</para></listitem>
</orderedlist>
<listitem>
<para>URL. The secure HTTP or HTTPS URL that &PRODUCT; can use to access your disk. The
type of file at the URL must match the value chosen in Format. For example, if Format is
VHD, the URL might look like the following:</para>
<para>http://yourFileServerIP/userdata/myDataDisk.vhd</para>
</listitem>
<listitem>
<para>MD5 checksum. (Optional) Use the hash that you created in step 1.</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Wait until the status of the volume shows that the upload is complete. Click Instances -
Volumes, find the name you specified in step 5, and make sure the status is Uploaded.</para>
</listitem>
</orderedlist>
</section>

View File

@ -22,14 +22,19 @@
under the License.
-->
<section id="vm-storage-migration">
<title>VM Storage Migration</title>
<para>Supported in XenServer, KVM, and VMware.</para>
<note><para>This procedure is different from moving disk volumes from one VM to another. See Detaching and Moving Volumes <xref linkend="detach-move-volumes" />.</para>
</note>
<para></para>
<para>You can migrate a virtual machines root disk volume or any additional data disk volume from one storage pool to another in the same zone.</para>
<para>You can use the storage migration feature to achieve some commonly desired administration goals, such as balancing the load on storage pools and increasing the reliability of virtual machines by moving them away from any storage pool that is experiencing issues.</para>
<xi:include href="migrate-datadisk-volume-new-storage-pool.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="migrate-vm-rootvolume-volume-new-storage-pool.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</section>
<title>VM Storage Migration</title>
<para>Supported in XenServer, KVM, and VMware.</para>
<note>
<para>This procedure is different from moving disk volumes from one VM to another. See Detaching
and Moving Volumes <xref linkend="detach-move-volumes"/>.</para>
</note>
<para>You can migrate a virtual machines root disk volume or any additional data disk volume from
one storage pool to another in the same zone.</para>
<para>You can use the storage migration feature to achieve some commonly desired administration
goals, such as balancing the load on storage pools and increasing the reliability of virtual
machines by moving them away from any storage pool that is experiencing issues.</para>
<xi:include href="migrate-datadisk-volume-new-storage-pool.xml"
xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="migrate-vm-rootvolume-volume-new-storage-pool.xml"
xmlns:xi="http://www.w3.org/2001/XInclude"/>
</section>

View File

@ -21,15 +21,24 @@
specific language governing permissions and limitations
under the License.
-->
<section id="volume-deletion-garbage-collection">
<title>Volume Deletion and Garbage Collection</title>
<para>The deletion of a volume does not delete the snapshots that have been created from the volume</para>
<para>When a VM is destroyed, data disk volumes that are attached to the VM are not deleted.</para>
<para>Volumes are permanently destroyed using a garbage collection process. The global configuration variables expunge.delay and expunge.interval determine when the physical deletion of volumes will occur.</para>
<itemizedlist>
<listitem><para>expunge.delay: determines how old the volume must be before it is destroyed, in seconds</para></listitem>
<listitem><para>expunge.interval: determines how often to run the garbage collection check</para></listitem>
</itemizedlist>
<para>Administrators should adjust these values depending on site policies around data retention.</para>
<title>Volume Deletion and Garbage Collection</title>
<para>The deletion of a volume does not delete the snapshots that have been created from the
volume</para>
<para>When a VM is destroyed, data disk volumes that are attached to the VM are not
deleted.</para>
<para>Volumes are permanently destroyed using a garbage collection process. The global
configuration variables expunge.delay and expunge.interval determine when the physical deletion
of volumes will occur.</para>
<itemizedlist>
<listitem>
<para>expunge.delay: determines how old the volume must be before it is destroyed, in
seconds</para>
</listitem>
<listitem>
<para>expunge.interval: determines how often to run the garbage collection check</para>
</listitem>
</itemizedlist>
<para>Administrators should adjust these values depending on site policies around data
retention.</para>
</section>

View File

@ -21,29 +21,32 @@
specific language governing permissions and limitations
under the License.
-->
<section id="working-with-volumes">
<title>Using Swift for Secondary Storage</title>
<para>A volume provides storage to a guest VM. The volume can provide for
a root disk or an additional data disk. &PRODUCT; supports additional
volumes for guest VMs.
</para>
<para>Volumes are created for a specific hypervisor type. A volume that has
been attached to guest using one hypervisor type (e.g, XenServer) may not
be attached to a guest that is using another hypervisor type (e.g.
vSphere, KVM). This is because the different hypervisors use
different disk image formats.
</para>
<para>&PRODUCT; defines a volume as a unit of storage available to a guest
VM. Volumes are either root disks or data disks. The root disk has "/"
in the file system and is usually the boot device. Data disks provide
for additional storage (e.g. As "/opt" or "D:"). Every guest VM has a root
disk, and VMs can also optionally have a data disk. End users can mount
multiple data disks to guest VMs. Users choose data disks from the disk
offerings created by administrators. The user can create a template from
a volume as well; this is the standard procedure for private template
creation. Volumes are hypervisor-specific: a volume from one hypervisor
type may not be used on a guest of another hypervisor type.
</para>
<title>Working With Volumes</title>
<para>A volume provides storage to a guest VM. The volume can provide for a root disk or an
additional data disk. &PRODUCT; supports additional volumes for guest VMs. </para>
<para>Volumes are created for a specific hypervisor type. A volume that has been attached to guest
using one hypervisor type (e.g, XenServer) may not be attached to a guest that is using another
hypervisor type, for example:vSphere, KVM. This is because the different hypervisors use different
disk image formats. </para>
<para>&PRODUCT; defines a volume as a unit of storage available to a guest VM. Volumes are either
root disks or data disks. The root disk has "/" in the file system and is usually the boot
device. Data disks provide for additional storage, for example: "/opt" or "D:". Every guest VM
has a root disk, and VMs can also optionally have a data disk. End users can mount multiple data
disks to guest VMs. Users choose data disks from the disk offerings created by administrators.
The user can create a template from a volume as well; this is the standard procedure for private
template creation. Volumes are hypervisor-specific: a volume from one hypervisor type may not be
used on a guest of another hypervisor type. </para>
<note>
<para>&PRODUCT; supports attaching up to 13 data disks to a VM on XenServer hypervisor versions
6.0 and above. For the VMs on other hypervisor types, the data disk limit is 6.</para>
</note>
<xi:include href="creating-new-volumes.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="upload-existing-volume-to-vm.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="attaching-volume.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="detach-move-volumes.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="vm-storage-migration.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="resizing-volumes.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="volume-deletion-garbage-collection.xml"
xmlns:xi="http://www.w3.org/2001/XInclude"/>
</section>

View File

@ -0,0 +1,32 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "qig.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<authorgroup>
<author>
<firstname>Apache</firstname>
<surname>CloudStack</surname>
</author>
</authorgroup>

View File

@ -0,0 +1,52 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "Runbook.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<bookinfo id="book-qig-qig">
<title>Quick Install Guide</title>
<subtitle>Prescriptive instructions for deploying Apache CloudStack</subtitle>
<productname>Apache CloudStack</productname>
<productnumber>4.0.2</productnumber>
<edition>0</edition>
<pubsnumber>0</pubsnumber>
<abstract>
<para>
This guide is designed to provide a strict environment to guarantee
a higher degree of success in initial deployments of Apache CloudStack.
All of the elements of the environment will be provided to you.
Apache CloudStack is capable of much more complex configurations,
but they are beyond the scope of this document.
</para>
</abstract>
<corpauthor>
<inlinemediaobject>
<imageobject>
<imagedata fileref="Common_Content/images/title_logo.svg" format="SVG" />
</imageobject>
</inlinemediaobject>
</corpauthor>
<xi:include href="Common_Content/Legal_Notice.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Author_Group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</bookinfo>

View File

@ -0,0 +1,53 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "Runbook.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<chapter id="chap-Runbook-Test_Chapter">
<title>Test Chapter</title>
<para>
This is a test paragraph
</para>
<section id="sect-Runbook-Test_Chapter-Test_Section_1">
<title>Test Section 1</title>
<para>
This is a test paragraph in a section
</para>
</section>
<section id="sect-Runbook-Test_Chapter-Test_Section_2">
<title>Test Section 2</title>
<para>
This is a test paragraph in Section 2
<orderedlist>
<listitem>
<para>
listitem text
</para>
</listitem>
</orderedlist>
</para>
</section>
</chapter>

View File

@ -0,0 +1,258 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "qig.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<chapter id="chap-qig-Environment">
<title>Environment</title>
<para>
Before you begin, you need to prepare the environment before you install CloudStack.
We will go over the steps to prepare now.
</para>
<section id="sect-qig-Environment-operatingsys">
<title>Operating System</title>
<para>
Using the CentOS 6.4 x86_64 minimal install ISO, you'll need to install CentOS
on your hardware. The defaults will generally be acceptable for this installation.
</para>
<para>
Once this installation is complete, you'll want to connect to your freshly
installed machine via SSH as the root user. Note that you should not allow root
logins in a production environment, so be sure to turn off remote logins once you
have finished the installation and configuration.
</para>
<section id="sect-qig-Environment-operatingsys-network">
<title>Configuring the network</title>
<para>
By default the network will not come up on your hardware and you
will need to configure it to work in your environment. Since we
specified that there will be no DHCP server in this environment
we will be manually configuring your network interface. We will
assume, for the purposes of this exercise, that eth0 is the only network
interface that will be connected and used.
</para>
<para>
Connecting via the console you should login as root. Check the
file <filename>/etc/sysconfig/network-scripts/ifcfg-eth0</filename>,
it will look like this by default:
<screen>
DEVICE="eth0"
HWADDR="52:54:00:B9:A6:C0"
NM_CONTROLLED="yes"
ONBOOT="no"
</screen>
</para>
<para>
Unfortunately, this configuration will not permit you to connect to the network,
and is also unsuitable for our purposes with CloudStack. We want to
configure that file so that it specifies the IP address, netmask, etc., as shown
in the following example:
</para>
<important>
<title>Hardware Addresses</title>
<para>You should not use the hardware address (aka MAC address) from our example
for your configuration. It is network interface specific, so you should keep the
address already provided in the HWADDR directive.
</para>
</important>
<screen>
DEVICE=eth0
HWADDR=52:54:00:B9:A6:C0
NM_CONTROLLED=no
ONBOOT=yes
BOOTPROTO=none
IPADDR=172.16.10.2
NETMASK=255.255.255.0
GATEWAY=172.16.10.1
DNS1=8.8.8.8
DNS2=8.8.4.4
</screen>
<note>
<title>IP Addressing</title>
<para>Throughout this document we are assuming that you will
have a /24 network for your CloudStack implementation. This can be any
RFC 1918 network. However, we are assuming that you will match the
machine address that we are using. Thus we may use
<userinput><replaceable>172.16.10</replaceable>.2</userinput> and because
you might be using the 192.168.55.0/24 network you would use
<userinput><replaceable>192.168.55</replaceable>.2</userinput>
</para>
</note>
<para> Now that we have the configuration files properly set up, we need to run a
few commands to start up the network</para>
<screen><prompt># </prompt><userinput><command>chkconfig</command> network on</userinput></screen>
<screen><prompt># </prompt><userinput><command>service</command> network start</userinput></screen>
</section>
<section id="sect-qig-Environment-operatingsys-hostname">
<title>Hostname</title>
<para>
Cloudstack requires that the hostname be properly set. If you used the default
options in the installation, then your hostname is currently set to
localhost.localdomain. To test this we will run: </para>
<screen><prompt># </prompt><userinput>hostname --fqdn</userinput></screen>
<para>At this point it will likely return:</para>
<screen>localhost</screen>
<para>To rectify this situation - we'll set the hostname by editing the
<filename>/etc/hosts</filename> file so that it follows a similar format to this example:<screen>
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.10.2 srvr1.cloud.priv
</screen>
</para>
<para>After you've modified that file, go ahead and restart the network using:</para>
<screen><prompt># </prompt><userinput><command>service</command> network restart</userinput></screen>
<para>Now recheck with the <command>hostname --fqdn</command> command and ensure that it returns
a FQDN response</para>
</section>
<section id="sect-qig-Environment-operatingsys-selinux">
<title>SELinux</title>
<para>At the moment, for CloudStack to work properly SELinux must be
set to permissive. We want to both configure this for future boots and modify it
in the current running system.
</para>
<para>To configure SELinux to be permissive in the running system we need to run
the following command:</para>
<screen><prompt># </prompt><userinput><command>setenforce</command> 0</userinput></screen>
<para>
To ensure that it remains in that state we need to configure the file
<filename>/etc/selinux/config</filename> to reflect the permissive state,
as shown in this example: </para>
<screen>
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=permissive
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
</screen>
</section>
<section id="sect-qig-Environment-operatingsys-ntp">
<title>NTP</title>
<para>NTP configuration is a necessity for keeping all of the clocks in your cloud
servers in sync. However, NTP is not installed by default. So we'll install and
and configure NTP at this stage. Installation is accomplished as follows:
</para>
<screen><prompt># </prompt><userinput><command>yum</command> -y install ntp</userinput></screen>
<para>The actual default configuration is fine for our purposes, so we merely need to
enable it and set it to start on boot as follows:</para>
<screen><prompt># </prompt><userinput><command>chkconfig</command> ntpd on</userinput></screen>
<screen><prompt># </prompt><userinput><command>service</command> ntpd start</userinput></screen>
</section>
<section id="sect-qig-Environment-operatingsys-repoconfig">
<title>Configuring the CloudStack Package Repository</title>
<para>
We need to configure the machine to use a CloudStack package repository.
<important>
<title>The below repository is not an official Apache CloudStack project repository</title>
<para>
The Apache CloudStack official releases are source code. As such there are no
'official' binaries available. The full installation guide describes how to take
the source release and generate RPMs and and yum repository. This guide attempts
to keep things as simple as possible, and thus we are using one of the
community-provided yum repositories.
</para>
</important>
</para>
<para>To add the CloudStack repository, create <filename>/etc/yum.repos.d/cloudstack.repo</filename> and insert the following information.</para>
<programlisting>
[cloudstack]
name=cloudstack
baseurl=http://cloudstack.apt-get.eu/rhel/4.1/
enabled=1
gpgcheck=0
</programlisting>
</section>
</section>
<section id="sect-qig-Environment-nfs">
<title>NFS</title>
<para>
Our configuration is going to use NFS for both primary and secondary
storage. We are going to go ahead and setup two NFS shares for those
purposes. We'll start out by installing
<application>nfs-utils</application>.
</para>
<screen><prompt># </prompt><userinput><command>yum</command> install nfs-utils</userinput></screen>
<para>
We now need to configure NFS to serve up two different shares. This is handled comparatively easily
in the <filename>/etc/exports</filename> file. You should ensure that it has the following content:
</para>
<screen>
/secondary *(rw,async,no_root_squash)
/primary *(rw,async,no_root_squash)
</screen>
<para>
You will note that we specified two directories that don't exist (yet) on the system.
We'll go ahead and create those directories and set permissions appropriately on them with the following commands:
</para>
<screen>
<prompt># </prompt><userinput><command>mkdir</command> /primary</userinput>
<prompt># </prompt><userinput><command>mkdir</command> /secondary</userinput>
</screen>
<para>CentOS 6.x releases use NFSv4 by default. NFSv4 requires that domain setting matches on all clients.
In our case, the domain is cloud.priv, so ensure that the domain setting in <filename>/etc/idmapd.conf</filename>
is uncommented and set as follows:</para>
<screen>Domain = cloud.priv</screen>
<para>Now you'll need uncomment the configuration values in the file <filename>/etc/sysconfig/nfs</filename></para>
<screen>
LOCKD_TCPPORT=32803
LOCKD_UDPPORT=32769
MOUNTD_PORT=892
RQUOTAD_PORT=875
STATD_PORT=662
STATD_OUTGOING_PORT=2020
</screen>
<para> Now we need to configure the firewall to permit incoming NFS connections.
Edit the file <filename>/etc/sysconfig/iptables</filename>
</para>
<screen>
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p udp --dport 111 -j ACCEPT
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 111 -j ACCEPT
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 2049 -j ACCEPT
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 32803 -j ACCEPT
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p udp --dport 32769 -j ACCEPT
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 892 -j ACCEPT
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p udp --dport 892 -j ACCEPT
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 875 -j ACCEPT
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p udp --dport 875 -j ACCEPT
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p tcp --dport 662 -j ACCEPT
-A INPUT -s 172.16.10.0/24 -m state --state NEW -p udp --dport 662 -j ACCEPT
</screen>
<para>Now you can restart the iptables service with the following command:
</para>
<screen><prompt># </prompt><userinput><command>service</command> iptables restart</userinput></screen>
<para>We now need to configure nfs service to start on boot and actually start it on the host by
executing the following commands:</para>
<screen>
<prompt># </prompt><userinput><command>service</command> rpcbind start</userinput>
<prompt># </prompt><userinput><command>service</command> nfs start</userinput>
<prompt># </prompt><userinput><command>chkconfig</command> rpcbind on</userinput>
<prompt># </prompt><userinput><command>chkconfig</command> nfs on</userinput>
</screen>
</section>
</chapter>

View File

@ -0,0 +1,99 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "qig.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<chapter id="chap-qig-Management">
<title>Installation of the management server</title>
<para>
Now it is time to start installing CloudStack's management server
and some of the related components.
</para>
<section id="sect-qig-Management-database">
<title>Database Installation and Configuration</title>
<para>
We'll start out by installing <application>MySQL</application> and configuring
some options to ensure CloudStack runs well.
</para>
<para>
To install <application>MySQL</application> run the following command:
<screen><prompt># </prompt><userinput><command>yum</command> -y install mysql-server</userinput></screen>
</para>
<para>With <application>MySQL</application> installed we need to make
a few configuration changes to <filename>/etc/my.cnf</filename>.
Specifically we need to add the following options to the [mysqld] section:
<screen>
innodb_rollback_on_timeout=1
innodb_lock_wait_timeout=600
max_connections=350
log-bin=mysql-bin
binlog-format = 'ROW'
</screen>
</para>
<para>
Now that <application>MySQL</application> is properly configured we can
start it and configure it to start on boot as follows:
<screen>
<prompt># </prompt><userinput><command>service</command> mysqld start</userinput>
<prompt># </prompt><userinput><command>chkconfig</command> mysqld on</userinput>
</screen>
</para>
</section>
<section id="sect-qig-Management-installation">
<title>Installation</title>
<para>We are now going to install the management server. We do that by executing the following command:
<screen><prompt># </prompt><userinput><command>yum</command> -y install cloud-client</userinput></screen>
</para>
<para>With the application itself installed we can now setup the database, we'll do that with the following command
and options:
</para>
<screen><prompt># </prompt><userinput><command>cloudstack-setup-databases</command> cloud:<replaceable>password</replaceable>@localhost --deploy-as=root</userinput></screen>
<para>When this process is finished, you should see a message like "CloudStack has successfully initialized the database."
</para>
<para>Now that the database has been created, we can take the final step in setting up the management server by issuing the following command:</para>
<screen><prompt># </prompt><userinput><command>cloudstack-setup-management</command></userinput></screen>
</section>
<section id="sect-qig-Management-templatesetup">
<title>System Template Setup</title>
<para>CloudStack uses a number of system VMs to provide functionality for
accessing the console of virtual machines, providing various networking
services, and managing various aspects of storage. This step will
acquire those system images ready for deployment when we bootstrap
your cloud.
</para>
<para>
Now we need to download the system VM template and deploy that to the
share we just mounted. The management server includes a script to properly
manipulate the system VMs images.
</para>
<screen><prompt># </prompt><userinput><command>/usr/share/cloudstack-common/scripts/storage/secondary/cloud-install-sys-tmplt</command> -m /secondary -u http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2 -h kvm -F</userinput>
</screen>
<para>
That concludes our setup of the management server. We still need to
configure CloudStack, but we will do that after we get our hypervisor
set up.
</para>
</section>
</chapter>

View File

@ -0,0 +1,93 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "qig.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<chapter id="chap-qig-Overview">
<title>Overview</title>
<para>
Infrastructure-as-a-Service (IaaS) clouds can be a complex thing to build,
and by definition they have a plethora of options, which often lead to confusion
for even experienced admins who are newcomers to building cloud platforms.
The goal for this runbook is to provide a straightforward set of instructions
to get you up and running with CloudStack with a minimum amount of trouble.
</para>
<section id="sect-qig-Overview-What_building">
<title>What exactly are we building?</title>
<para>
This runbook will focus on building a CloudStack cloud using KVM with
CentOS 6.4 with NFS storage on a flat layer-2 network utilizing
layer-3 network isolation (aka Security Groups), and doing it all
on a single piece of hardware.
</para>
<para>
KVM, or Kernel-based Virtual Machine is a virtualization technology
for the Linux kernel. KVM supports native virtualization atop
processors with hardware virtualization extensions.
</para>
<para>
Security Groups act as distributed firewalls that control access
to a group of virtual machines.
</para>
</section>
<section id="sect-qig-Overview-hilevel">
<title>High level overview of the process</title>
<para>
Before we actually get to installing CloudStack, we'll start with
installing our base operating system, and then configuring that to act
as an NFS server for several types of storage. We'll install the
management server, download the systemVMs, and finally install the agent
software. Finally we'll spend a good deal of time configuring the entire
cloud in the CloudStack web interface.
</para>
</section>
<section id="sect-qig-Overview-prereqs">
<title>Prerequisites</title>
<para>
To complete this runbook you'll need the following items:
<orderedlist>
<listitem>
<para>
At least one computer which supports hardware virtualization.
</para>
</listitem>
<listitem>
<para>
The
<ulink url="http://mirror.stanford.edu/yum/pub/centos/6.4/isos/x86_64/CentOS-6.4-x86_64-minimal.iso">
CentOS 6.4 x86_64 minimal install CD
</ulink>
</para>
</listitem>
<listitem>
<para>
A /24 network with the gateway being at xxx.xxx.xxx.1, no DHCP should be on this network and
none of the computers running CloudStack will have a dynamic address. Again this is done for
the sake of simplicity.
</para>
</listitem>
</orderedlist>
</para>
</section>
</chapter>

View File

@ -0,0 +1,33 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "qig.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<preface id="pref-qig-Preface">
<title>Preface</title>
<xi:include href="Common_Content/Conventions.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Feedback.xml" xmlns:xi="http://www.w3.org/2001/XInclude"><xi:fallback xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include href="Common_Content/Feedback.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</xi:fallback>
</xi:include>
</preface>

View File

@ -0,0 +1,42 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "qig.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<appendix id="appe-qig-Revision_History">
<title>Revision History</title>
<simpara>
<revhistory>
<revision>
<revnumber>0-0</revnumber>
<date>Fri Jun 28 2013</date>
<revdescription>
<simplelist>
<member>Initial creation of book by publican</member>
</simplelist>
</revdescription>
</revision>
</revhistory>
</simpara>
</appendix>

177
docs/qig/en-US/config.xml Normal file
View File

@ -0,0 +1,177 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "qig.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<chapter id="chap-qig-Config">
<title>Configuration</title>
<para>
As we noted before we will be using security groups to provide isolation
and by default that implies that we'll be using a flat layer-2 network.
It also means that the simplicity of our setup means that we can use the
quick installer.
</para>
<section id="sect-qig-Config-UI_Access">
<title>UI Access</title>
<para>
To get access to CloudStack's web interface, merely point your
browser to http://<replaceable>172.16.10.</replaceable>2:8080/client
The default username is 'admin', and the default password is 'password'.
You should see a splash screen that allows you to choose several options
for setting up CloudStack. You should choose the
<option>Continue with Basic Setup</option> option.
</para>
<para>
You should now see a prompt requiring you to change the password for
the admin user. Please do so.
</para>
</section>
<section id="sect-qig-Config-Zone">
<title>Setting up a Zone</title>
<para>
A zone is the largest organization entity in CloudStack - and we'll be creating one, this
should be the screen that you see in front of you now. And for us there are 5 pieces of
information that we need.
<orderedlist>
<listitem>
<para>Name - we will set this to the ever-descriptive 'Zone1' for our cloud.</para>
</listitem>
<listitem>
<para>Public DNS 1 - we will set this to '8.8.8.8' for our cloud.</para>
</listitem>
<listitem>
<para>Public DNS 2 - we will set this to '8.8.4.4' for our cloud.</para>
</listitem>
<listitem>
<para>Internal DNS1 - we will also set this to '8.8.8.8' for our cloud.</para>
</listitem>
<listitem>
<para>Internal DNS2 - we will also set this to '8.8.8.4' for our cloud.</para>
</listitem>
</orderedlist>
</para>
<note>
<title>Notes about DNS settings</title>
<para>
CloudStack distinguishes between internal and public DNS. Internal
DNS is assumed to be capable of resolving internal-only
hostnames, such as your NFS servers DNS name. Public DNS is
provided to the guest VMs to resolve public IP addresses. You can
enter the same DNS server for both types, but if you do so, you
must make sure that both internal and public IP addresses can
route to the DNS server. In our specific case we will not use any
names for resources internally, and we have indeed them set to look
to the same external resource so as to not add a namerserver setup
to our list of requirements.
</para>
</note>
</section>
<section id="sect-qig-Config-Pod">
<title>Pod Configuration</title>
<para>Now that we've added a Zone, the next step that comes up is a prompt
for information regading a pod. Which is looking for 4 items.
<orderedlist>
<listitem>
<para>Name - We'll use Pod1 for our cloud.</para>
</listitem>
<listitem>
<para>Gateway - We'll use <replaceable>172.16.10</replaceable>.1 as our gateway</para>
</listitem>
<listitem>
<para>Netmask - We'll use 255.255.255.0</para>
</listitem>
<listitem>
<para>Start/end reserved system IPs - we will use 172.16.10.10-172.16.10.20 </para>
</listitem>
<listitem>
<para>Guest gateway - We'll use <replaceable>172.16.10</replaceable>.1</para>
</listitem>
<listitem>
<para>Guest netmask - We'll use 255.255.255.0</para>
</listitem>
<listitem>
<para>Guest start/end IP - We'll use <replaceable>172.16.10.</replaceable>30-<replaceable>172.16.10.</replaceable>200</para>
</listitem>
</orderedlist>
</para>
</section>
<section id="Runbook-config-cluster">
<title>Cluster</title>
<para> Now that we've added a Zone, we need only add a few more items for configuring the cluster.
<orderedlist>
<listitem>
<para>Name - We'll use Cluster1</para>
</listitem>
<listitem>
<para>Hypervisor - Choose KVM</para>
</listitem>
</orderedlist>
</para>
<para> You should be prompted to add the first host to your cluster at this point. Only a few bits of information are needed.
<orderedlist>
<listitem>
<para>Hostname - we'll use the IP address <replaceable>172.16.10.</replaceable>2 since we didn't set up a DNS server.</para>
</listitem>
<listitem>
<para>Username - we'll use 'root' </para>
</listitem>
<listitem>
<para>Password - enter the operating system password for the root user</para>
</listitem>
</orderedlist>
</para>
<section id="Runbook-config-cluster-pristorage">
<title>Primary Storage</title>
<para>With your cluster now setup - you should be prompted for primary storage information. Choose NFS as the storage type and then enter the following values in the fields:
<orderedlist>
<listitem>
<para>Name - We'll use 'Primary1'</para>
</listitem>
<listitem>
<para>Server - We'll be using the IP address <replaceable>172.16.10.</replaceable>2</para>
</listitem>
<listitem>
<para>Path - Well define /primary as the path we are using </para>
</listitem>
</orderedlist>
</para>
</section>
<section id="Runbook-config-cluster-secstorage">
<title>Secondary Storage</title>
<para> If this is a new zone, you'll be prompted for secondary storage information - populate it as follows:
<orderedlist>
<listitem>
<para>NFS server - We'll use the IP address <replaceable>172.16.10.</replaceable>2</para>
</listitem>
<listitem>
<para>Path - We'll use /secondary</para>
</listitem>
</orderedlist>
</para>
<para> Now, click Launch and your cloud should begin setup - it may take several minutes depending on your internet connection speed for setup to finalize.</para>
</section>
</section>
</chapter>

142
docs/qig/en-US/kvm.xml Normal file
View File

@ -0,0 +1,142 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "qig.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<chapter id="chap-qig-KVM">
<title>KVM Setup and installation</title>
<para>
KVM is the hypervisor we'll be using - we will recover the initial setup
which has already been done on the hypervisor host and cover installation
of the agent software, you can use the same steps to add additional KVM
nodes to your CloudStack environment.
</para>
<section id="sect-qig-KVM-Prerequisites">
<title>Prerequisites</title>
<para>
We explicitly are using the management server as a compute node as well,
which means that we have already performed many of the prerequisite steps
when setting up the management server, but we will list them here for
clarity. Those steps are:
<orderedlist>
<listitem>
<para>
<xref linkend="sect-qig-Environment-operatingsys-network" />
</para>
</listitem>
<listitem>
<para>
<xref linkend="sect-qig-Environment-operatingsys-hostname" />
</para>
</listitem>
<listitem>
<para>
<xref linkend="sect-qig-Environment-operatingsys-selinux" />
</para>
</listitem>
<listitem>
<para>
<xref linkend="sect-qig-Environment-operatingsys-ntp" />
</para>
</listitem>
<listitem>
<para>
<xref linkend="sect-qig-Environment-operatingsys-repoconfig" />
</para>
</listitem>
</orderedlist>
</para>
<para>
You shouldn't need to do that for the management server, of course, but
any additional hosts will need for you to complete the above steps.
</para>
</section>
<section id="sect-qig-KVM-Installation">
<title>Installation</title>
<para>Installation of the KVM agent is trivial with just a single command, but afterwards we'll need to configure a few things.</para>
<screen><prompt># </prompt><userinput><command>yum</command> -y install cloud-agent</userinput></screen>
<section id="sect-qig-KVM-Configuration">
<title>KVM Configuration</title>
<para>We have two different parts of KVM to configure, libvirt, and QEMU.</para>
<section id="sect-qig-KVM-Configuration-qemu">
<title>QEMU Configuration</title>
<para>
KVM configuration is relatively simple at only a single item. We need to
edit the QEMU VNC configuration. This is done by editing
<filename>/etc/libvirt/qemu.conf</filename> and ensuring the following
line is present and uncommented.
<screen>vnc_listen=0.0.0.0</screen>
</para>
</section>
<section id="sect-qig-KVM-Configuration-libvirt">
<title>Libvirt Configuration</title>
<para>
CloudStack uses libvirt for managing virtual machines. Therefore it
is vital that libvirt is configured correctly. Libvirt is a dependency
of cloud-agent and should already be installed.
</para>
<orderedlist>
<listitem>
<para>In order to have live migration working libvirt has to listen
for unsecured TCP connections. We also need to turn off libvirts
attempt to use Multicast DNS advertising. Both of these settings
are in <filename>/etc/libvirt/libvirtd.conf</filename>
</para>
<para>Set the following paramaters:</para>
<programlisting>listen_tls = 0</programlisting>
<programlisting>listen_tcp = 1</programlisting>
<programlisting>tcp_port = "16059"</programlisting>
<programlisting>auth_tcp = "none"</programlisting>
<programlisting>mdns_adv = 0</programlisting>
</listitem>
<listitem>
<para>Turning on "listen_tcp" in libvirtd.conf is not enough, we have to change the parameters as well:</para>
<para>On RHEL or CentOS modify <filename>/etc/sysconfig/libvirtd</filename>:</para>
<para>Uncomment the following line:</para>
<programlisting>#LIBVIRTD_ARGS="--listen"</programlisting>
<para>On Ubuntu: modify <filename>/etc/init/libvirt-bin.conf</filename></para>
<para>Change the following line (at the end of the file):</para>
<programlisting>exec /usr/sbin/libvirtd -d</programlisting>
<para>to (just add -l)</para>
<programlisting>exec /usr/sbin/libvirtd -d -l</programlisting>
</listitem>
<listitem>
<para>Restart libvirt</para>
<para>In RHEL or CentOS:</para>
<programlisting><command>$ service libvirtd restart</command></programlisting>
<para>In Ubuntu:</para>
<programlisting><command>$ service libvirt-bin restart</command></programlisting>
</listitem>
</orderedlist>
</section>
<section id="sect-qig-KVM-Configuration-finish">
<title>KVM configuration complete</title>
<para>
That concludes our installation and configuration of KVM, and we'll now move to using the CloudStack UI
for the actual configuration of our cloud.
</para>
</section>
</section>
</section>
</chapter>

22
docs/qig/en-US/qig.ent Normal file
View File

@ -0,0 +1,22 @@
<!-- 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.
-->
<!ENTITY PRODUCT "Apache CloudStack">
<!ENTITY BOOKID "Quick Install Guide">
<!ENTITY YEAR "2013">
<!ENTITY HOLDER "Apache Software Foundation">

36
docs/qig/en-US/qig.xml Normal file
View File

@ -0,0 +1,36 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "Runbook.ent">
%BOOK_ENTITIES;
]>
<!-- 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.
-->
<book>
<xi:include href="Book_Info.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Preface.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Overview.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Environment.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Management.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="kvm.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="config.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Revision_History.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<!-- <index /> -->
</book>

View File

@ -0,0 +1,26 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.engine.subsystem.api.storage;
public interface ChapInfo {
String getInitiatorUsername();
String getInitiatorSecret();
String getTargetUsername();
String getTargetSecret();
}

View File

@ -24,17 +24,11 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.command.CommandResult;
public interface DataStoreDriver {
void createAsync(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback);
void deleteAsync(DataObject data, AsyncCompletionCallback<CommandResult> callback);
void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
boolean canCopy(DataObject srcData, DataObject destData);
void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback);
DataTO getTO(DataObject data);
DataStoreTO getStoreTO(DataStore store);
void createAsync(DataStore store, DataObject data, AsyncCompletionCallback<CreateCmdResult> callback);
void deleteAsync(DataStore store, DataObject data, AsyncCompletionCallback<CommandResult> callback);
void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
boolean canCopy(DataObject srcData, DataObject destData);
void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback);
}

View File

@ -22,7 +22,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.command.CommandResult;
public interface PrimaryDataStoreDriver extends DataStoreDriver {
void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback);
void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback);
public ChapInfo getChapInfo(VolumeInfo volumeInfo);
public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback);
public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback);
}

View File

@ -20,6 +20,7 @@ package org.apache.cloudstack.engine.subsystem.api.storage;
import java.util.Map;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Storage.StoragePoolType;
public class PrimaryDataStoreParameters {
@ -30,12 +31,17 @@ public class PrimaryDataStoreParameters {
private Map<String, String> details;
private String tags;
private StoragePoolType type;
private HypervisorType hypervisorType;
private String host;
private String path;
private int port;
private String uuid;
private String name;
private String userInfo;
private long capacityBytes;
private long usedBytes;
private boolean managed;
private Long capacityIops;
/**
* @return the userInfo
@ -187,6 +193,30 @@ public class PrimaryDataStoreParameters {
this.providerName = providerName;
}
public void setManaged(boolean managed) {
this.managed = managed;
}
public boolean isManaged() {
return managed;
}
public void setCapacityIops(Long capacityIops) {
this.capacityIops = capacityIops;
}
public Long getCapacityIops() {
return capacityIops;
}
public void setHypervisorType(HypervisorType hypervisorType) {
this.hypervisorType = hypervisorType;
}
public HypervisorType getHypervisorType() {
return hypervisorType;
}
/**
* @return the clusterId
*/
@ -231,4 +261,24 @@ public class PrimaryDataStoreParameters {
public void setZoneId(Long zoneId) {
this.zoneId = zoneId;
}
public long getCapacityBytes()
{
return capacityBytes;
}
public void setCapacityBytes(long capacityBytes)
{
this.capacityBytes = capacityBytes;
}
public long getUsedBytes()
{
return usedBytes;
}
public void setUsedBytes(long usedBytes)
{
this.usedBytes = usedBytes;
}
}

View File

@ -42,6 +42,8 @@ public interface VolumeService {
}
}
ChapInfo getChapInfo(VolumeInfo volumeInfo, DataStore dataStore);
/**
* Creates the volume based on the given criteria
*

View File

@ -24,6 +24,14 @@ import com.cloud.agent.api.to.DiskTO;
public final class AttachCommand extends Command implements StorageSubSystemCommand {
private DiskTO disk;
private String vmName;
private String _storageHost;
private int _storagePort;
private boolean _managed;
private String _iScsiName;
private String _chapInitiatorUsername;
private String _chapInitiatorPassword;
private String _chapTargetUsername;
private String _chapTargetPassword;
public AttachCommand(DiskTO disk, String vmName) {
super();
@ -52,4 +60,67 @@ public final class AttachCommand extends Command implements StorageSubSystemComm
this.vmName = vmName;
}
public void setStorageHost(String storageHost) {
_storageHost = storageHost;
}
public String getStorageHost() {
return _storageHost;
}
public void setStoragePort(int storagePort) {
_storagePort = storagePort;
}
public int getStoragePort() {
return _storagePort;
}
public void setManaged(boolean managed) {
_managed = managed;
}
public boolean isManaged() {
return _managed;
}
public void set_iScsiName(String iScsiName) {
this._iScsiName = iScsiName;
}
public String get_iScsiName() {
return _iScsiName;
}
public void setChapInitiatorUsername(String chapInitiatorUsername) {
_chapInitiatorUsername = chapInitiatorUsername;
}
public String getChapInitiatorUsername() {
return _chapInitiatorUsername;
}
public void setChapInitiatorPassword(String chapInitiatorPassword) {
_chapInitiatorPassword = chapInitiatorPassword;
}
public String getChapInitiatorPassword() {
return _chapInitiatorPassword;
}
public void setChapTargetUsername(String chapTargetUsername) {
_chapTargetUsername = chapTargetUsername;
}
public String getChapTargetUsername() {
return _chapTargetUsername;
}
public void setChapTargetPassword(String chapTargetPassword) {
_chapTargetPassword = chapTargetPassword;
}
public String getChapTargetPassword() {
return _chapTargetPassword;
}
}

View File

@ -24,6 +24,8 @@ import com.cloud.agent.api.to.DiskTO;
public class DettachCommand extends Command implements StorageSubSystemCommand {
private DiskTO disk;
private String vmName;
private boolean _managed;
private String _iScsiName;
public DettachCommand(DiskTO disk, String vmName) {
super();
@ -52,4 +54,19 @@ public class DettachCommand extends Command implements StorageSubSystemCommand {
this.vmName = vmName;
}
public void setManaged(boolean managed) {
_managed = managed;
}
public boolean isManaged() {
return _managed;
}
public void set_iScsiName(String iScsiName) {
_iScsiName = iScsiName;
}
public String get_iScsiName() {
return _iScsiName;
}
}

View File

@ -103,6 +103,12 @@ public class StoragePoolVO implements StoragePool {
@Enumerated(value = EnumType.STRING)
private ScopeType scope;
@Column(name = "managed")
private boolean managed;
@Column(name = "capacity_iops", updatable = true, nullable = true)
private Long capacityIops;
@Column(name = "hypervisor")
@Enumerated(value = EnumType.STRING)
private HypervisorType hypervisor;
@ -201,8 +207,24 @@ public class StoragePoolVO implements StoragePool {
usedBytes = available;
}
public void setCapacityBytes(long capacity) {
capacityBytes = capacity;
public void setCapacityBytes(long capacityBytes) {
this.capacityBytes = capacityBytes;
}
public void setManaged(boolean managed) {
this.managed = managed;
}
public boolean isManaged() {
return managed;
}
public void setCapacityIops(Long capacityIops) {
this.capacityIops = capacityIops;
}
public Long getCapacityIops() {
return capacityIops;
}
public Long getClusterId() {

View File

@ -44,7 +44,6 @@ import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface VolumeManager extends VolumeApiService {
VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId,
Long destPoolClusterId, HypervisorType dataDiskHyperType)
throws ConcurrentOperationException;

View File

@ -197,4 +197,8 @@ public class VlanVO implements Vlan {
public void setIp6Range(String ip6Range) {
this.ip6Range = ip6Range;
}
public void setIpRange(String ipRange) {
this.ip6Range = ipRange;
}
}

View File

@ -17,9 +17,11 @@
package com.cloud.network.dao;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.net.Ip;
import java.sql.SQLException;
import java.util.List;
public interface IPAddressDao extends GenericDao<IPAddressVO, Long> {
@ -72,4 +74,8 @@ public interface IPAddressDao extends GenericDao<IPAddressVO, Long> {
IPAddressVO findByIpAndVlanId(String ipAddress, long vlanid);
long countFreeIpsInVlan(long vlanDbId);
boolean deletePublicIPRangeExceptAliasIP(long vlanDbId, String aliasIp) throws SQLException;
boolean deletePublicIPRange(long vlanDbId) throws SQLException;
}

View File

@ -40,6 +40,7 @@ import javax.ejb.Local;
import javax.inject.Inject;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
@ -364,6 +365,28 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
return customSearch(sc, null).get(0);
}
@Override
public boolean deletePublicIPRangeExceptAliasIP(long vlanDbId, String aliasIp) throws SQLException {
Transaction txn = Transaction.currentTxn();
String deleteSql = "DELETE FROM `cloud`.`user_ip_address` WHERE vlan_db_id = ? and public_ip_address!=?";
txn.start();
PreparedStatement stmt = txn.prepareAutoCloseStatement(deleteSql);
stmt.setLong(1, vlanDbId);
stmt.setString(2, aliasIp);
stmt.executeUpdate();
txn.commit();
return true;
}
@Override
public boolean deletePublicIPRange(long vlanDbId) throws SQLException{
SearchCriteria<IPAddressVO> sc = AllFieldsSearch.create();
sc.setParameters("vlan", vlanDbId);
remove(sc);
return true;
}
@Override
@DB
public boolean remove(Long id) {

View File

@ -208,6 +208,9 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
VpcNetworksCount = createSearchBuilder(Long.class);
VpcNetworksCount.and("vpcId", VpcNetworksCount.entity().getVpcId(), Op.EQ);
VpcNetworksCount.select(null, Func.COUNT, VpcNetworksCount.entity().getId());
SearchBuilder<NetworkOfferingVO> join9 = _ntwkOffDao.createSearchBuilder();
join9.and("isSystem", join9.entity().isSystemOnly(), Op.EQ);
VpcNetworksCount.join("offerings", join9, VpcNetworksCount.entity().getNetworkOfferingId(), join9.entity().getId(), JoinBuilder.JoinType.INNER);
VpcNetworksCount.done();
OfferingAccountNetworkSearch = createSearchBuilder();
@ -587,6 +590,8 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long> implements N
public long countVpcNetworks(long vpcId) {
SearchCriteria<Long> sc = VpcNetworksCount.create();
sc.setParameters("vpcId", vpcId);
//offering shouldn't be system (the one used by the private gateway)
sc.setJoinParameters("offerings", "isSystem", false);
return customSearch(sc, null).get(0);
}

View File

@ -94,6 +94,15 @@ public class DiskOfferingVO implements DiskOffering {
@Column(name = "uuid")
private String uuid;
@Column(name="customized_iops")
private Boolean customizedIops;
@Column(name="min_iops")
Long minIops;
@Column(name="max_iops")
Long maxIops;
@Column(name = "sort_key")
int sortKey;
@ -116,8 +125,8 @@ public class DiskOfferingVO implements DiskOffering {
this.uuid = UUID.randomUUID().toString();
}
public DiskOfferingVO(Long domainId, String name, String displayText, long diskSize, String tags,
boolean isCustomized) {
public DiskOfferingVO(Long domainId, String name, String displayText, long diskSize, String tags, boolean isCustomized,
Boolean isCustomizedIops, Long minIops, Long maxIops) {
this.domainId = domainId;
this.name = name;
this.displayText = displayText;
@ -128,6 +137,9 @@ public class DiskOfferingVO implements DiskOffering {
this.useLocalStorage = false;
this.customized = isCustomized;
this.uuid = UUID.randomUUID().toString();
this.customizedIops = isCustomizedIops;
this.minIops = minIops;
this.maxIops = maxIops;
}
public DiskOfferingVO(String name, String displayText, boolean mirrored, String tags, boolean recreatable,
@ -175,6 +187,36 @@ public class DiskOfferingVO implements DiskOffering {
}
@Override
public Boolean isCustomizedIops() {
return customizedIops;
}
@Override
public void setCustomizedIops(Boolean customizedIops) {
this.customizedIops = customizedIops;
}
@Override
public Long getMinIops() {
return minIops;
}
@Override
public void setMinIops(Long minIops) {
this.minIops = minIops;
}
@Override
public Long getMaxIops() {
return maxIops;
}
@Override
public void setMaxIops(Long maxIops) {
this.maxIops = maxIops;
}
@Override
public String getUniqueName() {
return uniqueName;
}

View File

@ -70,6 +70,12 @@ public class VolumeVO implements Volume {
@Column(name = "size")
Long size;
@Column(name = "min_iops")
Long minIops;
@Column(name = "max_iops")
Long maxIops;
@Column(name = "folder")
String folder;
@ -141,25 +147,32 @@ public class VolumeVO implements Volume {
@Column(name = "display_volume", updatable = true, nullable = false)
protected boolean displayVolume;
@Column(name = "iscsi_name")
private String _iScsiName;
@Transient
// @Column(name="reservation")
String reservationId;
// Real Constructor
public VolumeVO(Type type, String name, long dcId, long domainId, long accountId, long diskOfferingId, long size) {
public VolumeVO(Type type, String name, long dcId, long domainId, long accountId, long diskOfferingId, long size,
Long minIops, Long maxIops, String iScsiName) {
this.volumeType = type;
this.name = name;
this.dataCenterId = dcId;
this.accountId = accountId;
this.domainId = domainId;
this.size = size;
this.minIops = minIops;
this.maxIops = maxIops;
this._iScsiName = iScsiName;
this.diskOfferingId = diskOfferingId;
this.state = State.Allocated;
this.uuid = UUID.randomUUID().toString();
}
public VolumeVO(String name, Long dcId, Long podId, long accountId, long domainId, Long instanceId, String folder,
String path, long size, Volume.Type vType) {
public VolumeVO(String name, long dcId, long podId, long accountId, long domainId, Long instanceId, String folder, String path,
long size, Long minIops, Long maxIops, String iScsiName, Volume.Type vType) {
this.name = name;
this.accountId = accountId;
this.domainId = domainId;
@ -167,6 +180,9 @@ public class VolumeVO implements Volume {
this.folder = folder;
this.path = path;
this.size = size;
this.minIops = minIops;
this.maxIops = maxIops;
this._iScsiName = iScsiName;
this.podId = podId;
this.dataCenterId = dcId;
this.volumeType = vType;
@ -177,11 +193,15 @@ public class VolumeVO implements Volume {
// Copy Constructor
public VolumeVO(Volume that) {
this(that.getName(), that.getDataCenterId(), that.getPodId(), that.getAccountId(), that.getDomainId(), that
.getInstanceId(), that.getFolder(), that.getPath(), that.getSize(), that.getVolumeType());
this(that.getName(), that.getDataCenterId(), that.getPodId(), that.getAccountId(), that.getDomainId(), that.getInstanceId(),
that.getFolder(), that.getPath(), that.getSize(), that.getMinIops(), that.getMaxIops(),
that.get_iScsiName(), that.getVolumeType());
this.recreatable = that.isRecreatable();
this.state = that.getState();
this.size = that.getSize();
this.minIops = that.getMinIops();
this.maxIops = that.getMaxIops();
this._iScsiName = that.get_iScsiName();
this.diskOfferingId = that.getDiskOfferingId();
this.poolId = that.getPoolId();
this.attached = that.getAttached();
@ -274,6 +294,24 @@ public class VolumeVO implements Volume {
this.size = size;
}
@Override
public Long getMinIops() {
return minIops;
}
public void setMinIops(Long minIops) {
this.minIops = minIops;
}
@Override
public Long getMaxIops() {
return maxIops;
}
public void setMaxIops(Long maxIops) {
this.maxIops = maxIops;
}
@Override
public Long getInstanceId() {
return instanceId;
@ -464,6 +502,15 @@ public class VolumeVO implements Volume {
this.uuid = uuid;
}
@Override
public String get_iScsiName() {
return this._iScsiName;
}
public void set_iScsiName(String iScsiName) {
this._iScsiName = iScsiName;
}
public boolean isDisplayVolume() {
return displayVolume;
}

View File

@ -28,8 +28,6 @@ import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -56,9 +54,7 @@ import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.UpdateBuilder;
import com.cloud.utils.exception.CloudRuntimeException;
@Component
@ -102,7 +98,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
private SearchBuilder<VMTemplateVO> PublicIsoSearch;
private SearchBuilder<VMTemplateVO> UserIsoSearch;
private GenericSearchBuilder<VMTemplateVO, Long> CountTemplatesByAccount;
// private SearchBuilder<VMTemplateVO> updateStateSearch;
// private SearchBuilder<VMTemplateVO> updateStateSearch;
@Inject
ResourceTagDao _tagsDao;
@ -344,6 +340,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
AccountIdSearch = createSearchBuilder();
AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AccountIdSearch.and("publicTemplate", AccountIdSearch.entity().isPublicTemplate(), SearchCriteria.Op.EQ);
AccountIdSearch.and("removed", AccountIdSearch.entity().getRemoved(), SearchCriteria.Op.NULL); // only list not removed templates for this account
AccountIdSearch.done();
SearchBuilder<VMTemplateZoneVO> tmpltZoneSearch = _templateZoneDao.createSearchBuilder();
@ -369,11 +366,11 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
CountTemplatesByAccount.and("removed", CountTemplatesByAccount.entity().getRemoved(), SearchCriteria.Op.NULL);
CountTemplatesByAccount.done();
// updateStateSearch = this.createSearchBuilder();
// updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ);
// updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ);
// updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ);
// updateStateSearch.done();
// updateStateSearch = this.createSearchBuilder();
// updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ);
// updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ);
// updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ);
// updateStateSearch.done();
return result;
}

View File

@ -58,6 +58,8 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long>, StateDao<Volume.S
List<VolumeVO> findByPoolId(long poolId);
List<VolumeVO> findByPoolId(long poolId, Volume.Type volumeType);
List<VolumeVO> findByInstanceAndDeviceId(long instanceId, long deviceId);
List<VolumeVO> findUsableVolumesForInstance(long instanceId);

View File

@ -109,6 +109,19 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
sc.setParameters("poolId", poolId);
sc.setParameters("notDestroyed", Volume.State.Destroy);
sc.setParameters("vType", Volume.Type.ROOT.toString());
return listBy(sc);
}
@Override
public List<VolumeVO> findByPoolId(long poolId, Volume.Type volumeType) {
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
sc.setParameters("poolId", poolId);
sc.setParameters("notDestroyed", Volume.State.Destroy);
if (volumeType != null) {
sc.setParameters("vType", volumeType.toString());
}
return listBy(sc);
}

View File

@ -462,7 +462,7 @@ public class Upgrade2214to30 extends Upgrade30xBase implements DbUpgrade {
ResultSet rs = null;
try {
int numRows = 0;
pstmt = conn.prepareStatement("select count(id) from `cloud`.`vm_instance` where removed is null");
pstmt = conn.prepareStatement("select count(id) from `cloud`.`vm_instance`");
rs = pstmt.executeQuery();
if(rs.next()){
numRows = rs.getInt(1);
@ -471,7 +471,7 @@ public class Upgrade2214to30 extends Upgrade30xBase implements DbUpgrade {
pstmt.close();
int offset = 0;
while(offset < numRows){
pstmt = conn.prepareStatement("select id, vnc_password from `cloud`.`vm_instance` where removed is null limit "+offset+", 500");
pstmt = conn.prepareStatement("select id, vnc_password from `cloud`.`vm_instance` limit "+offset+", 500");
rs = pstmt.executeQuery();
while (rs.next()) {
long id = rs.getLong(1);

View File

@ -147,7 +147,7 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager {
object = cacheReplacementAlgorithm.chooseOneToBeReplaced(store);
findAStore = store;
if (object != null) {
break;
break;
}
}
@ -230,6 +230,12 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager {
@Override
public DataObject createCacheObject(DataObject data, Scope scope) {
DataStore cacheStore = this.getCacheStorage(scope);
if (cacheStore == null)
{
String errMsg = "No cache DataStore in scope id " + scope.getScopeId() + " type " + scope.getScopeType().toString();
throw new CloudRuntimeException(errMsg);
}
return this.createCacheObject(data, cacheStore);
}

View File

@ -35,6 +35,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
@ -57,6 +58,7 @@ import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.host.Host;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
@ -135,6 +137,22 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
if (destStoreTO instanceof NfsTO || destStoreTO.getRole() == DataStoreRole.ImageCache) {
return false;
}
if (srcData.getType() == DataObjectType.TEMPLATE) {
TemplateInfo template = (TemplateInfo)srcData;
if (template.getHypervisorType() == HypervisorType.Hyperv) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("needCacheStorage false due to src TemplateInfo, which is DataObjectType.TEMPLATE of HypervisorType.Hyperv");
}
return false;
}
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("needCacheStorage true, dest at " +
destTO.getPath() + " dest role " + destStoreTO.getRole().toString() +
srcTO.getPath() + " src role " + srcStoreTO.getRole().toString() );
}
return true;
}
@ -157,26 +175,24 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
int _primaryStorageDownloadWait = NumbersUtil.parseInt(value,
Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
Answer answer = null;
boolean usingCache = false;
DataObject cacheData = null;
DataObject srcForCopy = srcData;
try {
if (needCacheStorage(srcData, destData)) {
// need to copy it to image cache store
Scope destScope = getZoneScope(destData.getDataStore().getScope());
cacheData = cacheMgr.createCacheObject(srcData, destScope);
CopyCommand cmd = new CopyCommand(cacheData.getTO(), destData.getTO(), _primaryStorageDownloadWait);
EndPoint ep = selector.select(cacheData, destData);
answer = ep.sendMessage(cmd);
} else {
// handle copy it to/from cache store
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _primaryStorageDownloadWait);
EndPoint ep = selector.select(srcData, destData);
answer = ep.sendMessage(cmd);
srcForCopy = cacheData = cacheMgr.createCacheObject(srcData, destScope);
}
CopyCommand cmd = new CopyCommand(srcForCopy.getTO(), destData.getTO(), _primaryStorageDownloadWait);
EndPoint ep = selector.select(srcForCopy, destData);
answer = ep.sendMessage(cmd);
if (cacheData != null) {
if (answer == null || !answer.getResult()) {
cacheMgr.deleteCacheObject(cacheData);
cacheMgr.deleteCacheObject(srcForCopy);
} else {
cacheMgr.releaseCacheObject(cacheData);
cacheMgr.releaseCacheObject(srcForCopy);
}
}
return answer;
@ -187,7 +203,6 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
}
throw new CloudRuntimeException(e.toString());
}
}
protected DataObject cacheSnapshotChain(SnapshotInfo snapshot) {
@ -204,10 +219,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
}
protected void deleteSnapshotCacheChain(SnapshotInfo snapshot) {
while (snapshot != null) {
cacheMgr.deleteCacheObject(snapshot);
snapshot = snapshot.getParent();
}
while (snapshot != null) {
cacheMgr.deleteCacheObject(snapshot);
snapshot = snapshot.getParent();
}
}
protected Answer copyVolumeFromSnapshot(DataObject snapObj, DataObject volObj) {
@ -317,6 +332,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
Answer answer = null;
String errMsg = null;
try {
s_logger.debug("copyAsync inspecting src type " + srcData.getType().toString() +
" copyAsync inspecting dest type " + destData.getType().toString());
if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.VOLUME) {
answer = copyVolumeFromSnapshot(srcData, destData);
@ -404,7 +421,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
@Override
public Void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost,
AsyncCompletionCallback<CopyCommandResult> callback) {
AsyncCompletionCallback<CopyCommandResult> callback) {
CopyCommandResult result = new CopyCommandResult(null, null);
result.setResult("Unsupported operation requested for copying data.");
callback.complete(result);

View File

@ -18,11 +18,9 @@
*/
package org.apache.cloudstack.storage.motion;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.host.Host;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
@ -32,9 +30,9 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.springframework.stereotype.Component;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.host.Host;
import com.cloud.utils.exception.CloudRuntimeException;
import javax.inject.Inject;
import java.util.List;
import java.util.Map;
@Component
public class DataMotionServiceImpl implements DataMotionService {
@ -72,4 +70,8 @@ public class DataMotionServiceImpl implements DataMotionService {
}
throw new CloudRuntimeException("can't find strategy to move data");
}
public void setStrategies(List<DataMotionStrategy> strategies) {
this.strategies = strategies;
}
}

View File

@ -40,16 +40,14 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.framework.async.AsyncRpcContext;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.DeleteCommand;
import org.apache.cloudstack.storage.datastore.DataObjectManager;
@ -84,7 +82,6 @@ import com.cloud.template.TemplateManager;
import com.cloud.user.AccountManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.utils.UriUtils;
import com.cloud.utils.fsm.NoTransitionException;
@Component
public class TemplateServiceImpl implements TemplateService {
@ -122,7 +119,7 @@ public class TemplateServiceImpl implements TemplateService {
@Inject
TemplateManager _tmpltMgr;
class TemplateOpContext<T> extends AsyncRpcConext<T> {
class TemplateOpContext<T> extends AsyncRpcContext<T> {
final TemplateObject template;
final AsyncCallFuture<TemplateApiResult> future;
@ -166,7 +163,7 @@ public class TemplateServiceImpl implements TemplateService {
AsyncCallbackDispatcher<TemplateServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context);
store.getDriver().createAsync(templateOnStore, caller);
store.getDriver().createAsync(store, templateOnStore, caller);
}
@Override
@ -511,7 +508,7 @@ public class TemplateServiceImpl implements TemplateService {
TemplateOpContext<TemplateApiResult> context = new TemplateOpContext<TemplateApiResult>(null, to, future);
AsyncCallbackDispatcher<TemplateServiceImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().deleteTemplateCallback(null, null)).setContext(context);
to.getDataStore().getDriver().deleteAsync(to, caller);
to.getDataStore().getDriver().deleteAsync(to.getDataStore(), to, caller);
return future;
}

View File

@ -145,7 +145,7 @@ public class ImageStoreImpl implements ImageStoreEntity {
@Override
public boolean delete(DataObject obj) {
AsyncCallFuture<CommandResult> future = new AsyncCallFuture<CommandResult>();
this.driver.deleteAsync(obj, future);
this.driver.deleteAsync(obj.getDataStore(), obj, future);
try {
future.get();
} catch (InterruptedException e) {

View File

@ -148,7 +148,8 @@ public class StorageAllocatorTest {
diskOffering = diskOfferingDao.persist(diskOffering);
diskOfferingId = diskOffering.getId();
volume = new VolumeVO(Volume.Type.ROOT, "volume", dcId, 1, 1, diskOffering.getId(), diskOffering.getDiskSize());
volume = new VolumeVO(Volume.Type.ROOT, "volume", dcId, 1, 1, diskOffering.getId(), diskOffering.getDiskSize(),
diskOffering.getMinIops(), diskOffering.getMaxIops(), "");
volume = volumeDao.persist(volume);
volumeId = volume.getId();
}

View File

@ -347,7 +347,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
private VolumeVO createVolume(Long templateId, long dataStoreId) {
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000);
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000, 0L, 0L, "");
volume.setDataCenterId(this.dcId);
volume.setPoolId(dataStoreId);
volume = volumeDao.persist(volume);

View File

@ -317,7 +317,7 @@ public class VolumeTest extends CloudStackTestNGBase {
}
private VolumeVO createVolume(Long templateId, long dataStoreId) {
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000);
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000, 0L, 0L, "");
;
volume.setPoolId(dataStoreId);
volume = volumeDao.persist(volume);

View File

@ -317,7 +317,7 @@ public class VolumeTestVmware extends CloudStackTestNGBase {
}
private VolumeVO createVolume(Long templateId, long dataStoreId) {
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000);
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000, 0L, 0L, "");
;
volume.setPoolId(dataStoreId);
volume = volumeDao.persist(volume);

View File

@ -363,7 +363,7 @@ public class volumeServiceTest extends CloudStackTestNGBase {
}
private VolumeVO createVolume(Long templateId, long dataStoreId) {
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000);
VolumeVO volume = new VolumeVO(Volume.Type.DATADISK, UUID.randomUUID().toString(), this.dcId, 1L, 1L, 1L, 1000, 0L, 0L, "");
volume.setPoolId(dataStoreId);
volume = volumeDao.persist(volume);
return volume;

View File

@ -125,11 +125,6 @@
<property name="name" value="Bare Metal Agent"/>
</bean>
<bean id="HypervServerDiscoverer" class="com.cloud.hypervisor.hyperv.HypervServerDiscoverer">
<property name="name" value="SCVMMServer"/>
</bean>
<bean id="FirstFitPlanner" class="com.cloud.deploy.FirstFitPlanner">
<property name="name" value="First Fit"/>
</bean>
@ -188,10 +183,6 @@
<property name="name" value="BareMetalGuru"/>
</bean>
<bean id="HypervGuru" class="com.cloud.hypervisor.guru.HypervGuru">
<property name="name" value="HypervGuru"/>
</bean>
<!--
DAO with customized configuration
-->

View File

@ -81,7 +81,8 @@
<bean id="ClassicalPrimaryDataStoreProvider" class="org.apache.cloudstack.storage.datastore.provider.CloudStackPrimaryDataStoreProviderImpl" />
<bean id="cloudStackImageStoreProviderImpl" class="org.apache.cloudstack.storage.datastore.provider.CloudStackImageStoreProviderImpl" />
<bean id="s3ImageStoreProviderImpl" class="org.apache.cloudstack.storage.datastore.provider.S3ImageStoreProviderImpl" />
<bean id="swiftImageStoreProviderImpl" class="org.apache.cloudstack.storage.datastore.provider.SwiftImageStoreProviderImpl" />
<bean id="swiftImageStoreProviderImpl" class="org.apache.cloudstack.storage.datastore.provider.SwiftImageStoreProviderImpl" />
<bean id="simulatorImageStoreProviderImpl" class="org.apache.cloudstack.storage.datastore.provider.SimulatorImageStoreProviderImpl" />
<bean id="BAREMETAL" class="org.apache.cloudstack.storage.image.format.BAREMETAL" />
<bean id="storagePoolAutomationImpl" class="com.cloud.storage.StoragePoolAutomationImpl" />
<bean id="AccountGuestVlanMapDaoImpl" class="com.cloud.network.dao.AccountGuestVlanMapDaoImpl" />

View File

@ -33,7 +33,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
import org.apache.cloudstack.framework.async.AsyncCallFuture;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.framework.async.AsyncRpcContext;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
@ -79,7 +79,7 @@ public class SnapshotServiceImpl implements SnapshotService {
@Inject
VMSnapshotDao _vmSnapshotDao;
static private class CreateSnapshotContext<T> extends AsyncRpcConext<T> {
static private class CreateSnapshotContext<T> extends AsyncRpcContext<T> {
final SnapshotInfo snapshot;
final AsyncCallFuture<SnapshotResult> future;
@ -91,7 +91,7 @@ public class SnapshotServiceImpl implements SnapshotService {
}
}
static private class DeleteSnapshotContext<T> extends AsyncRpcConext<T> {
static private class DeleteSnapshotContext<T> extends AsyncRpcContext<T> {
final SnapshotInfo snapshot;
final AsyncCallFuture<SnapshotResult> future;
@ -104,7 +104,7 @@ public class SnapshotServiceImpl implements SnapshotService {
}
static private class CopySnapshotContext<T> extends AsyncRpcConext<T> {
static private class CopySnapshotContext<T> extends AsyncRpcContext<T> {
final SnapshotInfo srcSnapshot;
final SnapshotInfo destSnapshot;
final AsyncCallFuture<SnapshotResult> future;
@ -355,7 +355,7 @@ public class SnapshotServiceImpl implements SnapshotService {
AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().deleteSnapshotCallback(null, null)).setContext(context);
DataStore store = snapInfo.getDataStore();
store.getDriver().deleteAsync(snapInfo, caller);
store.getDriver().deleteAsync(store, snapInfo, caller);
SnapshotResult result = null;
try {

View File

@ -49,7 +49,9 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator {
Volume volume = _volumeDao.findById(dskCh.getVolumeId());
List<Volume> requestVolumes = new ArrayList<Volume>();
requestVolumes.add(volume);
return storageMgr.storagePoolHasEnoughSpace(requestVolumes, pool);
return storageMgr.storagePoolHasEnoughIops(requestVolumes, pool) &&
storageMgr.storagePoolHasEnoughSpace(requestVolumes, pool);
}
@Override
@ -57,18 +59,27 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator {
DeploymentPlan plan, ExcludeList avoid, int returnUpTo) {
s_logger.debug("ZoneWideStoragePoolAllocator to find storage pool");
List<StoragePool> suitablePools = new ArrayList<StoragePool>();
HypervisorType hypervisor = dskCh.getHypervisorType();
if (hypervisor != null) {
if (hypervisor != HypervisorType.KVM && hypervisor != HypervisorType.VMware) {
s_logger.debug("Only kvm, VMware hypervisors are enabled to support zone wide storage");
return suitablePools;
List<StoragePoolVO> storagePools = _storagePoolDao.findZoneWideStoragePoolsByTags(plan.getDataCenterId(), dskCh.getTags());
if (storagePools == null) {
storagePools = new ArrayList<StoragePoolVO>();
}
List<StoragePoolVO> anyHypervisorStoragePools = new ArrayList<StoragePoolVO>();
for (StoragePoolVO storagePool : storagePools) {
if (HypervisorType.Any.equals(storagePool.getHypervisor())) {
anyHypervisorStoragePools.add(storagePool);
}
}
List<StoragePoolVO> storagePools = _storagePoolDao.findZoneWideStoragePoolsByTags(plan.getDataCenterId(), dskCh.getTags());
List<StoragePoolVO> storagePoolsByHypervisor = _storagePoolDao.findZoneWideStoragePoolsByHypervisor(plan.getDataCenterId(), dskCh.getHypervisorType());
storagePools.retainAll(storagePoolsByHypervisor);
storagePools.addAll(anyHypervisorStoragePools);
// add remaining pools in zone, that did not match tags, to avoid set
List<StoragePoolVO> allPools = _storagePoolDao.findZoneWideStoragePoolsByTags(plan.getDataCenterId(), null);
allPools.removeAll(storagePools);

View File

@ -30,7 +30,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.framework.async.AsyncRpcContext;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@ -78,7 +78,7 @@ public class DataObjectManagerImpl implements DataObjectManager {
return objectInDataStoreMgr.get(dataObj, dataStore);
}
class CreateContext<T> extends AsyncRpcConext<T> {
class CreateContext<T> extends AsyncRpcContext<T> {
final DataObject objInStrore;
public CreateContext(AsyncCompletionCallback<T> callback, DataObject objInStore) {
@ -162,7 +162,7 @@ public class DataObjectManagerImpl implements DataObjectManager {
AsyncCallbackDispatcher<DataObjectManagerImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().createAsynCallback(null, null)).setContext(context);
store.getDriver().createAsync(objInStore, caller);
store.getDriver().createAsync(store, objInStore, caller);
return;
}
@ -205,7 +205,7 @@ public class DataObjectManagerImpl implements DataObjectManager {
return null;
}
class CopyContext<T> extends AsyncRpcConext<T> {
class CopyContext<T> extends AsyncRpcContext<T> {
DataObject destObj;
DataObject srcObj;
@ -293,7 +293,7 @@ public class DataObjectManagerImpl implements DataObjectManager {
return null;
}
class DeleteContext<T> extends AsyncRpcConext<T> {
class DeleteContext<T> extends AsyncRpcContext<T> {
private final DataObject obj;
public DeleteContext(AsyncCompletionCallback<T> callback, DataObject obj) {
@ -321,7 +321,7 @@ public class DataObjectManagerImpl implements DataObjectManager {
AsyncCallbackDispatcher<DataObjectManagerImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().deleteAsynCallback(null, null)).setContext(context);
data.getDataStore().getDriver().deleteAsync(data, caller);
data.getDataStore().getDriver().deleteAsync(data.getDataStore(), data, caller);
return;
}

View File

@ -18,11 +18,9 @@
*/
package org.apache.cloudstack.storage.datastore;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import com.cloud.storage.DataStoreRole;
import com.cloud.utils.exception.CloudRuntimeException;
import edu.emory.mathcs.backport.java.util.Collections;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
@ -30,22 +28,20 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager;
import org.springframework.stereotype.Component;
import com.cloud.storage.DataStoreRole;
import com.cloud.utils.exception.CloudRuntimeException;
import edu.emory.mathcs.backport.java.util.Collections;
import javax.inject.Inject;
import java.util.List;
@Component
public class DataStoreManagerImpl implements DataStoreManager {
@Inject
PrimaryDataStoreProviderManager primaryStorMgr;
PrimaryDataStoreProviderManager primaryStoreMgr;
@Inject
ImageStoreProviderManager imageDataStoreMgr;
@Override
public DataStore getDataStore(long storeId, DataStoreRole role) {
if (role == DataStoreRole.Primary) {
return primaryStorMgr.getPrimaryDataStore(storeId);
return primaryStoreMgr.getPrimaryDataStore(storeId);
} else if (role == DataStoreRole.Image) {
return imageDataStoreMgr.getImageStore(storeId);
} else if (role == DataStoreRole.ImageCache) {
@ -57,7 +53,7 @@ public class DataStoreManagerImpl implements DataStoreManager {
@Override
public DataStore getDataStore(String uuid, DataStoreRole role) {
if (role == DataStoreRole.Primary) {
return primaryStorMgr.getPrimaryDataStore(uuid);
return primaryStoreMgr.getPrimaryDataStore(uuid);
} else if (role == DataStoreRole.Image) {
return imageDataStoreMgr.getImageStore(uuid);
}
@ -81,7 +77,7 @@ public class DataStoreManagerImpl implements DataStoreManager {
@Override
public DataStore getPrimaryDataStore(long storeId) {
return primaryStorMgr.getPrimaryDataStore(storeId);
return primaryStoreMgr.getPrimaryDataStore(storeId);
}
@Override
@ -94,4 +90,11 @@ public class DataStoreManagerImpl implements DataStoreManager {
return imageDataStoreMgr.listImageStores();
}
public void setPrimaryStoreMgr(PrimaryDataStoreProviderManager primaryStoreMgr) {
this.primaryStoreMgr = primaryStoreMgr;
}
public void setImageDataStoreMgr(ImageStoreProviderManager imageDataStoreMgr) {
this.imageDataStoreMgr = imageDataStoreMgr;
}
}

View File

@ -175,6 +175,12 @@ public class PrimaryDataStoreEntityImpl implements StorageEntity {
return 0;
}
@Override
public Long getCapacityIops() {
// TODO Auto-generated method stub
return 0L;
}
@Override
public Long getClusterId() {
// TODO Auto-generated method stub

View File

@ -18,15 +18,8 @@
*/
package org.apache.cloudstack.storage.datastore.provider;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.utils.component.ManagerBase;
import org.apache.cloudstack.api.response.StorageProviderResponse;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider.DataStoreProviderType;
@ -38,8 +31,13 @@ import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.utils.component.ManagerBase;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Component
public class DataStoreProviderManagerImpl extends ManagerBase implements DataStoreProviderManager {
@ -50,7 +48,7 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto
@Inject
PrimaryDataStoreProviderManager primaryDataStoreProviderMgr;
@Inject
ImageStoreProviderManager imageDataStoreProviderMgr;
ImageStoreProviderManager imageStoreProviderMgr;
@Override
public DataStoreProvider getDataStoreProvider(String name) {
@ -125,7 +123,7 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto
(PrimaryDataStoreDriver) provider.getDataStoreDriver());
primaryDataStoreProviderMgr.registerHostListener(provider.getName(), provider.getHostListener());
} else if (types.contains(DataStoreProviderType.IMAGE)) {
imageDataStoreProviderMgr.registerDriver(provider.getName(),
imageStoreProviderMgr.registerDriver(provider.getName(),
(ImageStoreDriver) provider.getDataStoreDriver());
}
} catch (Exception e) {
@ -168,4 +166,16 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto
throw new InvalidParameterValueException("Invalid parameter: " + type);
}
}
public void setProviders(List<DataStoreProvider> providers) {
this.providers = providers;
}
public void setPrimaryDataStoreProviderMgr(PrimaryDataStoreProviderManager primaryDataStoreProviderMgr) {
this.primaryDataStoreProviderMgr = primaryDataStoreProviderMgr;
}
public void setImageStoreProviderMgr(ImageStoreProviderManager imageDataStoreProviderMgr) {
this.imageStoreProviderMgr = imageDataStoreProviderMgr;
}
}

View File

@ -18,28 +18,6 @@
*/
package org.apache.cloudstack.storage.image;
import java.util.Date;
import java.util.Set;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.DeleteCommand;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
import org.apache.cloudstack.storage.image.ImageStoreDriver;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.DownloadAnswer;
import com.cloud.agent.api.to.DataObjectType;
@ -50,11 +28,30 @@ import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.download.DownloadMonitor;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcContext;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.DeleteCommand;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
import org.apache.log4j.Logger;
import javax.inject.Inject;
import java.util.Date;
public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
private static final Logger s_logger = Logger.getLogger(BaseImageStoreDriverImpl.class);
@Inject
VMTemplateDao templateDao;
VMTemplateDao _templateDao;
@Inject
DownloadMonitor _downloadMonitor;
@Inject
@ -71,7 +68,7 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
return null;
}
class CreateContext<T> extends AsyncRpcConext<T> {
protected class CreateContext<T> extends AsyncRpcContext<T> {
final DataObject data;
public CreateContext(AsyncCompletionCallback<T> callback, DataObject data) {
@ -81,7 +78,7 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
}
@Override
public void createAsync(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback) {
public void createAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback<CreateCmdResult> callback) {
CreateContext<CreateCmdResult> context = new CreateContext<CreateCmdResult>(callback, data);
AsyncCallbackDispatcher<BaseImageStoreDriverImpl, DownloadAnswer> caller = AsyncCallbackDispatcher
.create(this);
@ -95,7 +92,7 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
}
}
protected Void createTemplateAsyncCallback(AsyncCallbackDispatcher<BaseImageStoreDriverImpl, DownloadAnswer> callback,
protected Void createTemplateAsyncCallback(AsyncCallbackDispatcher<? extends BaseImageStoreDriverImpl, DownloadAnswer> callback,
CreateContext<CreateCmdResult> context) {
DownloadAnswer answer = callback.getResult();
DataObject obj = context.data;
@ -115,9 +112,9 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
_templateStoreDao.update(tmpltStoreVO.getId(), updateBuilder);
// update size in vm_template table
VMTemplateVO tmlptUpdater = templateDao.createForUpdate();
VMTemplateVO tmlptUpdater = _templateDao.createForUpdate();
tmlptUpdater.setSize(answer.getTemplateSize());
templateDao.update(obj.getId(), tmlptUpdater);
_templateDao.update(obj.getId(), tmlptUpdater);
}
AsyncCompletionCallback<CreateCmdResult> caller = context.getParentCallback();
@ -131,9 +128,9 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
caller.complete(result);
} else if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
if (answer.getCheckSum() != null) {
VMTemplateVO templateDaoBuilder = templateDao.createForUpdate();
VMTemplateVO templateDaoBuilder = _templateDao.createForUpdate();
templateDaoBuilder.setChecksum(answer.getCheckSum());
templateDao.update(obj.getId(), templateDaoBuilder);
_templateDao.update(obj.getId(), templateDaoBuilder);
}
CreateCmdResult result = new CreateCmdResult(null, null);
@ -142,7 +139,7 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
return null;
}
protected Void createVolumeAsyncCallback(AsyncCallbackDispatcher<BaseImageStoreDriverImpl, DownloadAnswer> callback,
protected Void createVolumeAsyncCallback(AsyncCallbackDispatcher<? extends BaseImageStoreDriverImpl, DownloadAnswer> callback,
CreateContext<CreateCmdResult> context) {
DownloadAnswer answer = callback.getResult();
DataObject obj = context.data;
@ -184,7 +181,7 @@ public abstract class BaseImageStoreDriverImpl implements ImageStoreDriver {
}
@Override
public void deleteAsync(DataObject data, AsyncCompletionCallback<CommandResult> callback) {
public void deleteAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback<CommandResult> callback) {
DeleteCommand cmd = new DeleteCommand(data.getTO());
CommandResult result = new CommandResult();

View File

@ -79,6 +79,11 @@ public class PrimaryDataStoreHelper {
dataStoreVO.setClusterId(params.getClusterId());
dataStoreVO.setStatus(StoragePoolStatus.Initialized);
dataStoreVO.setUserInfo(params.getUserInfo());
dataStoreVO.setManaged(params.isManaged());
dataStoreVO.setCapacityIops(params.getCapacityIops());
dataStoreVO.setCapacityBytes(params.getCapacityBytes());
dataStoreVO.setUsedBytes(params.getUsedBytes());
dataStoreVO.setHypervisor(params.getHypervisorType());
Map<String, String> details = params.getDetails();
String tags = params.getTags();

Some files were not shown because too many files have changed in this diff Show More