You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by pr...@apache.org on 2013/01/22 22:19:38 UTC

[1/14] Deploy, Start, Stop, Destroy VM orchestration service changes

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/94e8090b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java
index efa95fd..c60ed34 100755
--- a/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java
@@ -40,12 +40,16 @@ import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.hypervisor.Hypervisor;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.network.NetworkVO;
+import com.cloud.network.dao.NetworkDao;
 import com.cloud.service.ServiceOfferingVO;
 import com.cloud.service.dao.ServiceOfferingDao;
 import com.cloud.storage.DiskOfferingVO;
 import com.cloud.storage.dao.DiskOfferingDao;
 import com.cloud.storage.dao.VMTemplateDao;
+import com.cloud.user.dao.AccountDao;
 import com.cloud.utils.Pair;
+import com.cloud.vm.NicProfile;
 import com.cloud.vm.VMInstanceVO;
 import com.cloud.vm.VirtualMachineManager;
 import com.cloud.vm.dao.VMInstanceDao;
@@ -74,6 +78,13 @@ public class CloudOrchestrator implements OrchestrationService {
 	
 	@Inject 
 	protected VirtualMachineEntityFactory _vmEntityFactory;
+
+	@Inject
+	protected NetworkDao _networkDao;
+	
+	@Inject
+	protected AccountDao _accountDao = null;
+
 	
     public VirtualMachineEntity createFromScratch(String uuid, String iso, String os, String hypervisor, String hostName, int cpu, int speed, long memory, List<String> networks, List<String> computeTags,
             Map<String, String> details, String owner) {
@@ -143,28 +154,36 @@ public class CloudOrchestrator implements OrchestrationService {
             Long diskSize,
             List<String> computeTags, 
             List<String> rootDiskTags,
-            List<String> networks, DeploymentPlan plan) throws InsufficientCapacityException {
+            Map<String, NicProfile> networkNicMap, DeploymentPlan plan) throws InsufficientCapacityException {
 
     	// VirtualMachineEntityImpl vmEntity = new VirtualMachineEntityImpl(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, networks, vmEntityManager);
-    	
+
+        List<Pair<NetworkVO, NicProfile>> networkIpMap = new ArrayList<Pair<NetworkVO, NicProfile>>();
+        for (String uuid : networkNicMap.keySet()) {
+            NetworkVO network = _networkDao.findByUuid(uuid);
+            if(network != null){
+                networkIpMap.add(new Pair<NetworkVO, NicProfile>(network, networkNicMap.get(uuid)));
+            }
+        }
+
     	VirtualMachineEntityImpl vmEntity = null;
 		try {
 			vmEntity = _vmEntityFactory.getObject();
 		} catch (Exception e) {
 			// add error handling here
 		}
-    	vmEntity.init(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, networks);
+    	vmEntity.init(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, new ArrayList<String>(networkNicMap.keySet()));
+        
     	
     	HypervisorType hypervisorType = HypervisorType.valueOf(hypervisor);
 
     	//load vm instance and offerings and call virtualMachineManagerImpl
-    	VMInstanceVO vm = _vmDao.findByUUID(id);
+    	VMInstanceVO vm = _vmDao.findByUuid(id);
     	
-		// If the template represents an ISO, a disk offering must be passed in,
-		// and will be used to create the root disk
-		// Else, a disk offering is optional, and if present will be used to
-		// create the data disk
-		Pair<DiskOfferingVO, Long> rootDiskOffering = new Pair<DiskOfferingVO, Long>(null, null);
+		// If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk
+		// Else, a disk offering is optional, and if present will be used to create the data disk
+
+    	Pair<DiskOfferingVO, Long> rootDiskOffering = new Pair<DiskOfferingVO, Long>(null, null);
 		List<Pair<DiskOfferingVO, Long>> dataDiskOfferings = new ArrayList<Pair<DiskOfferingVO, Long>>();
  
 		ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getServiceOfferingId());
@@ -172,8 +191,7 @@ public class CloudOrchestrator implements OrchestrationService {
 
 		DiskOfferingVO diskOffering = _diskOfferingDao.findById(vm.getDiskOfferingId());
 		if (diskOffering == null) {
-			throw new InvalidParameterValueException(
-					"Unable to find disk offering " + vm.getDiskOfferingId());
+			throw new InvalidParameterValueException("Unable to find disk offering " + vm.getDiskOfferingId());
 		}
 		Long size = null;
 		if (diskOffering.getDiskSize() == 0) {
@@ -186,7 +204,8 @@ public class CloudOrchestrator implements OrchestrationService {
 		}
 		dataDiskOfferings.add(new Pair<DiskOfferingVO, Long>(diskOffering, size));
 		
-    	if (_itMgr.allocate(vm, _templateDao.findById(new Long(templateId)), offering, rootDiskOffering, dataDiskOfferings, null, null,	plan, hypervisorType, null) == null) {
+		
+    	if (_itMgr.allocate(vm, _templateDao.findById(new Long(templateId)), offering, rootDiskOffering, dataDiskOfferings, networkIpMap, null,	plan, hypervisorType, _accountDao.findById(new Long(owner))) == null) {
 			return null;
 		}
     	
@@ -195,7 +214,7 @@ public class CloudOrchestrator implements OrchestrationService {
 
     @Override
     public VirtualMachineEntity createVirtualMachineFromScratch(String id, String owner, String isoId, String hostName, String displayName, String hypervisor, String os, int cpu, int speed, long memory,Long diskSize,
-            List<String> computeTags, List<String> rootDiskTags, List<String> networks, DeploymentPlan plan)  throws InsufficientCapacityException {
+            List<String> computeTags, List<String> rootDiskTags, Map<String, NicProfile> networkNicMap, DeploymentPlan plan)  throws InsufficientCapacityException {
 		
     	// VirtualMachineEntityImpl vmEntity = new VirtualMachineEntityImpl(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, networks, vmEntityManager);
     	VirtualMachineEntityImpl vmEntity = null;
@@ -204,10 +223,10 @@ public class CloudOrchestrator implements OrchestrationService {
 		} catch (Exception e) {
 			// add error handling here
 		}
-    	vmEntity.init(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, networks);
+    	vmEntity.init(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, new ArrayList<String>(networkNicMap.keySet()));
 
     	//load vm instance and offerings and call virtualMachineManagerImpl
-    	VMInstanceVO vm = _vmDao.findByUUID(id);
+    	VMInstanceVO vm = _vmDao.findByUuid(id);
     	
     	
 		Pair<DiskOfferingVO, Long> rootDiskOffering = new Pair<DiskOfferingVO, Long>(null, null);
@@ -251,4 +270,10 @@ public class CloudOrchestrator implements OrchestrationService {
         return null;
     }
 
+	@Override
+	public VirtualMachineEntity getVirtualMachine(String id) {
+		VirtualMachineEntityImpl vmEntity = new VirtualMachineEntityImpl(id, vmEntityManager);
+		return vmEntity;
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/94e8090b/server/src/com/cloud/deploy/FirstFitPlanner.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/deploy/FirstFitPlanner.java b/server/src/com/cloud/deploy/FirstFitPlanner.java
index c0b72e7..787d1c1 100755
--- a/server/src/com/cloud/deploy/FirstFitPlanner.java
+++ b/server/src/com/cloud/deploy/FirstFitPlanner.java
@@ -734,31 +734,35 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
             //If the plan specifies a poolId, it means that this VM's ROOT volume is ready and the pool should be reused.
             //In this case, also check if rest of the volumes are ready and can be reused.
             if(plan.getPoolId() != null){
-                if (toBeCreated.getState() == Volume.State.Ready && toBeCreated.getPoolId() != null) {
-                    s_logger.debug("Volume is in READY state and has pool already allocated, checking if pool can be reused, poolId: "+toBeCreated.getPoolId());
-                    List<StoragePool> suitablePools = new ArrayList<StoragePool>();
-                    StoragePoolVO pool = _storagePoolDao.findById(toBeCreated.getPoolId());
-                    if(!pool.isInMaintenance()){
-                        if(!avoid.shouldAvoid(pool)){
-                            long exstPoolDcId = pool.getDataCenterId();
-
-                            long exstPoolPodId = pool.getPodId() != null ? pool.getPodId() : -1;
-                            long exstPoolClusterId = pool.getClusterId() != null ? pool.getClusterId() : -1;
-                            if(plan.getDataCenterId() == exstPoolDcId && plan.getPodId() == exstPoolPodId && plan.getClusterId() == exstPoolClusterId){
-                                s_logger.debug("Planner need not allocate a pool for this volume since its READY");
-                                suitablePools.add(pool);
-                                suitableVolumeStoragePools.put(toBeCreated, suitablePools);
-                                readyAndReusedVolumes.add(toBeCreated);
-                                continue;
-                            }else{
-                                s_logger.debug("Pool of the volume does not fit the specified plan, need to reallocate a pool for this volume");
-                            }
+                s_logger.debug("Volume has pool already allocated, checking if pool can be reused, poolId: "+toBeCreated.getPoolId());
+                List<StoragePool> suitablePools = new ArrayList<StoragePool>();
+                StoragePoolVO pool;
+                if(toBeCreated.getPoolId() != null){
+                    pool = _storagePoolDao.findById(toBeCreated.getPoolId());
+                }else{
+                    pool = _storagePoolDao.findById(plan.getPoolId());
+                }
+                
+                if(!pool.isInMaintenance()){
+                    if(!avoid.shouldAvoid(pool)){
+                        long exstPoolDcId = pool.getDataCenterId();
+
+                        long exstPoolPodId = pool.getPodId() != null ? pool.getPodId() : -1;
+                        long exstPoolClusterId = pool.getClusterId() != null ? pool.getClusterId() : -1;
+                        if(plan.getDataCenterId() == exstPoolDcId && plan.getPodId() == exstPoolPodId && plan.getClusterId() == exstPoolClusterId){
+                            s_logger.debug("Planner need not allocate a pool for this volume since its READY");
+                            suitablePools.add(pool);
+                            suitableVolumeStoragePools.put(toBeCreated, suitablePools);
+                            readyAndReusedVolumes.add(toBeCreated);
+                            continue;
                         }else{
-                            s_logger.debug("Pool of the volume is in avoid set, need to reallocate a pool for this volume");
+                            s_logger.debug("Pool of the volume does not fit the specified plan, need to reallocate a pool for this volume");
                         }
                     }else{
-                        s_logger.debug("Pool of the volume is in maintenance, need to reallocate a pool for this volume");
+                        s_logger.debug("Pool of the volume is in avoid set, need to reallocate a pool for this volume");
                     }
+                }else{
+                    s_logger.debug("Pool of the volume is in maintenance, need to reallocate a pool for this volume");
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/94e8090b/server/src/com/cloud/network/security/SecurityManagerMBeanImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/security/SecurityManagerMBeanImpl.java b/server/src/com/cloud/network/security/SecurityManagerMBeanImpl.java
index 9328190..90340d7 100644
--- a/server/src/com/cloud/network/security/SecurityManagerMBeanImpl.java
+++ b/server/src/com/cloud/network/security/SecurityManagerMBeanImpl.java
@@ -141,7 +141,7 @@ public class SecurityManagerMBeanImpl extends StandardMBean implements SecurityG
     @Override
     public void simulateVmStart(Long vmId) {
         //all we need is the vmId
-        VMInstanceVO vm = new VMInstanceVO(vmId, 5, "foo", "foo", Type.User, null, HypervisorType.Any, 8, 1, 1, false, false);
+        VMInstanceVO vm = new VMInstanceVO(vmId, 5, "foo", "foo", Type.User, null, HypervisorType.Any, 8, 1, 1, false, false,null);
         _sgMgr.handleVmStarted(vm);
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/94e8090b/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index bf3da4c..b6042a1 100644
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -50,6 +50,7 @@ import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
 import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
 import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
 import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
+
 import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity;
 import org.apache.cloudstack.engine.service.api.OrchestrationService;
 import org.apache.commons.codec.binary.Base64;
@@ -97,12 +98,14 @@ import com.cloud.dc.dao.DataCenterDao;
 import com.cloud.dc.dao.HostPodDao;
 import com.cloud.deploy.DataCenterDeployment;
 import com.cloud.deploy.DeployDestination;
+import com.cloud.deploy.DeploymentPlanner.ExcludeList;
 import com.cloud.domain.DomainVO;
 import com.cloud.domain.dao.DomainDao;
 import com.cloud.event.ActionEvent;
 import com.cloud.event.EventTypes;
 import com.cloud.event.UsageEventVO;
 import com.cloud.event.dao.UsageEventDao;
+import com.cloud.exception.CloudException;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.InvalidParameterValueException;
@@ -542,10 +545,15 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
         Account account = _accountDao.findById(user.getAccountId());
 
         try {
-            status = _itMgr.stop(vm, user, account);
+            VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
+            status = vmEntity.stop(new Long(userId).toString());            
         } catch (ResourceUnavailableException e) {
             s_logger.debug("Unable to stop due to ", e);
             status = false;
+        } catch (CloudException e) {
+            throw new CloudRuntimeException(
+                    "Unable to contact the agent to stop the virtual machine "
+                            + vm, e);
         }
 
         if (status) {
@@ -2903,8 +2911,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
         }
 
         List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>();
-
-        List<String> networkUuidList = new ArrayList<String>();
+       
+        Map<String, NicProfile> networkNicMap = new HashMap<String, NicProfile>();
 
         short defaultNetworkNumber = 0;
         boolean securityGroupEnabled = false;
@@ -2948,7 +2956,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
                 vpcNetwork = true;
             }
 
-            networkUuidList.add(network.getUuid());
+            networkNicMap.put(network.getUuid(), profile);
         }
 
         if (securityGroupIdList != null && !securityGroupIdList.isEmpty()
@@ -3030,7 +3038,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
                 template.getId(), hypervisorType, template.getGuestOSId(),
                 offering.getOfferHA(), offering.getLimitCpuUse(),
                 owner.getDomainId(), owner.getId(), offering.getId(), userData,
-                hostName);
+                hostName, diskOfferingId);
         vm.setUuid(uuidName);
 
         if (sshPublicKey != null) {
@@ -3063,9 +3071,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
         rootDiskTags.add(offering.getTags());
 
         if(isIso){
-            VirtualMachineEntity vmEntity = _orchSrvc.createVirtualMachineFromScratch(vm.getUuid(), owner.getAccountName(), vm.getIsoId().toString(), hostName, displayName, hypervisor.name(), guestOSCategory.getName(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize,  computeTags, rootDiskTags, networkUuidList, plan);
+            VirtualMachineEntity vmEntity = _orchSrvc.createVirtualMachineFromScratch(vm.getUuid(), new Long(owner.getAccountId()).toString(), vm.getIsoId().toString(), hostName, displayName, hypervisor.name(), guestOSCategory.getName(), offering.getCpu(), offering.getSpeed(), offering.getRamSize(), diskSize,  computeTags, rootDiskTags, networkNicMap, plan);
         }else {
-            VirtualMachineEntity vmEntity = _orchSrvc.createVirtualMachine(vm.getUuid(), owner.getAccountName(), new Long(template.getId()).toString(), hostName, displayName, hypervisor.name(), offering.getCpu(),  offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkUuidList, plan);
+            VirtualMachineEntity vmEntity = _orchSrvc.createVirtualMachine(vm.getUuid(), new Long(owner.getAccountId()).toString(), new Long(template.getId()).toString(), hostName, displayName, hypervisor.name(), offering.getCpu(),  offering.getSpeed(), offering.getRamSize(), diskSize, computeTags, rootDiskTags, networkNicMap, plan);
         }
 
         if (s_logger.isDebugEnabled()) {
@@ -3377,12 +3385,13 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
         UserVO user = _userDao.findById(userId);
 
         try {
-            _itMgr.advanceStop(vm, forced, user, caller);
+            VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
+            vmEntity.stop(new Long(userId).toString());            
         } catch (ResourceUnavailableException e) {
             throw new CloudRuntimeException(
                     "Unable to contact the agent to stop the virtual machine "
                             + vm, e);
-        } catch (OperationTimedoutException e) {
+        } catch (CloudException e) {
             throw new CloudRuntimeException(
                     "Unable to contact the agent to stop the virtual machine "
                             + vm, e);
@@ -3533,16 +3542,17 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
             params.put(VirtualMachineProfile.Param.VmPassword, password);
         }
 
-        vm = _itMgr.start(vm, params, callerUser, callerAccount, plan);
+        VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
+        
+        String reservationId = vmEntity.reserve("FirstFitPlanner", plan, new ExcludeList(), new Long(callerUser.getId()).toString());
+        vmEntity.deploy(reservationId, new Long(callerUser.getId()).toString());
 
-        Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmParamPair = new Pair(
-                vm, params);
+        Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmParamPair = new Pair(vm, params);
         if (vm != null && vm.isUpdateParameters()) {
             // this value is not being sent to the backend; need only for api
             // display purposes
             if (template.getEnablePassword()) {
-                vm.setPassword((String) vmParamPair.second().get(
-                        VirtualMachineProfile.Param.VmPassword));
+                vm.setPassword((String) vmParamPair.second().get(VirtualMachineProfile.Param.VmPassword));
                 vm.setUpdateParameters(false);
                 _vmDao.update(vm.getId(), vm);
             }
@@ -3579,8 +3589,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
         State vmState = vm.getState();
 
         try {
-            status = _itMgr.destroy(vm, userCaller, caller);
-        } catch (OperationTimedoutException e) {
+            VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
+            status = vmEntity.destroy(new Long(userId).toString());    
+        } catch (CloudException e) {
             CloudRuntimeException ex = new CloudRuntimeException(
                     "Unable to destroy with specified vmId", e);
             ex.addProxyObject(vm, vmId, "vmId");
@@ -4503,4 +4514,5 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
     @Override
     public void prepareStop(VirtualMachineProfile<UserVmVO> profile) {
     }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/94e8090b/server/src/com/cloud/vm/dao/VMInstanceDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/dao/VMInstanceDao.java b/server/src/com/cloud/vm/dao/VMInstanceDao.java
index 3293f61..d34b257 100644
--- a/server/src/com/cloud/vm/dao/VMInstanceDao.java
+++ b/server/src/com/cloud/vm/dao/VMInstanceDao.java
@@ -114,7 +114,5 @@ public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<
      * @return
      */
     List<String> listDistinctHostNames(long networkId, VirtualMachine.Type... types);
-    
-    VMInstanceVO findByUUID(String uuid);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/94e8090b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
index c85b2f6..109c68f 100644
--- a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
+++ b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java
@@ -617,9 +617,4 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
         return result;
     }
 
-	@Override
-	public VMInstanceVO findByUUID(String uuid) {
-		// TODO Auto-generated method stub
-		return null;
-	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/94e8090b/setup/db/4.1-new-db-schema.sql
----------------------------------------------------------------------
diff --git a/setup/db/4.1-new-db-schema.sql b/setup/db/4.1-new-db-schema.sql
index 84fbd91..f52354f 100644
--- a/setup/db/4.1-new-db-schema.sql
+++ b/setup/db/4.1-new-db-schema.sql
@@ -65,3 +65,28 @@ CREATE TABLE `cloud`.`vm_network_map` (
   `network_id` bigint unsigned NOT NULL COMMENT 'network id',
   PRIMARY KEY(`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+
+CREATE TABLE `cloud`.`vm_reservation` (
+  `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `uuid` varchar(40) NOT NULL COMMENT 'reservation id',
+  `vm_id` bigint unsigned NOT NULL COMMENT 'vm id',
+  `datacenter_id` bigint unsigned NOT NULL COMMENT 'zone id',
+  `pod_id` bigint unsigned NOT NULL COMMENT 'pod id',
+  `cluster_id` bigint unsigned NOT NULL COMMENT 'cluster id',
+  `host_id` bigint unsigned NOT NULL COMMENT 'host id',
+  `created` datetime COMMENT 'date created',
+  `removed` datetime COMMENT 'date removed if not null',
+  CONSTRAINT `uc_vm_reservation__uuid` UNIQUE (`uuid`),
+  PRIMARY KEY(`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE `cloud`.`volume_reservation` (
+  `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `vm_reservation_id` bigint unsigned NOT NULL COMMENT 'id of the vm reservation',
+  `vm_id` bigint unsigned NOT NULL COMMENT 'vm id',
+  `volume_id` bigint unsigned NOT NULL COMMENT 'volume id',
+  `pool_id` bigint unsigned NOT NULL COMMENT 'pool assigned to the volume',
+  CONSTRAINT `fk_vm_pool_reservation__vm_reservation_id` FOREIGN KEY (`vm_reservation_id`) REFERENCES `vm_reservation`(`id`) ON DELETE CASCADE,
+  PRIMARY KEY(`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;