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

[1/2] generalize storage orchestration: DataObjectManager will handle all the object life cycle management

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
index f3da368..8cfbae4 100644
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
@@ -22,7 +22,8 @@ import javax.inject.Inject;
 
 import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
 import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
-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.VolumeInfo;
@@ -31,6 +32,7 @@ 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.storage.datastore.DataObjectManager;
 import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
 import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
 import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
@@ -55,6 +57,8 @@ public class VolumeServiceImpl implements VolumeService {
     @Inject
     ObjectInDataStoreManager objectInDataStoreMgr;
     @Inject
+    DataObjectManager dataObjectMgr;
+    @Inject
     ImageMotionService imageMotion;
     @Inject
     TemplateInstallStrategy templateInstallStrategy;
@@ -85,6 +89,8 @@ public class VolumeServiceImpl implements VolumeService {
         
     }
     
+    
+    
     @Override
     public AsyncCallFuture<VolumeApiResult> createVolumeAsync(VolumeInfo volume, long dataStoreId) {
         PrimaryDataStore dataStore = dataStoreMgr.getPrimaryDataStore(dataStoreId);
@@ -107,16 +113,16 @@ public class VolumeServiceImpl implements VolumeService {
         vo.stateTransit(Volume.Event.CreateRequested);
 
         CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, vo, future);
-        AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this);
+        AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
         caller.setCallback(caller.getTarget().createVolumeCallback(null, null))
         .setContext(context);
         
-        //dataStore.createVolumeAsync(vo, null, caller);
+        dataObjectMgr.createAsync(volume, dataStore, caller, true);
         return future;
     }
     
