mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
more changes
This commit is contained in:
parent
49143dbe4a
commit
c443867f28
@ -137,7 +137,7 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateCommand;
|
||||
import com.cloud.agent.api.storage.DestroyCommand;
|
||||
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.agent.api.to.StoragePoolTO;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.agent.resource.computing.LibvirtStoragePoolDef.poolType;
|
||||
import com.cloud.agent.resource.computing.LibvirtStorageVolumeDef.volFormat;
|
||||
@ -1173,7 +1173,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
}
|
||||
|
||||
protected Answer execute(CreateCommand cmd) {
|
||||
StoragePoolTO pool = cmd.getPool();
|
||||
StorageFilerTO pool = cmd.getPool();
|
||||
DiskProfile dskch = cmd.getDiskCharacteristics();
|
||||
StorageVol tmplVol = null;
|
||||
StoragePool primaryPool = null;
|
||||
|
||||
@ -18,19 +18,16 @@
|
||||
package com.cloud.agent.api.storage;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.to.StoragePoolTO;
|
||||
import com.cloud.storage.StoragePoolVO;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.vm.DiskProfile;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
|
||||
public class CreateCommand extends Command {
|
||||
private long volId;
|
||||
private StoragePoolTO pool;
|
||||
private StorageFilerTO pool;
|
||||
private DiskProfile diskCharacteristics;
|
||||
private String templateUrl;
|
||||
private long size;
|
||||
private String instanceName;
|
||||
|
||||
protected CreateCommand() {
|
||||
super();
|
||||
@ -45,8 +42,8 @@ public class CreateCommand extends Command {
|
||||
* @param templateUrl
|
||||
* @param pool
|
||||
*/
|
||||
public CreateCommand(VolumeVO vol, VMInstanceVO vm, DiskProfile diskCharacteristics, String templateUrl, StoragePoolVO pool) {
|
||||
this(vol, vm, diskCharacteristics, pool, 0);
|
||||
public CreateCommand(DiskProfile diskCharacteristics, String templateUrl, StorageFilerTO pool) {
|
||||
this(diskCharacteristics, pool, 0);
|
||||
this.templateUrl = templateUrl;
|
||||
}
|
||||
|
||||
@ -58,13 +55,20 @@ public class CreateCommand extends Command {
|
||||
* @param diskCharacteristics
|
||||
* @param pool
|
||||
*/
|
||||
public CreateCommand(VolumeVO vol, VMInstanceVO vm, DiskProfile diskCharacteristics, StoragePoolVO pool, long size) {
|
||||
this.volId = vol.getId();
|
||||
public CreateCommand(DiskProfile diskCharacteristics, StorageFilerTO pool, long size) {
|
||||
this.volId = diskCharacteristics.getVolumeId();
|
||||
this.diskCharacteristics = diskCharacteristics;
|
||||
this.pool = new StoragePoolTO(pool);
|
||||
this.pool = pool;
|
||||
this.templateUrl = null;
|
||||
this.size = size;
|
||||
//this.instanceName = vm.getInstanceName();
|
||||
}
|
||||
|
||||
public CreateCommand(DiskProfile diskCharacteristics, String templateUrl, StoragePool pool) {
|
||||
this(diskCharacteristics, templateUrl, new StorageFilerTO(pool));
|
||||
}
|
||||
|
||||
public CreateCommand(DiskProfile diskCharacteristics, StoragePool pool, long size) {
|
||||
this(diskCharacteristics, new StorageFilerTO(pool), size);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -76,7 +80,7 @@ public class CreateCommand extends Command {
|
||||
return templateUrl;
|
||||
}
|
||||
|
||||
public StoragePoolTO getPool() {
|
||||
public StorageFilerTO getPool() {
|
||||
return pool;
|
||||
}
|
||||
|
||||
@ -92,7 +96,8 @@ public class CreateCommand extends Command {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getInstanceName() {
|
||||
return instanceName;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -17,11 +17,10 @@
|
||||
*/
|
||||
package com.cloud.agent.api.to;
|
||||
|
||||
import com.cloud.storage.StoragePoolVO;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StoragePool;
|
||||
|
||||
|
||||
public class StoragePoolTO {
|
||||
public class StorageFilerTO {
|
||||
long id;
|
||||
String uuid;
|
||||
String host;
|
||||
@ -29,7 +28,7 @@ public class StoragePoolTO {
|
||||
int port;
|
||||
StoragePoolType type;
|
||||
|
||||
public StoragePoolTO(StoragePoolVO pool) {
|
||||
public StorageFilerTO(StoragePool pool) {
|
||||
this.id = pool.getId();
|
||||
this.host = pool.getHostAddress();
|
||||
this.port = pool.getPort();
|
||||
@ -62,7 +61,7 @@ public class StoragePoolTO {
|
||||
return type;
|
||||
}
|
||||
|
||||
protected StoragePoolTO() {
|
||||
protected StorageFilerTO() {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -20,18 +20,39 @@ package com.cloud.exception;
|
||||
import com.cloud.utils.SerialVersionUID;
|
||||
|
||||
/**
|
||||
* This exception is thrown when the storage device can not be reached.
|
||||
*
|
||||
* This exception is thrown when storage for a VM is unavailable.
|
||||
* If the cause is due to storage pool unavailable, calling
|
||||
* getOffendingObject() will return the object that we have
|
||||
* problem with.
|
||||
*
|
||||
*/
|
||||
public class StorageUnavailableException extends AgentUnavailableException {
|
||||
public class StorageUnavailableException extends Exception {
|
||||
Object _obj;
|
||||
|
||||
private static final long serialVersionUID = SerialVersionUID.StorageUnavailableException;
|
||||
|
||||
public StorageUnavailableException(long hostId) {
|
||||
super(hostId);
|
||||
}
|
||||
|
||||
public StorageUnavailableException(String msg) {
|
||||
super(msg, -1);
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public StorageUnavailableException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
public StorageUnavailableException(String msg, Object cause) {
|
||||
super(msg);
|
||||
_obj = cause;
|
||||
}
|
||||
|
||||
public StorageUnavailableException(String msg, Object obj, Throwable cause) {
|
||||
super(msg, cause);
|
||||
_obj = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return object that caused this problem. It can either be a StoragePool or volume.
|
||||
*/
|
||||
public Object getOffendingObject() {
|
||||
return _obj;
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,10 +23,10 @@ public interface NetworkConfiguration {
|
||||
}
|
||||
|
||||
enum State implements FiniteState<State, Event> {
|
||||
Allocated, // Indicates the network configuration is in allocated but not setup.
|
||||
Setup, // Indicates the network configuration is setup.
|
||||
Implemented, // Indicates the network configuration is in use.
|
||||
Destroying;
|
||||
Allocated("Indicates the network configuration is in allocated but not setup"),
|
||||
Setup("Indicates the network configuration is setup"),
|
||||
Implemented("Indicates the network configuration is in use"),
|
||||
Destroying("Indicates the network configuration is being destroyed");
|
||||
|
||||
@Override
|
||||
public StateMachine<State, Event> getStateMachine() {
|
||||
@ -48,7 +48,23 @@ public interface NetworkConfiguration {
|
||||
return s_fsm.getPossibleEvents(this);
|
||||
}
|
||||
|
||||
String _description;
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return _description;
|
||||
}
|
||||
|
||||
private State(String description) {
|
||||
_description = description;
|
||||
}
|
||||
|
||||
private static StateMachine<State, Event> s_fsm = new StateMachine<State, Event>();
|
||||
static {
|
||||
s_fsm.addTransition(State.Allocated, Event.ImplementNetwork, State.Implemented);
|
||||
s_fsm.addTransition(State.Implemented, Event.DestroyNetwork, State.Destroying);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -26,12 +26,14 @@ public interface Resource {
|
||||
}
|
||||
|
||||
enum State implements FiniteState<State, Event> {
|
||||
Allocated, // Resource is allocated
|
||||
Reserving, // Resource is being reserved right now.
|
||||
Reserved, // Resource is reserved
|
||||
Releasing, // Resource is being released.
|
||||
Ready; // Resource is ready which means it does not need to go through reservation.
|
||||
Allocated("Resource is allocated but not reserved"),
|
||||
Reserving("Resource is being reserved right now"),
|
||||
Reserved("Resource has been reserved."),
|
||||
Releasing("Resource is being released"),
|
||||
Ready("Resource is ready which means it doesn't need to go through resservation");
|
||||
|
||||
String _description;
|
||||
|
||||
@Override
|
||||
public StateMachine<State, Event> getStateMachine() {
|
||||
|
||||
@ -54,12 +56,24 @@ public interface Resource {
|
||||
return s_fsm.getPossibleEvents(this);
|
||||
}
|
||||
|
||||
private State(String description) {
|
||||
_description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return _description;
|
||||
}
|
||||
|
||||
final static private StateMachine<State, Event> s_fsm = new StateMachine<State, Event>();
|
||||
static {
|
||||
s_fsm.addTransition(State.Allocated, Event.ReservationRequested, State.Reserving);
|
||||
s_fsm.addTransition(State.Reserving, Event.CancelRequested, State.Allocated);
|
||||
s_fsm.addTransition(State.Reserving, Event.OperationCompleted, State.Reserved);
|
||||
s_fsm.addTransition(State.Reserving, Event.OperationFailed, State.Allocated);
|
||||
s_fsm.addTransition(State.Reserved, Event.ReleaseRequested, State.Releasing);
|
||||
s_fsm.addTransition(State.Releasing, Event.OperationCompleted, State.Allocated);
|
||||
s_fsm.addTransition(State.Releasing, Event.OperationFailed, State.Reserved);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
30
api/src/com/cloud/storage/StorageGuru.java
Normal file
30
api/src/com/cloud/storage/StorageGuru.java
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.cloud.storage;
|
||||
|
||||
import com.cloud.utils.component.Adapter;
|
||||
|
||||
/**
|
||||
* StorageGuru understands about how to implement different
|
||||
* types of storage pools.
|
||||
*/
|
||||
public interface StorageGuru extends Adapter {
|
||||
void createVolume();
|
||||
void prepareVolume();
|
||||
void destroyVolume();
|
||||
}
|
||||
@ -101,4 +101,8 @@ public interface StoragePool {
|
||||
* @return the storage pool status
|
||||
*/
|
||||
Status getStatus();
|
||||
|
||||
int getPort();
|
||||
|
||||
Long getPodId();
|
||||
}
|
||||
|
||||
@ -18,10 +18,14 @@
|
||||
package com.cloud.storage;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.cloud.domain.PartOf;
|
||||
import com.cloud.template.BasedOn;
|
||||
import com.cloud.user.OwnedBy;
|
||||
import com.cloud.utils.fsm.FiniteState;
|
||||
import com.cloud.utils.fsm.StateMachine;
|
||||
|
||||
|
||||
public interface Volume extends PartOf, OwnedBy, BasedOn {
|
||||
@ -29,14 +33,70 @@ public interface Volume extends PartOf, OwnedBy, BasedOn {
|
||||
|
||||
enum MirrorState {NOT_MIRRORED, ACTIVE, DEFUNCT};
|
||||
|
||||
enum State {
|
||||
Allocated,
|
||||
Creating,
|
||||
Created,
|
||||
Corrupted,
|
||||
ToBeDestroyed,
|
||||
Expunging,
|
||||
Destroyed
|
||||
enum State implements FiniteState<State, Event> {
|
||||
Allocated("The volume is allocated but has not been created yet."),
|
||||
Creating("The volume is being created. getPoolId() should reflect the pool where it is being created."),
|
||||
Ready("The volume is ready to be used."),
|
||||
Destroy("The volume is set to be desctroyed but can be recovered."),
|
||||
Expunging("The volume is being destroyed. There's no way to recover."),
|
||||
Destroyed("The volume is destroyed. Should be removed.");
|
||||
|
||||
String _description;
|
||||
|
||||
private State(String description) {
|
||||
_description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateMachine<State, Event> getStateMachine() {
|
||||
return s_fsm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getNextState(Event event) {
|
||||
return s_fsm.getNextState(this, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<State> getFromStates(Event event) {
|
||||
return s_fsm.getFromStates(this, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Event> getPossibleEvents() {
|
||||
return s_fsm.getPossibleEvents(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return _description;
|
||||
}
|
||||
|
||||
private final static StateMachine<State, Event> s_fsm = new StateMachine<State, Event>();
|
||||
static {
|
||||
s_fsm.addTransition(Allocated, Event.Create, Creating);
|
||||
s_fsm.addTransition(Allocated, Event.Destroy, Destroyed);
|
||||
s_fsm.addTransition(Creating, Event.OperationRetry, Creating);
|
||||
s_fsm.addTransition(Creating, Event.OperationFailed, Allocated);
|
||||
s_fsm.addTransition(Creating, Event.OperationSucceeded, Ready);
|
||||
s_fsm.addTransition(Creating, Event.Destroy, Expunging);
|
||||
s_fsm.addTransition(Ready, Event.Destroy, Destroy);
|
||||
s_fsm.addTransition(Destroy, Event.Expunge, Expunging);
|
||||
s_fsm.addTransition(Destroy, Event.Recover, Ready);
|
||||
s_fsm.addTransition(Expunging, Event.OperationSucceeded, Destroyed);
|
||||
s_fsm.addTransition(Expunging, Event.OperationFailed, Destroy);
|
||||
s_fsm.addTransition(Allocated, Event.Destroy, Destroyed);
|
||||
}
|
||||
}
|
||||
|
||||
enum Event {
|
||||
Create,
|
||||
OperationFailed,
|
||||
OperationSucceeded,
|
||||
OperationRetry,
|
||||
Destroy,
|
||||
Recover,
|
||||
Expunge;
|
||||
}
|
||||
|
||||
enum SourceType {
|
||||
|
||||
@ -26,21 +26,28 @@ import com.cloud.utils.fsm.StateMachine;
|
||||
import com.cloud.vm.VirtualMachine.Event;
|
||||
|
||||
public enum State implements FiniteState<State, Event> {
|
||||
Creating(true),
|
||||
Starting(true),
|
||||
Running(false),
|
||||
Stopping(true),
|
||||
Stopped(false),
|
||||
Destroyed(false),
|
||||
Expunging(true),
|
||||
Migrating(true),
|
||||
Error(false),
|
||||
Unknown(false);
|
||||
Creating(true, "VM is being created"),
|
||||
Starting(true, "VM is being started. At this state, you should find host id filled which means it's being started on that host."),
|
||||
Running(false, "VM is running. host id has the host that it is running on."),
|
||||
Stopping(true, "VM is being stopped. host id has the host that it is being stopped on."),
|
||||
Stopped(false, "VM is stopped. host id should be null."),
|
||||
Destroyed(false, "VM is marked for destroy."),
|
||||
Expunging(true, "VM is being expunged."),
|
||||
Migrating(true, "VM is being migrated. host id holds to from host"),
|
||||
Error(false, "VM is in error"),
|
||||
Unknown(false, "VM state is unknown.");
|
||||
|
||||
private final boolean _transitional;
|
||||
String _description;
|
||||
|
||||
private State(boolean transitional) {
|
||||
private State(boolean transitional, String description) {
|
||||
_transitional = transitional;
|
||||
_description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return _description;
|
||||
}
|
||||
|
||||
public boolean isTransitional() {
|
||||
@ -67,6 +74,7 @@ public enum State implements FiniteState<State, Event> {
|
||||
return s_fsm;
|
||||
}
|
||||
|
||||
|
||||
protected static final StateMachine<State, VirtualMachine.Event> s_fsm = new StateMachine<State, VirtualMachine.Event>();
|
||||
static {
|
||||
s_fsm.addTransition(null, VirtualMachine.Event.CreateRequested, State.Creating);
|
||||
|
||||
@ -145,7 +145,7 @@ import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.agent.api.storage.ShareAnswer;
|
||||
import com.cloud.agent.api.storage.ShareCommand;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.StoragePoolTO;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.exception.InternalErrorException;
|
||||
@ -4449,7 +4449,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
|
||||
|
||||
protected Answer execute(ModifyStoragePoolCommand cmd) {
|
||||
StoragePoolVO pool = cmd.getPool();
|
||||
StoragePoolTO poolTO = new StoragePoolTO(pool);
|
||||
StorageFilerTO poolTO = new StorageFilerTO(pool);
|
||||
try {
|
||||
Connection conn = getConnection();
|
||||
|
||||
@ -4478,7 +4478,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
|
||||
|
||||
protected Answer execute(DeleteStoragePoolCommand cmd) {
|
||||
StoragePoolVO pool = cmd.getPool();
|
||||
StoragePoolTO poolTO = new StoragePoolTO(pool);
|
||||
StorageFilerTO poolTO = new StorageFilerTO(pool);
|
||||
try {
|
||||
Connection conn = getConnection();
|
||||
SR sr = getStorageRepository(conn, poolTO);
|
||||
@ -4719,7 +4719,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
|
||||
|
||||
@Override
|
||||
public CreateAnswer execute(CreateCommand cmd) {
|
||||
StoragePoolTO pool = cmd.getPool();
|
||||
StorageFilerTO pool = cmd.getPool();
|
||||
DiskProfile dskch = cmd.getDiskCharacteristics();
|
||||
|
||||
VDI vdi = null;
|
||||
@ -4893,7 +4893,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
|
||||
}
|
||||
}
|
||||
|
||||
protected SR getIscsiSR(StoragePoolTO pool) {
|
||||
protected SR getIscsiSR(StorageFilerTO pool) {
|
||||
Connection conn = getConnection();
|
||||
synchronized (pool.getUuid().intern()) {
|
||||
Map<String, String> deviceConfig = new HashMap<String, String>();
|
||||
@ -5003,7 +5003,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
|
||||
}
|
||||
}
|
||||
|
||||
protected SR getNfsSR(StoragePoolTO pool) {
|
||||
protected SR getNfsSR(StorageFilerTO pool) {
|
||||
Connection conn = getConnection();
|
||||
|
||||
Map<String, String> deviceConfig = new HashMap<String, String>();
|
||||
@ -5124,7 +5124,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
|
||||
public CopyVolumeAnswer execute(final CopyVolumeCommand cmd) {
|
||||
String volumeUUID = cmd.getVolumePath();
|
||||
StoragePoolVO pool = cmd.getPool();
|
||||
StoragePoolTO poolTO = new StoragePoolTO(pool);
|
||||
StorageFilerTO poolTO = new StorageFilerTO(pool);
|
||||
String secondaryStorageURL = cmd.getSecondaryStorageURL();
|
||||
|
||||
URI uri = null;
|
||||
@ -6041,7 +6041,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
|
||||
}
|
||||
}
|
||||
|
||||
protected SR getStorageRepository(Connection conn, StoragePoolTO pool) {
|
||||
protected SR getStorageRepository(Connection conn, StorageFilerTO pool) {
|
||||
Set<SR> srs;
|
||||
try {
|
||||
srs = SR.getByNameLabel(conn, pool.getUuid());
|
||||
|
||||
@ -28,6 +28,8 @@ import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.HostPodVO;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientStorageCapacityException;
|
||||
import com.cloud.exception.InternalErrorException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceInUseException;
|
||||
@ -229,9 +231,9 @@ public interface StorageManager extends Manager {
|
||||
*/
|
||||
boolean volumeOnSharedStoragePool(VolumeVO volume);
|
||||
|
||||
Answer[] sendToPool(StoragePoolVO pool, Command[] cmds, boolean stopOnError);
|
||||
Answer[] sendToPool(StoragePool pool, Command[] cmds, boolean stopOnError);
|
||||
|
||||
Answer sendToPool(StoragePoolVO pool, Command cmd);
|
||||
Answer sendToPool(StoragePool pool, Command cmd);
|
||||
|
||||
/**
|
||||
* Checks that one of the following is true:
|
||||
@ -314,9 +316,9 @@ public interface StorageManager extends Manager {
|
||||
<T extends VMInstanceVO> DiskProfile allocateTemplatedVolume(VolumeType type, String name, DiskOfferingVO offering, VMTemplateVO template, T vm, AccountVO owner);
|
||||
|
||||
<T extends VMInstanceVO> void create(T vm);
|
||||
Long findHostIdForStoragePool(StoragePoolVO pool);
|
||||
Long findHostIdForStoragePool(StoragePool pool);
|
||||
void createCapacityEntry(StoragePoolVO storagePool, long allocated);
|
||||
|
||||
|
||||
VolumeTO[] prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException;
|
||||
VolumeTO[] prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, InsufficientStorageCapacityException, ConcurrentOperationException;
|
||||
}
|
||||
|
||||
@ -82,7 +82,8 @@ public class StoragePoolVO implements StoragePool {
|
||||
@Enumerated(value=EnumType.STRING)
|
||||
private Status status;
|
||||
|
||||
public long getId() {
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -95,19 +96,23 @@ public class StoragePoolVO implements StoragePool {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public StoragePoolType getPoolType() {
|
||||
@Override
|
||||
public StoragePoolType getPoolType() {
|
||||
return poolType;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
@Override
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
@ -115,19 +120,23 @@ public class StoragePoolVO implements StoragePool {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public Date getUpdateTime() {
|
||||
@Override
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public long getDataCenterId() {
|
||||
@Override
|
||||
public long getDataCenterId() {
|
||||
return dataCenterId;
|
||||
}
|
||||
|
||||
public long getAvailableBytes() {
|
||||
@Override
|
||||
public long getAvailableBytes() {
|
||||
return availableBytes;
|
||||
}
|
||||
|
||||
public long getCapacityBytes() {
|
||||
@Override
|
||||
public long getCapacityBytes() {
|
||||
return capacityBytes;
|
||||
}
|
||||
|
||||
@ -160,10 +169,12 @@ public class StoragePoolVO implements StoragePool {
|
||||
this.clusterId = clusterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHostAddress() {
|
||||
return hostAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
@ -217,10 +228,12 @@ public class StoragePoolVO implements StoragePool {
|
||||
return port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShared() {
|
||||
return poolType.isShared();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
return !poolType.isShared();
|
||||
}
|
||||
@ -252,6 +265,10 @@ public class StoragePoolVO implements StoragePool {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean isInMaintenance() {
|
||||
return status == Status.PrepareForMaintenance || status == Status.Maintenance || status == Status.ErrorInMaintenance || removed != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof StoragePoolVO) || obj == null) {
|
||||
|
||||
@ -236,6 +236,10 @@ public class VolumeVO implements Volume {
|
||||
this.status = AsyncInstanceCreateStatus.Created;
|
||||
this.recreatable = false;
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public boolean isRecreatable() {
|
||||
return recreatable;
|
||||
@ -245,7 +249,8 @@ public class VolumeVO implements Volume {
|
||||
return iscsiName;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ package com.cloud.storage.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.utils.Pair;
|
||||
@ -47,4 +48,13 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long> {
|
||||
List<VolumeVO> findCreatedByInstance(long id);
|
||||
List<VolumeVO> findByPoolId(long poolId);
|
||||
List<VolumeVO> findByInstanceAndDeviceId(long instanceId, long deviceId);
|
||||
List<VolumeVO> findUsableVolumesForInstance(long instanceId);
|
||||
|
||||
/**
|
||||
* Updates the volume only if the state in memory matches the state in the database.
|
||||
* @param vol Volume to be updated.
|
||||
* @param event event that causes the database change.
|
||||
* @return true if update happened, false if not.
|
||||
*/
|
||||
boolean update(VolumeVO vol, Volume.Event event) throws ConcurrentOperationException;
|
||||
}
|
||||
|
||||
@ -29,11 +29,13 @@ import javax.ejb.Local;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.async.AsyncInstanceCreateStatus;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.Volume.MirrorState;
|
||||
import com.cloud.storage.Volume.VolumeType;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Attribute;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.GenericSearchBuilder;
|
||||
@ -42,6 +44,7 @@ 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;
|
||||
|
||||
@Local(value=VolumeDao.class) @DB(txn=false)
|
||||
@ -62,6 +65,10 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
protected final SearchBuilder<VolumeVO> RemovedButNotDestroyedSearch;
|
||||
protected final SearchBuilder<VolumeVO> PoolIdSearch;
|
||||
protected final SearchBuilder<VolumeVO> InstanceAndDeviceIdSearch;
|
||||
protected final SearchBuilder<VolumeVO> InstanceStatesSearch;
|
||||
protected final SearchBuilder<VolumeVO> IdStateSearch;
|
||||
|
||||
protected final Attribute _stateAttr;
|
||||
|
||||
protected static final String SELECT_VM_SQL = "SELECT DISTINCT instance_id from volumes v where v.host_id = ? and v.mirror_state = ?";
|
||||
protected static final String SELECT_VM_ID_SQL = "SELECT DISTINCT instance_id from volumes v where v.host_id = ?";
|
||||
@ -143,6 +150,15 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findUsableVolumesForInstance(long instanceId) {
|
||||
SearchCriteria<VolumeVO> sc = InstanceStatesSearch.create();
|
||||
sc.setParameters("instance", instanceId);
|
||||
sc.setParameters("states", Volume.State.Creating, Volume.State.Ready, Volume.State.Allocated);
|
||||
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VolumeVO> findByInstanceAndType(long id, VolumeType vType) {
|
||||
SearchCriteria<VolumeVO> sc = InstanceAndTypeSearch.create();
|
||||
@ -271,6 +287,28 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
update(volumeId, volume);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(VolumeVO vol, Volume.Event event) throws ConcurrentOperationException {
|
||||
Volume.State oldState = vol.getState();
|
||||
Volume.State newState = oldState.getNextState(event);
|
||||
|
||||
assert newState != null : "Event "+ event + " cannot happen from " + oldState;
|
||||
|
||||
UpdateBuilder builder = getUpdateBuilder(vol);
|
||||
builder.set(vol, _stateAttr, newState);
|
||||
|
||||
SearchCriteria<VolumeVO> sc = IdStateSearch.create();
|
||||
sc.setParameters("id", vol.getId());
|
||||
sc.setParameters("state", vol.getState());
|
||||
|
||||
int rows = update(builder, sc, null);
|
||||
if (rows != 1) {
|
||||
VolumeVO dbVol = findById(vol.getId());
|
||||
throw new ConcurrentOperationException("Unable to update " + vol + ": Old State=" + oldState + "; New State = " + newState + "; DB State=" + dbVol.getState());
|
||||
}
|
||||
return rows == 1;
|
||||
}
|
||||
|
||||
protected VolumeDaoImpl() {
|
||||
AccountIdSearch = createSearchBuilder();
|
||||
AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
@ -353,6 +391,19 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
|
||||
RemovedButNotDestroyedSearch.and("destroyed", RemovedButNotDestroyedSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
RemovedButNotDestroyedSearch.and("removed", RemovedButNotDestroyedSearch.entity().getRemoved(), SearchCriteria.Op.NNULL);
|
||||
RemovedButNotDestroyedSearch.done();
|
||||
|
||||
InstanceStatesSearch = createSearchBuilder();
|
||||
InstanceStatesSearch.and("instance", InstanceStatesSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||
InstanceStatesSearch.and("states", InstanceStatesSearch.entity().getState(), SearchCriteria.Op.IN);
|
||||
InstanceStatesSearch.done();
|
||||
|
||||
IdStateSearch = createSearchBuilder();
|
||||
IdStateSearch.and("id", IdStateSearch.entity().getId(), SearchCriteria.Op.EQ);
|
||||
IdStateSearch.and("state", IdStateSearch.entity().getState(), SearchCriteria.Op.EQ);
|
||||
IdStateSearch.done();
|
||||
|
||||
_stateAttr = _allAttributes.get("state");
|
||||
assert _stateAttr != null : "Couldn't get the state attribute";
|
||||
}
|
||||
|
||||
@Override @DB(txn=false)
|
||||
|
||||
@ -516,7 +516,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach
|
||||
@Override
|
||||
public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) {
|
||||
try {
|
||||
return start(proxyVmId, startEventId);
|
||||
return start2(proxyVmId, startEventId);
|
||||
} catch (StorageUnavailableException e) {
|
||||
s_logger.warn("Exception while trying to start console proxy", e);
|
||||
return null;
|
||||
@ -852,7 +852,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach
|
||||
if (s_logger.isDebugEnabled())
|
||||
s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId);
|
||||
|
||||
Map<String, Object> context = createProxyInstance(dataCenterId);
|
||||
Map<String, Object> context = createProxyInstance2(dataCenterId);
|
||||
|
||||
long proxyVmId = (Long) context.get("proxyVmId");
|
||||
if (proxyVmId == 0) {
|
||||
@ -892,7 +892,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach
|
||||
if (s_logger.isDebugEnabled())
|
||||
s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId);
|
||||
|
||||
Map<String, Object> context = createProxyInstance(dataCenterId);
|
||||
Map<String, Object> context = createProxyInstance2(dataCenterId);
|
||||
|
||||
long proxyVmId = (Long) context.get("proxyVmId");
|
||||
if (proxyVmId == 0) {
|
||||
@ -1417,7 +1417,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach
|
||||
try {
|
||||
if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) {
|
||||
try {
|
||||
readyProxy = start(readyProxy.getId(), 0);
|
||||
readyProxy = start2(readyProxy.getId(), 0);
|
||||
} finally {
|
||||
proxyLock.unlock();
|
||||
}
|
||||
@ -2150,7 +2150,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach
|
||||
|
||||
if (!_storageMgr.share(proxy, vols, routingHost, false)) {
|
||||
s_logger.warn("Can not share " + proxy.getName());
|
||||
throw new StorageUnavailableException(vol.getPoolId());
|
||||
throw new StorageUnavailableException("Can not share " + proxy.getName(), vol);
|
||||
}
|
||||
|
||||
Answer answer = _agentMgr.easySend(routingHost.getId(), cmd);
|
||||
|
||||
@ -2139,7 +2139,7 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager
|
||||
|
||||
if( ! _storageMgr.share(router, vols, routingHost, false) ) {
|
||||
s_logger.warn("Can not share " + vol.getPath() + " to " + router.getName() );
|
||||
throw new StorageUnavailableException(vol.getPoolId());
|
||||
throw new StorageUnavailableException("Can not share " + vol.getPath() + " to " + router.getName(), vol);
|
||||
}
|
||||
|
||||
final Answer answer = _agentMgr.easySend(routingHost.getId(), cmd);
|
||||
|
||||
@ -26,7 +26,6 @@ import java.util.Enumeration;
|
||||
import java.util.Formatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -56,6 +55,7 @@ import com.cloud.agent.api.storage.CreateAnswer;
|
||||
import com.cloud.agent.api.storage.CreateCommand;
|
||||
import com.cloud.agent.api.storage.DeleteTemplateCommand;
|
||||
import com.cloud.agent.api.storage.DestroyCommand;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.alert.AlertManager;
|
||||
import com.cloud.api.BaseCmd;
|
||||
@ -84,6 +84,7 @@ import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.DiscoveryException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.InsufficientStorageCapacityException;
|
||||
import com.cloud.exception.InternalErrorException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
@ -103,6 +104,7 @@ import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.Volume.Event;
|
||||
import com.cloud.storage.Volume.MirrorState;
|
||||
import com.cloud.storage.Volume.SourceType;
|
||||
import com.cloud.storage.Volume.VolumeType;
|
||||
@ -173,10 +175,6 @@ public class StorageManagerImpl implements StorageManager {
|
||||
@Inject protected ConsoleProxyDao _consoleProxyDao;
|
||||
@Inject protected DetailsDao _detailsDao;
|
||||
@Inject protected SnapshotDao _snapshotDao;
|
||||
@Inject(adapter=StoragePoolAllocator.class)
|
||||
protected Adapters<StoragePoolAllocator> _storagePoolAllocators;
|
||||
@Inject(adapter=StoragePoolDiscoverer.class)
|
||||
protected Adapters<StoragePoolDiscoverer> _discoverers;
|
||||
@Inject protected StoragePoolHostDao _storagePoolHostDao;
|
||||
@Inject protected AlertManager _alertMgr;
|
||||
@Inject protected VMTemplateHostDao _vmTemplateHostDao = null;
|
||||
@ -197,6 +195,11 @@ public class StorageManagerImpl implements StorageManager {
|
||||
@Inject protected ServiceOfferingDao _offeringDao;
|
||||
@Inject protected UserDao _userDao;
|
||||
|
||||
@Inject(adapter=StoragePoolAllocator.class)
|
||||
protected Adapters<StoragePoolAllocator> _storagePoolAllocators;
|
||||
@Inject(adapter=StoragePoolDiscoverer.class)
|
||||
protected Adapters<StoragePoolDiscoverer> _discoverers;
|
||||
|
||||
protected SearchBuilder<VMTemplateHostVO> HostTemplateStatesSearch;
|
||||
protected SearchBuilder<StoragePoolVO> PoolsUsedByVmSearch;
|
||||
|
||||
@ -272,79 +275,6 @@ public class StorageManagerImpl implements StorageManager {
|
||||
return vols.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolumeTO[] prepare(VirtualMachineProfile vm, DeployDestination dest) {
|
||||
List<VolumeVO> vols = _volsDao.findCreatedByInstance(vm.getId());
|
||||
List<VolumeVO> recreateVols = new ArrayList<VolumeVO>(vols.size());
|
||||
Host host = dest.getHost();
|
||||
|
||||
VolumeTO[] disks = new VolumeTO[vols.size()];
|
||||
int i = 0;
|
||||
Iterator<VolumeVO> it = vols.iterator();
|
||||
while (it.hasNext()) {
|
||||
VolumeVO vol = it.next();
|
||||
if (vol.isRecreatable()) {
|
||||
it.remove();
|
||||
//if we have a system vm
|
||||
//get the storage pool
|
||||
//if pool is in maintenance
|
||||
//add to recreate vols, and continue
|
||||
if(vm.getType().equals(VirtualMachine.Type.ConsoleProxy) || vm.getType().equals(VirtualMachine.Type.DomainRouter) || vm.getType().equals(VirtualMachine.Type.SecondaryStorageVm))
|
||||
{
|
||||
StoragePoolVO sp = _storagePoolDao.findById(vol.getPoolId());
|
||||
|
||||
if(sp!=null && sp.getStatus().equals(Status.PrepareForMaintenance))
|
||||
{
|
||||
recreateVols.add(vol);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
StoragePoolHostVO ph = _storagePoolHostDao.findByPoolHost(vol.getPoolId(), host.getId());
|
||||
if (ph == null) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Must recreate " + vol + " since " + vol.getPoolId() + " has is not hooked up with host " + host.getId());
|
||||
}
|
||||
recreateVols.add(vol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (VolumeVO vol : recreateVols) {
|
||||
VolumeVO create = allocateDuplicateVolume(vol);
|
||||
vols.add(vol);
|
||||
}
|
||||
|
||||
/*
|
||||
create.setDiskOfferingId(vol.getDiskOfferingId());
|
||||
create.setDeviceId(vol.getDeviceId());
|
||||
create = _volsDao.persist(create);
|
||||
VMTemplateVO template = _templateDao.findById(create.getTemplateId());
|
||||
DataCenterVO dc = _dcDao.findById(create.getDataCenterId());
|
||||
HostPodVO pod = _podDao.findById(host.getPodId());
|
||||
DiskOfferingVO diskOffering = null;
|
||||
diskOffering = _diskOfferingDao.findById(vol.getDiskOfferingId());
|
||||
ServiceOfferingVO offering;
|
||||
if (vm instanceof UserVmVO) {
|
||||
offering = _offeringDao.findById(((UserVmVO)vm).getServiceOfferingId());
|
||||
} else {
|
||||
offering = _offeringDao.findById(vol.getDiskOfferingId());
|
||||
}
|
||||
VolumeVO created = createVolume(create, vm, template, dc, pod, host.getClusterId(), offering, diskOffering, new ArrayList<StoragePoolVO>(),0);
|
||||
if (created == null) {
|
||||
break;
|
||||
}
|
||||
createds.add(created);
|
||||
|
||||
for (VolumeVO vol : recreateVols) {
|
||||
_volsDao.remove(vol.getId());
|
||||
}
|
||||
disks[i++] = null;
|
||||
}
|
||||
*/
|
||||
return disks;
|
||||
}
|
||||
|
||||
VolumeVO allocateDuplicateVolume(VolumeVO oldVol) {
|
||||
VolumeVO newVol = new VolumeVO(oldVol.getVolumeType(), oldVol.getName(), oldVol.getDataCenterId(), oldVol.getDomainId(), oldVol.getAccountId(), oldVol.getDiskOfferingId(), oldVol.getSize());
|
||||
newVol.setTemplateId(oldVol.getTemplateId());
|
||||
@ -487,7 +417,7 @@ public class StorageManagerImpl implements StorageManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long findHostIdForStoragePool(StoragePoolVO pool) {
|
||||
public Long findHostIdForStoragePool(StoragePool pool) {
|
||||
List<StoragePoolHostVO> poolHosts = _poolHostDao.listByHostStatus(pool.getId(), Status.Up);
|
||||
|
||||
if (poolHosts.size() == 0) {
|
||||
@ -498,7 +428,7 @@ public class StorageManagerImpl implements StorageManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer[] sendToPool(StoragePoolVO pool, Command[] cmds, boolean stopOnError) {
|
||||
public Answer[] sendToPool(StoragePool pool, Command[] cmds, boolean stopOnError) {
|
||||
List<StoragePoolHostVO> poolHosts = _poolHostDao.listByHostStatus(pool.getId(), Status.Up);
|
||||
Collections.shuffle(poolHosts);
|
||||
|
||||
@ -520,7 +450,7 @@ public class StorageManagerImpl implements StorageManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer sendToPool(StoragePoolVO pool, Command cmd) {
|
||||
public Answer sendToPool(StoragePool pool, Command cmd) {
|
||||
Command[] cmds = new Command[]{cmd};
|
||||
Answer[] answers = sendToPool(pool, cmds, true);
|
||||
if (answers == null) {
|
||||
@ -885,9 +815,9 @@ public class StorageManagerImpl implements StorageManager {
|
||||
if (tmpltStoredOn == null) {
|
||||
continue;
|
||||
}
|
||||
cmd = new CreateCommand(volume, vm, dskCh, tmpltStoredOn.getLocalDownloadPath(), pool);
|
||||
cmd = new CreateCommand(dskCh, tmpltStoredOn.getLocalDownloadPath(), new StorageFilerTO(pool));
|
||||
} else {
|
||||
cmd = new CreateCommand(volume, vm, dskCh, pool, size);
|
||||
cmd = new CreateCommand(dskCh, new StorageFilerTO(pool), size);
|
||||
}
|
||||
|
||||
Answer answer = sendToPool(pool, cmd);
|
||||
@ -2441,6 +2371,149 @@ public class StorageManagerImpl implements StorageManager {
|
||||
return createDiskCharacteristics(volume, offering);
|
||||
}
|
||||
|
||||
protected StoragePool findStorage(DiskProfile dskCh, DeployDestination dest, VirtualMachineProfile vm, List<? extends Volume> alreadyAllocated, Set<? extends StoragePool> avoid) {
|
||||
for (StoragePoolAllocator allocator : _storagePoolAllocators) {
|
||||
StoragePool pool = allocator.allocateTo(dskCh, vm, dest, alreadyAllocated, avoid);
|
||||
if (pool != null) {
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolumeTO[] prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, InsufficientStorageCapacityException {
|
||||
List<VolumeVO> vols = _volsDao.findUsableVolumesForInstance(vm.getId());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Preparing " + vols.size() + " volumes for " + vm);
|
||||
}
|
||||
|
||||
List<VolumeVO> recreateVols = new ArrayList<VolumeVO>(vols.size());
|
||||
VolumeTO[] disks = new VolumeTO[vols.size()];
|
||||
|
||||
int i = 0;
|
||||
for (VolumeVO vol : vols) {
|
||||
Volume.State state = vol.getState();
|
||||
if (state == Volume.State.Ready) {
|
||||
StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
|
||||
if (pool.getRemoved() != null || pool.isInMaintenance()) {
|
||||
if (vol.isRecreatable()) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Volume " + vol + " has to be recreated due to storage pool " + pool + " is unavailable");
|
||||
}
|
||||
recreateVols.add(vol);
|
||||
} else {
|
||||
throw new StorageUnavailableException("Volume " + vol + " is not available on the storage pool.", pool);
|
||||
}
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Volume " + vol + " is ready.");
|
||||
}
|
||||
disks[i++] = new VolumeTO(vol, pool);
|
||||
}
|
||||
} else if (state == Volume.State.Allocated) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Creating volume " + vol + " for the first time.");
|
||||
}
|
||||
recreateVols.add(vol);
|
||||
} else {
|
||||
throw new StorageUnavailableException("Volume " + vol + " can not be used", vol);
|
||||
}
|
||||
}
|
||||
|
||||
for (VolumeVO vol : recreateVols) {
|
||||
VolumeVO newVol;
|
||||
if (vol.getState() == Volume.State.Allocated) {
|
||||
newVol = vol;
|
||||
} else {
|
||||
newVol = switchVolume(vol);
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Created new volume " + newVol + " for old volume " + vol);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
_volsDao.update(newVol, Volume.Event.Create);
|
||||
} catch(ConcurrentOperationException e) {
|
||||
throw new StorageUnavailableException("Unable to create " + newVol, newVol);
|
||||
}
|
||||
Pair<VolumeTO, StoragePool> created = createVolume(newVol, _diskOfferingDao.findById(newVol.getDiskOfferingId()), vm, vols, dest);
|
||||
if (created == null) {
|
||||
newVol.setPoolId(null);
|
||||
try {
|
||||
_volsDao.update(newVol, Event.OperationFailed);
|
||||
} catch (ConcurrentOperationException e) {
|
||||
throw new CloudRuntimeException("Unable to update the failure on a volume: " + newVol, e);
|
||||
}
|
||||
throw new StorageUnavailableException("Unable to create " + newVol, newVol);
|
||||
}
|
||||
newVol.setStatus(AsyncInstanceCreateStatus.Created);
|
||||
newVol.setFolder(created.second().getPath());
|
||||
newVol.setPath(created.first().getPath());
|
||||
newVol.setSize(created.first().getSize());
|
||||
newVol.setPoolType(created.second().getPoolType());
|
||||
newVol.setPodId(created.second().getPodId());
|
||||
try {
|
||||
_volsDao.update(newVol, Event.OperationSucceeded);
|
||||
} catch (ConcurrentOperationException e) {
|
||||
throw new CloudRuntimeException("Unable to update an CREATE operation succeeded on volume " + newVol, e);
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Volume " + newVol + " is created on " + created.second());
|
||||
}
|
||||
disks[i++] = created.first();
|
||||
}
|
||||
|
||||
return disks;
|
||||
}
|
||||
|
||||
@DB
|
||||
protected VolumeVO switchVolume(VolumeVO existingVolume) throws StorageUnavailableException {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
try {
|
||||
txn.start();
|
||||
_volsDao.update(existingVolume, Event.Destroy);
|
||||
VolumeVO newVolume = allocateDuplicateVolume(existingVolume);
|
||||
txn.commit();
|
||||
return newVolume;
|
||||
} catch (ConcurrentOperationException e) {
|
||||
throw new StorageUnavailableException("Unable to duplicate the volume " + existingVolume, existingVolume, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Pair<VolumeTO, StoragePool> createVolume(VolumeVO toBeCreated, DiskOfferingVO offering, VirtualMachineProfile vm, List<? extends Volume> alreadyCreated, DeployDestination dest) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Creating volume: " + toBeCreated);
|
||||
}
|
||||
DiskProfile diskProfile = new DiskProfile(toBeCreated, offering);
|
||||
|
||||
Set<StoragePool> avoids = new HashSet<StoragePool>();
|
||||
StoragePool pool = null;
|
||||
while ((pool = findStorage(diskProfile, dest, vm, alreadyCreated, avoids)) != null) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Trying to create in " + pool);
|
||||
}
|
||||
avoids.add(pool);
|
||||
toBeCreated.setPoolId(pool.getId());
|
||||
try {
|
||||
_volsDao.update(toBeCreated, Volume.Event.OperationRetry);
|
||||
} catch (ConcurrentOperationException e) {
|
||||
throw new CloudRuntimeException("Unable to retry a create operation on volume " + toBeCreated);
|
||||
}
|
||||
CreateCommand cmd = new CreateCommand(diskProfile, new StorageFilerTO(pool), diskProfile.getSize());
|
||||
Answer answer = sendToPool(pool, cmd);
|
||||
if (answer.getResult()) {
|
||||
CreateAnswer createAnswer = (CreateAnswer)answer;
|
||||
return new Pair<VolumeTO, StoragePool>(createAnswer.getVolume(), pool);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Unable to create volume " + toBeCreated);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends VMInstanceVO> void create(T vm) {
|
||||
List<VolumeVO> vols = _volsDao.findByInstance(vm.getId());
|
||||
|
||||
@ -28,6 +28,8 @@ import javax.naming.ConfigurationException;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.HostPodVO;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
@ -229,8 +231,11 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoragePool allocateTo(DiskProfile dskCh, VirtualMachineProfile vm, DeployDestination dest, List<Volume> disks, Set<StoragePool> avoids) {
|
||||
public StoragePool allocateTo(DiskProfile dskCh, VirtualMachineProfile vm, DeployDestination dest, List<? extends Volume> disks, Set<? extends StoragePool> avoids) {
|
||||
|
||||
return null;
|
||||
VMInstanceVO instance = (VMInstanceVO)(vm.getVm());
|
||||
|
||||
VMTemplateVO template = vm.getTemplateId() != null ? _templateDao.findById(vm.getTemplateId()) : null;
|
||||
return allocateToPool(dskCh, (DataCenterVO)dest.getDataCenter(), (HostPodVO)dest.getPod(), dest.getCluster().getId(), instance, template, avoids);
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,5 +43,5 @@ public interface StoragePoolAllocator extends Adapter {
|
||||
|
||||
String chooseStorageIp(VirtualMachine vm, Host host, Host storage);
|
||||
|
||||
StoragePool allocateTo(DiskProfile dskCh, VirtualMachineProfile vm, DeployDestination dest, List<Volume> disks, Set<StoragePool> avoids);
|
||||
StoragePool allocateTo(DiskProfile dskCh, VirtualMachineProfile vm, DeployDestination dest, List<? extends Volume> disks, Set<? extends StoragePool> avoids);
|
||||
}
|
||||
|
||||
@ -1822,7 +1822,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
|
||||
|
||||
if( !_storageMgr.share(secStorageVm, vols, routingHost, false) ) {
|
||||
s_logger.warn("Can not share " + vol.getPath() + " to " + secStorageVm.getName());
|
||||
throw new StorageUnavailableException(vol.getPoolId());
|
||||
throw new StorageUnavailableException("Can not share " + vol.getPath() + " to " + secStorageVm.getName(), vol);
|
||||
}
|
||||
|
||||
Answer answer = _agentMgr.easySend(routingHost.getId(), cmd);
|
||||
|
||||
@ -36,7 +36,9 @@ import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.deploy.DeploymentPlanner;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.network.NetworkConfigurationVO;
|
||||
import com.cloud.network.NetworkManager;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
@ -233,7 +235,7 @@ public class MauriceMoss implements VmManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends VMInstanceVO> T start(T vm, DeploymentPlan plan) throws InsufficientCapacityException {
|
||||
public <T extends VMInstanceVO> T start(T vm, DeploymentPlan plan) throws InsufficientCapacityException, ConcurrentOperationException {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Creating actual resources for VM " + vm);
|
||||
}
|
||||
@ -246,7 +248,7 @@ public class MauriceMoss implements VmManager {
|
||||
|
||||
Set<DeployDestination> avoids = new HashSet<DeployDestination>();
|
||||
int retry = _retry;
|
||||
while (retry-- > 0) {
|
||||
while (retry-- != 0) { // It's != so that it can match -1.
|
||||
DeployDestination dest = null;
|
||||
for (DeploymentPlanner dispatcher : _planners) {
|
||||
dest = dispatcher.plan(vmProfile, plan, avoids);
|
||||
@ -266,8 +268,15 @@ public class MauriceMoss implements VmManager {
|
||||
_vmDao.updateIf(vm, Event.StartRequested, dest.getHost().getId());
|
||||
|
||||
VirtualMachineTO vmTO = new VirtualMachineTO();
|
||||
try {
|
||||
_storageMgr.prepare(vmProfile, dest);
|
||||
} catch (ConcurrentOperationException e) {
|
||||
throw e;
|
||||
} catch (StorageUnavailableException e) {
|
||||
s_logger.warn("Unable to contact storage.", e);
|
||||
continue;
|
||||
}
|
||||
_networkMgr.prepare(vmProfile, dest);
|
||||
// _storageMgr.prepare(vm, dest);
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
|
||||
@ -179,9 +179,9 @@ import com.cloud.vm.DomainRouter.Role;
|
||||
import com.cloud.vm.VirtualMachine.Event;
|
||||
import com.cloud.vm.VirtualMachine.Type;
|
||||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
import com.cloud.vm.dao.InstanceGroupDao;
|
||||
import com.cloud.vm.dao.InstanceGroupVMMapDao;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.InstanceGroupDao;
|
||||
|
||||
@Local(value={UserVmManager.class})
|
||||
public class UserVmManagerImpl implements UserVmManager {
|
||||
@ -1207,6 +1207,7 @@ public class UserVmManagerImpl implements UserVmManager {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void releaseGuestIpAddress(UserVmVO userVm) {
|
||||
ServiceOffering offering = _offeringDao.findById(userVm.getServiceOfferingId());
|
||||
|
||||
@ -2117,7 +2118,7 @@ public class UserVmManagerImpl implements UserVmManager {
|
||||
|
||||
if( !_storageMgr.share(vm, vols, vmHost, false) ) {
|
||||
s_logger.warn("Can not share " + vm.toString() + " on host " + vmHost.getId());
|
||||
throw new StorageUnavailableException(vmHost.getId());
|
||||
throw new StorageUnavailableException("Can not share " + vm.toString() + " on host " + vmHost.getId());
|
||||
}
|
||||
|
||||
Answer answer = _agentMgr.easySend(vmHost.getId(), cmd);
|
||||
@ -2400,6 +2401,7 @@ public class UserVmManagerImpl implements UserVmManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VMTemplateVO createPrivateTemplateRecord(Long userId, long volumeId, String name, String description, long guestOSId, Boolean requiresHvm, Integer bits, Boolean passwordEnabled, boolean isPublic, boolean featured)
|
||||
throws InvalidParameterValueException {
|
||||
|
||||
@ -3014,7 +3016,8 @@ public class UserVmManagerImpl implements UserVmManager {
|
||||
_vmMgr = vmMgr;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
@Override
|
||||
public void run() {
|
||||
GlobalLock scanLock = GlobalLock.getInternLock("UserVMExpunge");
|
||||
try {
|
||||
if(scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) {
|
||||
|
||||
@ -52,4 +52,6 @@ public interface FiniteState<S, E> {
|
||||
* @return array of events.
|
||||
*/
|
||||
Set<E> getPossibleEvents();
|
||||
|
||||
String getDescription();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user