-    protected Void createVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> callback, CreateVolumeContext<VolumeApiResult> context) {
-        CommandResult result = callback.getResult();
+    protected Void createVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeContext<VolumeApiResult> context) {
+        CreateCmdResult result = callback.getResult();
         VolumeObject vo = context.getVolume();
         VolumeApiResult volResult = new VolumeApiResult(vo);
         if (result.isSuccess()) {
@@ -172,7 +178,7 @@ public class VolumeServiceImpl implements VolumeService {
         caller.setCallback(caller.getTarget().deleteVolumeCallback(null, null))
             .setContext(context);
         
-        dataStore.getDriver().deleteAsync(volume, caller);
+        dataObjectMgr.deleteAsync(volume, caller);
         return future;
     }
     
@@ -279,21 +285,23 @@ public class VolumeServiceImpl implements VolumeService {
     
     @DB
     protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, AsyncCallFuture<VolumeApiResult> future) {
-        CreateBaseImageContext<VolumeApiResult> context = new CreateBaseImageContext<VolumeApiResult>(null, volume, 
+        CreateBaseImageContext<CreateCmdResult> context = new CreateBaseImageContext<CreateCmdResult>(null, volume, 
                 dataStore,
                 template,
                 future);
         
-        AsyncCallbackDispatcher<VolumeServiceImpl, CreateBaseImageResult> caller = AsyncCallbackDispatcher.create(this);
-        caller.setCallback(caller.getTarget().createBaseImageCallback(null, null))
+        AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
+        caller.setCallback(caller.getTarget().copyBaseImageCallback(null, null))
         .setContext(context);
-        
-        templateInstallStrategy.installAsync(template, dataStore, caller);
+        DataObject templateOnPrimaryStoreObj = dataObjectMgr.createInternalStateOnly(template, dataStore);
+     
+        dataObjectMgr.copyAsync(context.srcTemplate, templateOnPrimaryStoreObj, caller);
+        return;
     }
-
+    
     @DB
-    protected Void createBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateBaseImageResult> callback, CreateBaseImageContext<VolumeApiResult> context) {
-        CreateBaseImageResult result = callback.getResult();
+    protected Void copyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateBaseImageContext<VolumeApiResult> context) {
+        CreateCmdResult result = callback.getResult();
         VolumeApiResult res = new VolumeApiResult(context.getVolume());
         
         AsyncCallFuture<VolumeApiResult> future = context.getFuture();
@@ -302,23 +310,26 @@ public class VolumeServiceImpl implements VolumeService {
             future.complete(res);
             return null;
         }
-        
-        //now create volume on base image
-        TemplateInfo templateOnPrimaryStoreObj = result.template;
-        VolumeInfo volume = context.getVolume();
-        PrimaryDataStore pd = context.getDataStore();
+        DataObject templateOnPrimaryStoreObj = objectInDataStoreMgr.get(context.srcTemplate, context.dataStore);
 
-        createVolumeFromBaseImageAsync(volume, templateOnPrimaryStoreObj, pd, future);
+        createVolumeFromBaseImageAsync(context.volume, templateOnPrimaryStoreObj, context.dataStore, future);
         return null;
     }
     
     private class CreateVolumeFromBaseImageContext<T> extends AsyncRpcConext<T> {
         private final VolumeObject vo;
         private final AsyncCallFuture<VolumeApiResult> future;
-        public CreateVolumeFromBaseImageContext(AsyncCompletionCallback<T> callback, VolumeObject vo, AsyncCallFuture<VolumeApiResult> future) {
+        private final DataStore primaryStore;
+        private final DataObject templateOnStore;
+        public CreateVolumeFromBaseImageContext(AsyncCompletionCallback<T> callback, VolumeObject vo, 
+                DataStore primaryStore,
+                DataObject templateOnStore,
+                AsyncCallFuture<VolumeApiResult> future) {
             super(callback);
             this.vo = vo;
             this.future = future;
+            this.primaryStore = primaryStore;
+            this.templateOnStore = templateOnStore;
         }
         
         public VolumeObject getVolumeObject() {
@@ -331,7 +342,7 @@ public class VolumeServiceImpl implements VolumeService {
     }
     
     @DB
-    protected void createVolumeFromBaseImageAsync(VolumeInfo volume, TemplateInfo templateOnPrimaryStore, PrimaryDataStore pd, AsyncCallFuture<VolumeApiResult> future) {
+    protected void createVolumeFromBaseImageAsync(VolumeInfo volume, DataObject templateOnPrimaryStore, PrimaryDataStore pd, AsyncCallFuture<VolumeApiResult> future) {
         VolumeObject vo = (VolumeObject) volume;
         try {
             vo.stateTransit(Volume.Event.CreateRequested);
@@ -342,19 +353,22 @@ public class VolumeServiceImpl implements VolumeService {
             return;
         }
 
-        CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, vo, future);
-        AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller =  AsyncCallbackDispatcher.create(this);
-        caller.setCallback(caller.getTarget().createVolumeFromBaseImageCallback(null, null))
+        CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, vo, pd, templateOnPrimaryStore, future);
+        AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller =  AsyncCallbackDispatcher.create(this);
+        caller.setCallback(caller.getTarget().copyBaseImageCallBack(null, null))
         .setContext(context);
 
-       pd.getDriver().copyAsync(volume, templateOnPrimaryStore, caller);
+        DataObject volumeOnPrimaryStorage = dataObjectMgr.createInternalStateOnly(volume, pd);
+        dataObjectMgr.copyAsync(context.templateOnStore, volumeOnPrimaryStorage, caller);
+        return;
     }
     
     @DB
-    public Object createVolumeFromBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
+    public Void copyBaseImageCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
         VolumeObject vo = context.getVolumeObject();
-        CopyCommandResult result = callback.getResult();
+        CreateCmdResult result = callback.getResult();
         VolumeApiResult volResult = new VolumeApiResult(vo);
+       
         if (result.isSuccess()) {
             if (result.getPath() != null) {
                 vo.setPath(result.getPath());

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
index 1aa96c3..06367af 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
@@ -28,22 +28,18 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 
 import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer;
 import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
 import org.apache.cloudstack.storage.command.CopyCmd;
 import org.apache.cloudstack.storage.command.CopyCmdAnswer;
+import org.apache.cloudstack.storage.command.CreateObjectAnswer;
 import org.apache.cloudstack.storage.command.CreateObjectCommand;
 import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd;
-import org.apache.cloudstack.storage.command.CreateObjectAnswer;
 import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand;
 import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
 import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol;
 import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO;
-import org.apache.cloudstack.storage.to.NfsPrimaryDataStoreTO;
-import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
-import org.apache.cloudstack.storage.to.TemplateTO;
 import org.apache.cloudstack.storage.to.VolumeTO;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
@@ -57,8 +53,10 @@ import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.Command;
 import com.cloud.agent.api.storage.DeleteVolumeCommand;
 import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
-import com.cloud.storage.Storage.StoragePoolType;
 import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.storage.encoding.DataStore;
+import com.cloud.utils.storage.encoding.DecodedDataObject;
+import com.cloud.utils.storage.encoding.Decoder;
 import com.xensource.xenapi.Connection;
 import com.xensource.xenapi.Host;
 import com.xensource.xenapi.PBD;
@@ -137,28 +135,23 @@ public class XenServerStorageResource {
     }
     protected CreateObjectAnswer execute(CreateObjectCommand cmd) {
         String uriString = cmd.getObjectUri();
-        Map<String, String> params = null;
-        
-        try {
-            URI uri = new URI(uriString);
-            params = getParameters(uri);
-        } catch (URISyntaxException e1) {
-            s_logger.debug("uri exception", e1);
-            return new CreateObjectAnswer(cmd, false, e1.toString()); 
-        }
-        
-        if (params.get("objType").equalsIgnoreCase("template")) {
-            return getTemplateSize(cmd, params.get("path"));
-        }
-        
-        long size = Long.parseLong(params.get("size"));
-        String name = params.get("name");
-        String storeUuid = params.get("storagePath");
+        DecodedDataObject obj = null;
+
         Connection conn = hypervisorResource.getConnection();
         VDI vdi = null;
         boolean result = false;
         String errorMsg = null;
+        
         try {
+            obj = Decoder.decode(uriString);
+            DataStore store = obj.getStore(); 
+            if (obj.getObjType().equalsIgnoreCase("template") && store.getRole().equalsIgnoreCase("image")) {
+                return getTemplateSize(cmd, obj.getPath());
+            }
+            
+            long size = obj.getSize();
+            String name = obj.getName();
+            String storeUuid = store.getUuid();
             SR primaryDataStoreSR = getSRByNameLabel(conn, storeUuid);
             vdi = createVdi(conn, name, primaryDataStoreSR, size);
             VDI.Record record = vdi.getRecord(conn);
@@ -173,6 +166,9 @@ public class XenServerStorageResource {
         } catch (XmlRpcException e) {
             s_logger.debug("Failed to create volume", e);
             errorMsg = e.toString();
+        } catch (URISyntaxException e) {
+            s_logger.debug("Failed to create volume", e);
+            errorMsg = e.toString();
         } finally {
             if (!result && vdi != null) {
                 try {
@@ -227,13 +223,13 @@ public class XenServerStorageResource {
         }
     }
     
-    protected SR getNfsSR(Connection conn, URI uri) {
+    protected SR getNfsSR(Connection conn, DataStore store) {
         Map<String, String> deviceConfig = new HashMap<String, String>();
-        Map<String, String> params = getParameters(uri);
-        String uuid = params.get("storeUuid");
+
+        String uuid = store.getUuid();
         try {
-            String server = uri.getHost();
-            String serverpath = uri.getPath();
+            String server = store.getServer();
+            String serverpath = store.getPath();
             
             serverpath = serverpath.replace("//", "/");
             Set<SR> srs = SR.getAll(conn);
@@ -410,25 +406,17 @@ public class XenServerStorageResource {
     protected Answer execute(CreatePrimaryDataStoreCmd cmd) {
         Connection conn = hypervisorResource.getConnection();
         String storeUrl = cmd.getDataStore();
-        String scheme = null;
-        String type = null;
-        URI storeUri = null;
-        try {
-            storeUri = new URI(storeUrl);
-        } catch(URISyntaxException e) {
-            return new Answer(cmd, false, e.toString());
-        }
-        
-        scheme = storeUri.getScheme();
-        
+
         try {
-            if (scheme.equalsIgnoreCase("nfs")) {
-                SR sr = getNfsSR(conn, storeUri);
-            } else if (scheme.equalsIgnoreCase("iscsi")) {
+            DecodedDataObject obj = Decoder.decode(storeUrl);
+            DataStore store = obj.getStore();
+            if (store.getScheme().equalsIgnoreCase("nfs")) {
+                SR sr = getNfsSR(conn, store);
+            } else if (store.getScheme().equalsIgnoreCase("iscsi")) {
                 //getIscsiSR(conn, dataStore);
-            } else if (scheme.equalsIgnoreCase("presetup")) {
+            } else if (store.getScheme().equalsIgnoreCase("presetup")) {
             } else {
-                return new Answer(cmd, false, "The pool type: " + scheme + " is not supported.");
+                return new Answer(cmd, false, "The pool type: " + store.getScheme() + " is not supported.");
             }
             return new Answer(cmd, true, "success");
         } catch (Exception e) {
@@ -509,31 +497,30 @@ public class XenServerStorageResource {
        
     }
     
-    protected Answer directDownloadHttpTemplate(CopyCmd cmd, TemplateTO template, PrimaryDataStoreTO primarDataStore) {
-        String primaryStoreUuid = primarDataStore.getUuid();
+    protected Answer directDownloadHttpTemplate(CopyCmd cmd, DecodedDataObject srcObj, DecodedDataObject destObj) {
         Connection conn = hypervisorResource.getConnection();
         SR poolsr = null;
         VDI vdi = null;
         boolean result = false;
         try {
-            
-            Set<SR> srs = SR.getByNameLabel(conn, primaryStoreUuid);
+            if (destObj.getPath() == null) {
+                //need to create volume at first
+                
+            }
+            vdi = VDI.getByUuid(conn, destObj.getPath());
+            if (vdi == null) {
+                throw new CloudRuntimeException("can't find volume: " + destObj.getPath());
+            }
+            String destStoreUuid = destObj.getStore().getUuid();
+            Set<SR> srs = SR.getByNameLabel(conn, destStoreUuid);
             if (srs.size() != 1) {
-                throw new CloudRuntimeException("storage uuid: " + primaryStoreUuid + " is not unique");
+                throw new CloudRuntimeException("storage uuid: " + destStoreUuid + " is not unique");
             }
             poolsr = srs.iterator().next();
-            VDI.Record vdir = new VDI.Record();
-            vdir.nameLabel = "Base-Image-" + UUID.randomUUID().toString();
-            vdir.SR = poolsr;
-            vdir.type = Types.VdiType.USER;
-            
-            vdir.virtualSize = getTemplateSize(conn, template.getPath());
-            vdi = VDI.create(conn, vdir);
-            
-            vdir = vdi.getRecord(conn);
+            VDI.Record vdir = vdi.getRecord(conn);
             String vdiLocation = vdir.location;
             String pbdLocation = null;
-            if (primarDataStore.getType().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) {
+            if (destObj.getStore().getScheme().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) {
                 pbdLocation = "/run/sr-mount/" + poolsr.getUuid(conn);
             } else {
                 Set<PBD> pbds = poolsr.getPBDs(conn);
@@ -551,7 +538,7 @@ public class XenServerStorageResource {
             String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd";
             //download a url into vdipath
             //downloadHttpToLocalFile(vdiPath, template.getPath());
-            hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", template.getPath());
+            hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", srcObj.getPath());
             result = true;
             return new CopyCmdAnswer(cmd, vdi.getUuid(conn));
         } catch (BadServerResponse e) {
@@ -581,16 +568,10 @@ public class XenServerStorageResource {
     protected Answer execute(AttachPrimaryDataStoreCmd cmd) {
         String dataStoreUri = cmd.getDataStore();
         Connection conn = hypervisorResource.getConnection();
-        Map<String, String> params = null;
         try {
-            try {
-                URI uri = new URI(dataStoreUri);
-                params = getParameters(uri);
-            } catch (URISyntaxException e1) {
-                s_logger.debug("uri exception", e1);
-                return new CreateObjectAnswer(cmd, false, e1.toString()); 
-            }
-            SR sr = hypervisorResource.getStorageRepository(conn, params.get("storeUuid"));
+            DecodedDataObject obj = Decoder.decode(dataStoreUri);
+            DataStore store = obj.getStore();
+            SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid());
             hypervisorResource.setupHeartbeatSr(conn, sr, false);
             long capacity = sr.getPhysicalSize(conn);
             long available = capacity - sr.getPhysicalUtilisation(conn);
@@ -616,10 +597,18 @@ public class XenServerStorageResource {
     }
     
     protected Answer execute(CopyCmd cmd) {
-        ImageOnPrimayDataStoreTO imageTO = cmd.getImage();
-        TemplateTO template = imageTO.getTemplate();
-        if (template.getPath().startsWith("http")) {
-            return directDownloadHttpTemplate(cmd, template, imageTO.getPrimaryDataStore());
+        DecodedDataObject srcObj = null;
+        DecodedDataObject destObj = null;
+        try {
+            srcObj = Decoder.decode(cmd.getSrcUri());
+            destObj = Decoder.decode(cmd.getDestUri());
+        } catch (URISyntaxException e) {
+            return new Answer(cmd, false, e.toString());
+        }
+       
+        
+        if (srcObj.getPath().startsWith("http")) {
+            return directDownloadHttpTemplate(cmd, srcObj, destObj);
         } else {
             return new Answer(cmd, false, "not implemented yet");
             /*

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java
index e066dff..04b553c 100644
--- a/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java
@@ -37,7 +37,7 @@ public class VMTemplateDetailsDaoImpl extends GenericDaoBase<VMTemplateDetailVO,
     protected final SearchBuilder<VMTemplateDetailVO> TemplateSearch;
     protected final SearchBuilder<VMTemplateDetailVO> DetailSearch;
     
-	protected VMTemplateDetailsDaoImpl() {
+	public VMTemplateDetailsDaoImpl() {
 		TemplateSearch = createSearchBuilder();
 		TemplateSearch.and("templateId", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
 		TemplateSearch.done();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/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 d541537..e8bafa2 100644
--- a/setup/db/4.1-new-db-schema.sql
+++ b/setup/db/4.1-new-db-schema.sql
@@ -18,6 +18,8 @@
 alter table vm_template add image_data_store_id bigint unsigned;
 alter table vm_template add size bigint unsigned;
 alter table vm_template add state varchar(255);
+alter table vm_template add update_count bigint unsigned;
+alter table vm_template add updated  datetime;
 alter table storage_pool add storage_provider_id bigint unsigned; 
 alter table storage_pool add scope varchar(255); 
 alter table storage_pool modify id bigint unsigned AUTO_INCREMENT UNIQUE NOT NULL;
@@ -67,7 +69,7 @@ CREATE TABLE  `cloud`.`object_datastore_ref` (
   `size` bigint unsigned COMMENT 'the size of the template on the pool',
   `state` varchar(255) NOT NULL,
   `update_count` bigint unsigned NOT NULL,
-  `updated` DATETIME NOT NULL,
+  `updated` DATETIME,
   PRIMARY KEY  (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;