cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kis...@apache.org
Subject [11/50] [abbrv] git commit: updated refs/heads/network_acl to 1609d01
Date Fri, 03 May 2013 13:14:53 GMT
Apply patch for https://reviews.apache.org/r/10892/


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/f1012410
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/f1012410
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/f1012410

Branch: refs/heads/network_acl
Commit: f1012410503edf4f7fd624ecf4f5004bea0ac9a1
Parents: 48540dc
Author: Kelven Yang <kelveny@gmail.com>
Authored: Wed May 1 17:40:23 2013 -0700
Committer: Kelven Yang <kelveny@gmail.com>
Committed: Wed May 1 17:40:38 2013 -0700

----------------------------------------------------------------------
 .../agent/api/storage/CreateVolumeOVAAnswer.java   |   26 +
 .../agent/api/storage/CreateVolumeOVACommand.java  |   60 +++
 .../agent/api/storage/PrepareOVAPackingAnswer.java |   26 +
 .../api/storage/PrepareOVAPackingCommand.java      |   48 ++
 .../command/user/snapshot/CreateSnapshotCmd.java   |    2 +
 .../storage/resource/StoragePoolResource.java      |    4 +
 .../src/com/cloud/hypervisor/guru/VMwareGuru.java  |   12 +
 .../vmware/manager/VmwareStorageManager.java       |    4 +
 .../vmware/manager/VmwareStorageManagerImpl.java   |  401 +++++++++++++--
 .../hypervisor/vmware/resource/VmwareResource.java |   48 ++
 .../VmwareSecondaryStorageResourceHandler.java     |   24 +
 .../src/com/cloud/server/ManagementServerImpl.java |   17 +-
 .../cloud/template/HypervisorTemplateAdapter.java  |   78 +++
 server/src/com/cloud/template/TemplateAdapter.java |    3 +
 .../com/cloud/template/TemplateAdapterBase.java    |   13 +
 .../com/cloud/template/TemplateManagerImpl.java    |    7 +
 .../hypervisor/vmware/mo/VirtualMachineMO.java     |    6 +-
 17 files changed, 724 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/api/src/com/cloud/agent/api/storage/CreateVolumeOVAAnswer.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/storage/CreateVolumeOVAAnswer.java b/api/src/com/cloud/agent/api/storage/CreateVolumeOVAAnswer.java
new file mode 100755
index 0000000..52a57db
--- /dev/null
+++ b/api/src/com/cloud/agent/api/storage/CreateVolumeOVAAnswer.java
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent.api.storage;
+
+import com.cloud.agent.api.Answer;
+
+public class CreateVolumeOVAAnswer extends Answer {
+    public CreateVolumeOVAAnswer(CreateVolumeOVACommand cmd, boolean result, String details) {
+        super(cmd, result, details);
+    }
+
+} 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/api/src/com/cloud/agent/api/storage/CreateVolumeOVACommand.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/storage/CreateVolumeOVACommand.java b/api/src/com/cloud/agent/api/storage/CreateVolumeOVACommand.java
new file mode 100755
index 0000000..224b7c80
--- /dev/null
+++ b/api/src/com/cloud/agent/api/storage/CreateVolumeOVACommand.java
@@ -0,0 +1,60 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent.api.storage;
+
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.storage.StoragePool;
+
+public class CreateVolumeOVACommand extends Command {
+        String secUrl;
+        String volPath;
+        String volName;
+        StorageFilerTO pool;
+
+        public CreateVolumeOVACommand() {
+        }
+
+        public CreateVolumeOVACommand(String secUrl, String volPath, String volName, StoragePool pool, int wait) {
+        this.secUrl = secUrl;
+        this.volPath = volPath;
+        this.volName = volName;
+        this.pool = new StorageFilerTO(pool);
+        setWait(wait);
+   }
+
+        @Override
+    public boolean executeInSequence() {
+        return true;
+    }
+
+        public String getVolPath() {
+                return this.volPath;
+        }
+
+        public String getVolName() {
+                return this.volName;
+        }
+        public String getSecondaryStorageUrl() {
+                return this.secUrl;
+    }
+    public StorageFilerTO getPool() {
+            return pool;
+    }
+}
+
+ 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/api/src/com/cloud/agent/api/storage/PrepareOVAPackingAnswer.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/storage/PrepareOVAPackingAnswer.java b/api/src/com/cloud/agent/api/storage/PrepareOVAPackingAnswer.java
new file mode 100755
index 0000000..923d952
--- /dev/null
+++ b/api/src/com/cloud/agent/api/storage/PrepareOVAPackingAnswer.java
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent.api.storage;
+
+import com.cloud.agent.api.Answer;
+
+public class PrepareOVAPackingAnswer extends Answer {
+    public PrepareOVAPackingAnswer(PrepareOVAPackingCommand cmd, boolean result, String details) {
+        super(cmd, result, details);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/api/src/com/cloud/agent/api/storage/PrepareOVAPackingCommand.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/storage/PrepareOVAPackingCommand.java b/api/src/com/cloud/agent/api/storage/PrepareOVAPackingCommand.java
new file mode 100755
index 0000000..29fa26d
--- /dev/null
+++ b/api/src/com/cloud/agent/api/storage/PrepareOVAPackingCommand.java
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent.api.storage;
+
+import com.cloud.agent.api.Command;
+
+public class PrepareOVAPackingCommand extends Command {
+        private String templatePath;
+        private String secUrl;
+
+        public PrepareOVAPackingCommand() {
+        }
+
+        public PrepareOVAPackingCommand(String secUrl, String templatePath) {
+            this.secUrl = secUrl;
+            this.templatePath = templatePath;
+        }
+
+        @Override
+        public boolean executeInSequence() {
+                return true;
+        }
+
+        public String getTemplatePath() {
+                return this.templatePath;
+        }
+
+        public String getSecondaryStorageUrl() {
+                return this.secUrl;
+        }
+
+}
+
+ 
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
index 95d7659..0b33f56 100644
--- a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
@@ -163,6 +163,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
 
     @Override
     public void execute() {
+        s_logger.info("VOLSS: createSnapshotCmd starts:" + System.currentTimeMillis());
         UserContext.current().setEventDetails("Volume Id: "+getVolumeId());
         Snapshot snapshot = _snapshotService.createSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()));
         if (snapshot != null) {
@@ -172,6 +173,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
         } else {
             throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create snapshot due to an internal error creating snapshot for volume " + volumeId);
         }
+        s_logger.info("VOLSS:  backupSnapshotCmd finishes:" + System.currentTimeMillis());
     }
 
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/core/src/com/cloud/storage/resource/StoragePoolResource.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/resource/StoragePoolResource.java b/core/src/com/cloud/storage/resource/StoragePoolResource.java
index 5d352b0..fccfd0f 100644
--- a/core/src/com/cloud/storage/resource/StoragePoolResource.java
+++ b/core/src/com/cloud/storage/resource/StoragePoolResource.java
@@ -21,6 +21,8 @@ import com.cloud.agent.api.storage.CopyVolumeAnswer;
 import com.cloud.agent.api.storage.CopyVolumeCommand;
 import com.cloud.agent.api.storage.CreateAnswer;
 import com.cloud.agent.api.storage.CreateCommand;
+import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
+import com.cloud.agent.api.storage.CreateVolumeOVACommand;
 import com.cloud.agent.api.storage.DestroyCommand;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
@@ -34,5 +36,7 @@ public interface StoragePoolResource {
     
     CopyVolumeAnswer execute(CopyVolumeCommand cmd);
     
+    CreateVolumeOVAAnswer execute(CreateVolumeOVACommand cmd);
+
     CreateAnswer execute(CreateCommand cmd);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
index ee1b324..55bb1e9 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
@@ -38,6 +38,8 @@ import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
 import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
 import com.cloud.agent.api.UnregisterVMCommand;
 import com.cloud.agent.api.storage.CopyVolumeCommand;
+import com.cloud.agent.api.storage.CreateVolumeOVACommand;
+import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
 import com.cloud.agent.api.to.NicTO;
 import com.cloud.agent.api.to.VirtualMachineTO;
@@ -282,10 +284,18 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
                 cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
                 cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
                 cmd instanceof CopyVolumeCommand ||
+                cmd instanceof CreateVolumeOVACommand ||
+                cmd instanceof PrepareOVAPackingCommand ||
                 cmd instanceof CreateVolumeFromSnapshotCommand) {
             needDelegation = true;
         }
+        /* Fang: remove this before checking in */
+        // needDelegation = false;
 
+        if (cmd instanceof PrepareOVAPackingCommand ||
+                cmd instanceof CreateVolumeOVACommand	) {
+                cmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
+        }
         if(needDelegation) {
             HostVO host = _hostDao.findById(hostId);
             assert(host != null);
@@ -311,6 +321,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
                         cmd instanceof CreatePrivateTemplateFromVolumeCommand || 
                         cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
                         cmd instanceof CopyVolumeCommand ||
+                        cmd instanceof CreateVolumeOVACommand ||
+                        cmd instanceof PrepareOVAPackingCommand ||
                         cmd instanceof CreateVolumeFromSnapshotCommand) {
 
                     String workerName = _vmwareMgr.composeWorkerName();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java
index a2e517d..8c0603e 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java
@@ -25,6 +25,8 @@ import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
 import com.cloud.agent.api.DeleteVMSnapshotCommand;
 import com.cloud.agent.api.RevertToVMSnapshotCommand;
 import com.cloud.agent.api.storage.CopyVolumeCommand;
+import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
+import com.cloud.agent.api.storage.CreateVolumeOVACommand;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
 
 public interface VmwareStorageManager {
@@ -33,6 +35,8 @@ public interface VmwareStorageManager {
     Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromVolumeCommand cmd);
     Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromSnapshotCommand cmd);
     Answer execute(VmwareHostService hostService, CopyVolumeCommand cmd);
+	Answer execute(VmwareHostService hostService, CreateVolumeOVACommand cmd);
+	Answer execute(VmwareHostService hostService, PrepareOVAPackingCommand cmd);
     Answer execute(VmwareHostService hostService, CreateVolumeFromSnapshotCommand cmd);
     Answer execute(VmwareHostService hostService, CreateVMSnapshotCommand cmd);
     Answer execute(VmwareHostService hostService, DeleteVMSnapshotCommand cmd);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
index 1f11645..9f1351e 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
@@ -18,12 +18,14 @@ package com.cloud.hypervisor.vmware.manager;
 
 import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.OutputStreamWriter;
 import java.rmi.RemoteException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Properties;
 import java.util.Map;
 import java.util.UUID;
 
@@ -44,6 +46,10 @@ import com.cloud.agent.api.RevertToVMSnapshotAnswer;
 import com.cloud.agent.api.RevertToVMSnapshotCommand;
 import com.cloud.agent.api.storage.CopyVolumeAnswer;
 import com.cloud.agent.api.storage.CopyVolumeCommand;
+import com.cloud.agent.api.storage.PrepareOVAPackingAnswer;
+import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
+import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
+import com.cloud.agent.api.storage.CreateVolumeOVACommand;
 import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
@@ -102,6 +108,109 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
         _timeout = NumbersUtil.parseInt(value, 1440) * 1000;
     }
 
+    //Fang note: use Answer here instead of the PrepareOVAPackingAnswer
+    @Override
+    public Answer execute(VmwareHostService hostService, PrepareOVAPackingCommand cmd) {
+		String secStorageUrl = ((PrepareOVAPackingCommand) cmd).getSecondaryStorageUrl();
+		assert (secStorageUrl != null);
+        String installPath = cmd.getTemplatePath();
+        String details = null;
+		boolean success = false;
+		String ovafileName = "";
+		s_logger.info("Fang: execute OVAPacking cmd at vmwareMngImpl. ");
+	    String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
+	     //   String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
+	    String installFullPath = secondaryMountPoint + "/" + installPath;
+
+	    String templateName = installFullPath;   // should be a file ending .ova;
+	    s_logger.info("Fang: execute vmwareMgrImpl: templateNAme " + templateName);
+		// Fang: Dir list, if there is ova file, done; Fang: add answer cmd;
+		// if not, from ova.meta, create a new OVA file;
+		// change the install path to *.ova , not ova.meta;
+	    // VmwareContext context = hostService.getServiceContext(cmd);  //Fang: we may not have the CTX here
+	    try {
+		if (templateName.endsWith(".ova")) {
+			if(new File(templateName).exists())  {
+				details = "OVA files exists. succeed. ";
+				return new Answer(cmd, true, details);
+			} else {
+				if (new File(templateName + ".meta").exists()) { //Fang parse the meta file
+				    //execute the tar command;
+					s_logger.info("Fang: execute vmwareMgrImpl: getfromMeta " + templateName);
+					ovafileName = getOVAFromMetafile(templateName + ".meta");
+                           details =  "OVA file in meta file is " + ovafileName;
+                           return  new Answer(cmd, true, details);
+				}  else {
+				    String msg = "Unable to find ova meta or ova file to prepare template (vmware)";
+				    s_logger.error(msg);
+				    throw new Exception(msg);
+			    }
+		   }
+		}
+            } catch (Throwable e) {
+                     if (e instanceof RemoteException) {
+                          //hostService.invalidateServiceContext(context); do not need context
+                          s_logger.error("Unable to connect to remote service ");
+                          details = "Unable to connect to remote service ";
+                          return new Answer(cmd, false, details);
+                     }
+                    String msg = "Unable to execute PrepareOVAPackingCommand due to exception";
+                     s_logger.error(msg, e);
+                     return new Answer(cmd, false, details);
+            }
+		return new Answer(cmd, true, details);
+    }
+
+    //Fang: new command added;
+    // Important! we need to sync file system before we can safely use tar to work around a linux kernal bug(or feature)
+    @Override
+    public Answer execute(VmwareHostService hostService, CreateVolumeOVACommand cmd) {
+		String secStorageUrl = ((CreateVolumeOVACommand) cmd).getSecondaryStorageUrl();
+		assert (secStorageUrl != null);
+        String installPath = cmd.getVolPath();
+        String details = null;
+		boolean success = false;
+
+		s_logger.info("volss: execute CreateVolumeOVA cmd at vmwareMngImpl. ");
+	    String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
+	     //   String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
+	    s_logger.info("volss: mountPoint: " + secondaryMountPoint + "installPath:" + installPath);
+	    String installFullPath = secondaryMountPoint + "/" + installPath;
+
+	    String volName = cmd.getVolName();   // should be a UUID, without ova ovf, etc;
+	    s_logger.info("volss: execute vmwareMgrImpl: VolName " + volName);
+		// Fang: Dir list, if there is ova file, done; Note: add answer cmd;
+
+	    try {
+		if(new File(volName + ".ova").exists())  {
+				details = "OVA files exists. succeed. ";
+				return new CreateVolumeOVAAnswer(cmd, true, details);
+	    } else {
+	      File ovaFile = new File(installFullPath);
+	      String exportDir = ovaFile.getParent();
+
+              s_logger.info("Fang: exportDir is (for VolumeOVA): " + exportDir);
+          s_logger.info("Sync file system before we package OVA...");
+
+          Script commandSync = new Script(true, "sync", 0, s_logger);
+          commandSync.execute();
+
+          Script command = new Script(false, "tar", 0, s_logger);
+          command.setWorkDir(exportDir);
+          command.add("-cf", volName + ".ova");
+          command.add(volName + ".ovf");		// OVF file should be the first file in OVA archive
+          command.add(volName + "-disk0.vmdk");
+
+          s_logger.info("Package Volume OVA with commmand: " + command.toString());
+          command.execute();
+          return new CreateVolumeOVAAnswer(cmd, true, details);
+         }
+	    } catch (Throwable e) {
+                s_logger.info("Exception for createVolumeOVA");
+	    }
+             return new CreateVolumeOVAAnswer(cmd, true, "fail to pack OVA for volume");
+       }
+
     @Override
     public Answer execute(VmwareHostService hostService, PrimaryStorageDownloadCommand cmd) {
 		String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
@@ -570,11 +679,14 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
         String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
         String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
         String installFullPath = secondaryMountPoint + "/" + installPath;
-        String installFullName = installFullPath + "/" + templateUniqueName + ".ova";
-        String snapshotFullName = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId)
-            + "/" + backedUpSnapshotUuid + ".ova";
+        String installFullOVAName = installFullPath + "/" + templateUniqueName + ".ova";  //Note: volss for tmpl
+        String snapshotRoot = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId);
+        String snapshotFullOVAName = snapshotRoot + "/" + backedUpSnapshotUuid + ".ova";
+        String snapshotFullOvfName = snapshotRoot + "/" + backedUpSnapshotUuid + ".ovf";
         String result;
         Script command;
+        String templateVMDKName = "";
+        String snapshotFullVMDKName = snapshotRoot + "/";
 
         synchronized(installPath.intern()) {
             command = new Script(false, "mkdir", _timeout, s_logger);
@@ -591,40 +703,85 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
         }
 
         try {
-            command = new Script(false, "cp", _timeout, s_logger);
-            command.add(snapshotFullName);
-            command.add(installFullName);
-            result = command.execute();
-            if(result != null) {
-                String msg = "unable to copy snapshot " + snapshotFullName + " to " + installFullPath;
-                s_logger.error(msg);
-                throw new Exception(msg);
-            }
+            if(new File(snapshotFullOVAName).exists()) {
+                command = new Script(false, "cp", _timeout, s_logger);
+                command.add(snapshotFullOVAName);
+                command.add(installFullOVAName);
+                result = command.execute();
+                if(result != null) {
+                   String msg = "unable to copy snapshot " + snapshotFullOVAName + " to " + installFullPath;
+                   s_logger.error(msg);
+                   throw new Exception(msg);
+                }
 
-            // untar OVA file at template directory
-            command = new Script("tar", 0, s_logger);
-            command.add("--no-same-owner");
-            command.add("-xf", installFullName);
-            command.setWorkDir(installFullPath);
-            s_logger.info("Executing command: " + command.toString());
-            result = command.execute();
-            if(result != null) {
-                String msg = "unable to untar snapshot " + snapshotFullName + " to "
-                    + installFullPath;
+                // untar OVA file at template directory
+                command = new Script("tar", 0, s_logger);
+                command.add("--no-same-owner");
+                command.add("-xf", installFullOVAName);
+                command.setWorkDir(installFullPath);
+                s_logger.info("Executing command: " + command.toString());
+                result = command.execute();
+                if(result != null) {
+                   String msg = "unable to untar snapshot " + snapshotFullOVAName + " to "
+                     + installFullPath;
+                   s_logger.error(msg);
+                   throw new Exception(msg);
+                }
+
+            } else {  // there is no ova file, only ovf originally;
+                if(new File(snapshotFullOvfName).exists()) {
+                     command = new Script(false, "cp", _timeout, s_logger);
+                     command.add(snapshotFullOvfName);
+                     //command.add(installFullOvfName);
+                     command.add(installFullPath);
+                     result = command.execute();
+                     if(result != null) {
+                        String msg = "unable to copy snapshot " + snapshotFullOvfName + " to " + installFullPath;
+                        s_logger.error(msg);
+                        throw new Exception(msg);
+                     }
+
+                     File snapshotdir = new File(snapshotRoot);
+                     File[] ssfiles = snapshotdir.listFiles();
+                     // List<String> filenames = new ArrayList<String>();
+                     for (int i = 0; i < ssfiles.length; i++) {
+                         String vmdkfile = ssfiles[i].getName();
+                         if(vmdkfile.toLowerCase().startsWith(backedUpSnapshotUuid) && vmdkfile.toLowerCase().endsWith(".vmdk")) {
+                              snapshotFullVMDKName += vmdkfile;
+                              templateVMDKName += vmdkfile;
+                              break;
+                          }
+                     }
+                 if (snapshotFullVMDKName != null) {
+                        command = new Script(false, "cp", _timeout, s_logger);
+                        command.add(snapshotFullVMDKName);
+                        command.add(installFullPath);
+                        result = command.execute();
+                        s_logger.info("Copy VMDK file: " + snapshotFullVMDKName);
+                        if(result != null) {
+                            String msg = "unable to copy snapshot vmdk file " + snapshotFullVMDKName + " to " + installFullPath;
+                            s_logger.error(msg);
+                            throw new Exception(msg);
+                        }
+                 }
+            } else {
+                String msg = "unable to find any snapshot ova/ovf files" + snapshotFullOVAName + " to " + installFullPath;
                 s_logger.error(msg);
                 throw new Exception(msg);
+              }
             }
 
-            long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
+            long physicalSize = new File(installFullPath + "/" + templateVMDKName).length();
             VmdkProcessor processor = new VmdkProcessor();
+              // long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
             Map<String, Object> params = new HashMap<String, Object>();
             params.put(StorageLayer.InstanceConfigKey, _storage);
             processor.configure("VMDK Processor", params);
             long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
 
             postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);
+            writeMetaOvaForTemplate(installFullPath, backedUpSnapshotUuid + ".ovf", templateVMDKName, templateUniqueName, physicalSize);
             return new Ternary<String, Long, Long>(installPath + "/" + templateUniqueName + ".ova", physicalSize, virtualSize);
-
         } catch(Exception e) {
             // TODO, clean up left over files
             throw e;
@@ -648,7 +805,8 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
             out.newLine();
             out.write("size=" + size);
             out.newLine();
-            out.write("ova=true");
+            //out.write("ova=true");
+            out.write("ova=false");  //volss: the real ova file is not created
             out.newLine();
             out.write("id=" + templateId);
             out.newLine();
@@ -670,6 +828,31 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
         }
     }
 
+    private void writeMetaOvaForTemplate(String installFullPath, String ovfFilename, String vmdkFilename,
+            String templateName, long diskSize) throws Exception {
+
+            // TODO a bit ugly here
+            BufferedWriter out = null;
+            try {
+                out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(installFullPath + "/" + templateName +".ova.meta")));
+                out.write("ova.filename=" + templateName + ".ova");
+                out.newLine();
+                out.write("version=1.0");
+                out.newLine();
+                out.write("ovf=" + ovfFilename);
+                out.newLine();
+                out.write("numDisks=1");
+                out.newLine();
+                out.write("disk1.name=" + vmdkFilename);
+                out.newLine();
+                out.write("disk1.size=" + diskSize);
+                out.newLine();
+            } finally {
+                if(out != null)
+                    out.close();
+            }
+     }
+
     private String createVolumeFromSnapshot(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName,
         long accountId, long volumeId, String secStorageUrl, String snapshotBackupUuid) throws Exception {
 
@@ -688,23 +871,35 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
         if (backupName.contains("/")){
             snapshotDir = backupName.split("/")[0];
         }
-        String srcFileName = getOVFFilePath(srcOVAFileName);
-        if(srcFileName == null) {
-            Script command = new Script("tar", 0, s_logger);
-            command.add("--no-same-owner");
-            command.add("-xf", srcOVAFileName);
-            command.setWorkDir(secondaryMountPoint + "/" +  secStorageDir + "/" + snapshotDir);
-            s_logger.info("Executing command: " + command.toString());
-            String result = command.execute();
-            if(result != null) {
-                String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
-                s_logger.error(msg);
-                throw new Exception(msg);
-            }
-        }
 
-        srcFileName = getOVFFilePath(srcOVAFileName);
-        if(srcFileName == null) {
+        File ovafile = new File(srcOVAFileName);
+        String srcOVFFileName = secondaryMountPoint + "/" +  secStorageDir + "/"
+                + backupName + ".ovf";
+        File ovfFile = new File(srcOVFFileName);
+        // String srcFileName = getOVFFilePath(srcOVAFileName);
+        if (!ovfFile.exists()) {
+            srcOVFFileName = getOVFFilePath(srcOVAFileName);
+            if(srcOVFFileName == null && ovafile.exists() ) {  // volss: ova file exists; o/w can't do tar
+                Script command = new Script("tar", 0, s_logger);
+                command.add("--no-same-owner");
+                command.add("-xf", srcOVAFileName);
+                command.setWorkDir(secondaryMountPoint + "/" +  secStorageDir + "/" + snapshotDir);
+                s_logger.info("Executing command: " + command.toString());
+                String result = command.execute();
+                if(result != null) {
+                        String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
+                        s_logger.error(msg);
+                        throw new Exception(msg);
+                }
+            } else {
+               String msg = "Unable to find snapshot OVA file at: " + srcOVAFileName;
+               s_logger.error(msg);
+               throw new Exception(msg);
+           }
+
+           srcOVFFileName = getOVFFilePath(srcOVAFileName);
+        }
+        if(srcOVFFileName == null) {
             String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
             s_logger.error(msg);
             throw new Exception(msg);
@@ -712,7 +907,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
 
         VirtualMachineMO clonedVm = null;
         try {
-            hyperHost.importVmFromOVF(srcFileName, newVolumeName, primaryDsMo, "thin");
+            hyperHost.importVmFromOVF(srcOVFFileName, newVolumeName, primaryDsMo, "thin");
             clonedVm = hyperHost.findVmOnHyperHost(newVolumeName);
             if(clonedVm == null)
                 throw new Exception("Unable to create container VM for volume creation");
@@ -774,7 +969,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
                 throw new Exception(msg);
             }
 
-            clonedVm.exportVm(exportPath, exportName, true, true);
+            clonedVm.exportVm(exportPath, exportName, false, false);  //Note: volss: not to create ova.
         } finally {
             if(clonedVm != null) {
                 clonedVm.detachAllDisks();
@@ -787,17 +982,31 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
 
         String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
         String snapshotMountRoot = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId);
-        File file = new File(snapshotMountRoot + "/" + backupUuid + ".ova");
+        File file = new File(snapshotMountRoot + "/" + backupUuid + ".ovf");
         if(file.exists()) {
-            if(file.delete())
-                return null;
-
-        } else {
-            return "Backup file does not exist. backupUuid: " + backupUuid;
-        }
-
-        return "Failed to delete snapshot backup file, backupUuid: " + backupUuid;
-    }
+             File snapshotdir = new File(snapshotMountRoot);
+             File[] ssfiles = snapshotdir.listFiles();
+            // List<String> filenames = new ArrayList<String>();
+             for (int i = 0; i < ssfiles.length; i++) {
+                String vmdkfile = ssfiles[i].getName();
+                if(vmdkfile.toLowerCase().startsWith(backupUuid) && vmdkfile.toLowerCase().endsWith(".vmdk")) {
+                        // filenames.add(vmdkfile);
+                        new File(vmdkfile).delete();
+                }
+             }
+             if(file.delete())
+                 return null;
+         } else {
+                File file1 = new File(snapshotMountRoot + "/" + backupUuid + ".ova");
+                if(file1.exists()) {
+                     if(file1.delete())
+                        return null;
+                 } else {
+                     return "Backup file does not exist. backupUuid: " + backupUuid;
+                 }
+         }
+         return "Failed to delete snapshot backup file, backupUuid: " + backupUuid;
+     }
 
     private Pair<String, String> copyVolumeToSecStorage(VmwareHostService hostService, VmwareHypervisorHost hyperHost, CopyVolumeCommand cmd,
         String vmName, long volumeId, String poolId, String volumePath,
@@ -881,6 +1090,92 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
         return new Pair<String, String>(volumeFolder, newVolume);
     }
 
+    //Fang:  here I use a method to return the ovf and vmdk file names; Another way to do it:
+    // create a new class, and like TemplateLocation.java and create templateOvfInfo.java to handle it;
+    private String getOVAFromMetafile(String metafileName) throws Exception  {
+        File ova_metafile = new File(metafileName);
+        Properties props = null;
+        FileInputStream strm = null;
+        String ovaFileName = "";
+        s_logger.info("Fang: getOVAfromMetaFile: metafileName " + metafileName);
+  try {
+        strm = new FileInputStream(ova_metafile);
+        if (null == strm) {
+             String msg = "Cannot read ova meat file.  Error";
+             s_logger.error(msg);
+	     throw new Exception(msg);
+        }
+
+        s_logger.info("Fang: getOVAfromMetaFile: load strm " );
+     if (null != ova_metafile) {
+         props = new Properties();
+         props.load(strm);
+        if (props == null) {
+               s_logger.info("Fang: getOVAfromMetaFile: props is null. " );
+        }
+     }
+      if (null != props) {
+        ovaFileName = props.getProperty("ova.filename");
+        s_logger.info("Fang: ovafilename" + ovaFileName);
+        String ovfFileName = props.getProperty("ovf");
+        s_logger.info("Fang: ovffilename" + ovfFileName);
+        int diskNum = Integer.parseInt(props.getProperty("numDisks"));
+        if (diskNum <= 0) {
+		 String msg = "VMDK disk file number is 0. Error";
+                 s_logger.error(msg);
+                 throw new Exception(msg);
+        }
+        String[] disks = new String[diskNum];
+        for (int i = 0; i < diskNum; i++) {
+                //String diskNameKey = "disk" + Integer.toString(i+1) + ".name"; // Fang use this
+                String diskNameKey = "disk1.name";
+                disks[i] = props.getProperty(diskNameKey);
+                s_logger.info("Fang: diskname " + disks[i]);
+        }
+        String exportDir = ova_metafile.getParent();
+        s_logger.info("Fang: exportDir: " + exportDir);
+        // Important! we need to sync file system before we can safely use tar to work around a linux kernal bug(or feature)
+        s_logger.info("Fang: Sync file system before we package OVA..., before tar ");
+        s_logger.info("Fang: ova: " + ovaFileName+ ", ovf:" + ovfFileName + ", vmdk:" + disks[0] + ".");
+        Script commandSync = new Script(true, "sync", 0, s_logger);
+        commandSync.execute();
+        Script command = new Script(false, "tar", 0, s_logger);
+        command.setWorkDir(exportDir);  //Fang: pass this in to the method?
+        command.add("-cf", ovaFileName);
+        command.add(ovfFileName);          // OVF file should be the first file in OVA archive
+        for(String diskName: disks) {
+              command.add(diskName);
+        }
+        command.execute();
+        s_logger.info("Fang: Package OVA for template in dir: " + exportDir + "cmd: " + command.toString());
+        // to be safe, physically test existence of the target OVA file
+        if((new File(exportDir + ovaFileName)).exists()) {
+               s_logger.info("Fang: ova file is created and ready to extract ");
+               return (ovaFileName);
+        }  else {
+            String msg = exportDir + File.separator + ovaFileName + ".ova is not created as expected";
+            s_logger.error(msg);
+            throw new Exception(msg);
+        }
+      } else {
+            String msg = "Error reading the ova meta file: " + metafileName;
+            s_logger.error(msg);
+	    throw new Exception(msg);
+      }
+   } catch (Exception e) {
+	   return null;
+	   //Do something, re-throw the exception
+   }  finally {
+        if (strm != null) {
+             try {
+                   strm.close();
+                 } catch (Exception e) {
+                    }
+        }
+   }
+
+  }
+
     private String getOVFFilePath(String srcOVAFileName) {
         File file = new File(srcOVAFileName);
         assert(_storage != null);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 99ad1ca..38c9f86 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -155,6 +155,10 @@ import com.cloud.agent.api.routing.VmDataCommand;
 import com.cloud.agent.api.routing.VpnUsersCfgCommand;
 import com.cloud.agent.api.storage.CopyVolumeAnswer;
 import com.cloud.agent.api.storage.CopyVolumeCommand;
+import com.cloud.agent.api.storage.CreateVolumeOVACommand;
+import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
+import com.cloud.agent.api.storage.PrepareOVAPackingAnswer;
+import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
 import com.cloud.agent.api.storage.CreateAnswer;
 import com.cloud.agent.api.storage.CreateCommand;
 import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
@@ -392,6 +396,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                 answer = execute((DeleteStoragePoolCommand) cmd);
             } else if (clz == CopyVolumeCommand.class) {
                 answer = execute((CopyVolumeCommand) cmd);
+            } else if (clz == CreateVolumeOVACommand.class) {
+                answer = execute((CreateVolumeOVACommand) cmd);
+            } else if (clz == PrepareOVAPackingCommand.class)  {
+                answer = execute((PrepareOVAPackingCommand) cmd);
             } else if (clz == AttachVolumeCommand.class) {
                 answer = execute((AttachVolumeCommand) cmd);
             } else if (clz == AttachIsoCommand.class) {
@@ -3905,8 +3913,48 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         }
     }
 
+    public CreateVolumeOVAAnswer execute(CreateVolumeOVACommand cmd) {
+        if (s_logger.isInfoEnabled()) {
+            s_logger.info("Executing resource CreateVolumeOVACommand: " + _gson.toJson(cmd));
+        }
+
+        try {
+            VmwareContext context = getServiceContext();
+            VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+            return (CreateVolumeOVAAnswer) mgr.getStorageManager().execute(this, cmd);
+        } catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+                invalidateServiceContext();
+            }
 
+            String msg = "CreateVolumeOVACommand failed due to " + VmwareHelper.getExceptionMessage(e);
+            s_logger.error(msg, e);
+            return new CreateVolumeOVAAnswer(cmd, false, msg);
+        }
+    }
 
+    protected Answer execute(PrepareOVAPackingCommand cmd) {
+        if (s_logger.isInfoEnabled()) {
+            s_logger.info("Executing resource PrepareOVAPackingCommand: " + _gson.toJson(cmd));
+        }
+
+        try {
+            VmwareContext context = getServiceContext();
+            VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+
+            return mgr.getStorageManager().execute(this, cmd);
+        } catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+                invalidateServiceContext();
+            }
+
+            String details = "PrepareOVAPacking for template failed due to " + VmwareHelper.getExceptionMessage(e);
+            s_logger.error(details, e);
+            return new PrepareOVAPackingAnswer(cmd, false, details);
+        }
+    }
     private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
             String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
index ce42f67..95ba317 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
@@ -28,6 +28,9 @@ import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
 import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
 import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
 import com.cloud.agent.api.storage.CopyVolumeCommand;
+import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
+import com.cloud.agent.api.storage.CreateVolumeOVACommand;
+import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
 import com.cloud.hypervisor.vmware.manager.VmwareHostService;
 import com.cloud.hypervisor.vmware.manager.VmwareStorageManager;
@@ -76,6 +79,10 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
             answer = execute((CreatePrivateTemplateFromSnapshotCommand)cmd);
         } else if(cmd instanceof CopyVolumeCommand) {
             answer = execute((CopyVolumeCommand)cmd);
+        } else if(cmd instanceof CreateVolumeOVACommand) {
+            answer = execute((CreateVolumeOVACommand)cmd);
+        } else if (cmd instanceof PrepareOVAPackingCommand) {
+            answer = execute((PrepareOVAPackingCommand)cmd);
         } else if(cmd instanceof CreateVolumeFromSnapshotCommand) {
             answer = execute((CreateVolumeFromSnapshotCommand)cmd);
         } else {
@@ -138,6 +145,23 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
         return _storageMgr.execute(this, cmd);
     }
 
+    private Answer execute(PrepareOVAPackingCommand cmd) {
+        s_logger.info("Fang: VmwareSecStorageResourceHandler: exec cmd. cmd is  " + cmd.toString());
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Executing resource PrepareOVAPackingCommand: " + _gson.toJson(cmd));
+        }
+
+        return _storageMgr.execute(this, cmd);
+    }
+
+    private CreateVolumeOVAAnswer execute(CreateVolumeOVACommand cmd) {
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Executing resource CreateVolumeOVACommand: " + _gson.toJson(cmd));
+        }
+
+        return (CreateVolumeOVAAnswer) _storageMgr.execute(this, cmd);
+    }
+
     private Answer execute(CreateVolumeFromSnapshotCommand cmd) {
         if (s_logger.isDebugEnabled()) {
             s_logger.debug("Executing resource CreateVolumeFromSnapshotCommand: " + _gson.toJson(cmd));

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index f18c9d5..da01b83 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -95,6 +95,8 @@ import com.cloud.agent.api.GetVncPortAnswer;
 import com.cloud.agent.api.GetVncPortCommand;
 import com.cloud.agent.api.storage.CopyVolumeAnswer;
 import com.cloud.agent.api.storage.CopyVolumeCommand;
+import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
+import com.cloud.agent.api.storage.CreateVolumeOVACommand;
 import com.cloud.agent.manager.allocator.HostAllocator;
 import com.cloud.alert.Alert;
 import com.cloud.alert.AlertManager;
@@ -3081,7 +3083,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         List<UploadVO> extractURLList = _uploadDao.listByTypeUploadStatus(volumeId, Upload.Type.VOLUME, UploadVO.Status.DOWNLOAD_URL_CREATED);
 
         if (extractMode == Upload.Mode.HTTP_DOWNLOAD && extractURLList.size() > 0) {
-            return extractURLList.get(0).getId(); // If download url already
+            return extractURLList.get(0).getId(); // If download url already  Note: volss
             // exists then return
         } else {
             UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, Upload.Type.VOLUME,
@@ -3133,6 +3135,19 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
             }
 
             String volumeLocalPath = "volumes/" + volume.getId() + "/" + cvAnswer.getVolumePath() + "." + getFormatForPool(srcPool);
+          //Fang:  volss, handle the ova special case;
+            if (getFormatForPool(srcPool) == "ova") {
+                CreateVolumeOVACommand cvOVACmd = new CreateVolumeOVACommand(secondaryStorageURL, volumeLocalPath, cvAnswer.getVolumePath(), srcPool, copyvolumewait);
+                CreateVolumeOVAAnswer  OVAanswer = null;
+
+                try {
+                        cvOVACmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
+                        OVAanswer = (CreateVolumeOVAAnswer) _storageMgr.sendToPool(srcPool, cvOVACmd); //Fang: for extract volume, create the ova file here;
+
+                } catch (StorageUnavailableException e) {
+                    s_logger.debug("Storage unavailable");
+                }
+            }
             // Update the DB that volume is copied and volumePath
             uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);
             uploadJob.setLastUpdated(new Date());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/server/src/com/cloud/template/HypervisorTemplateAdapter.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java
index 491900b..322f32e 100755
--- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java
+++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java
@@ -30,6 +30,9 @@ import javax.inject.Inject;
 import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
 import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
 import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
+import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd;
+import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
+import com.cloud.agent.api.storage.PrepareOVAPackingAnswer;
 import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
 import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
@@ -64,6 +67,10 @@ import com.cloud.utils.UriUtils;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.vm.UserVmVO;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
+
 
 @Local(value=TemplateAdapter.class)
 public class HypervisorTemplateAdapter extends TemplateAdapterBase implements TemplateAdapter {
@@ -188,6 +195,77 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te
         return template;
     }
 
+	@Override
+	public TemplateProfile prepareExtractTemplate(ExtractTemplateCmd extractcmd) {
+             TemplateProfile profile = super.prepareExtractTemplate(extractcmd);
+             VMTemplateVO template = (VMTemplateVO)profile.getTemplate();
+             Long zoneId = profile.getZoneId();
+             Long templateId = template.getId();
+
+             if (template.getHypervisorType() == HypervisorType.VMware) {
+                PrepareOVAPackingCommand cmd = null;
+                String zoneName="";
+                List<HostVO> secondaryStorageHosts;
+                if (!template.isCrossZones() && zoneId != null) {
+                        DataCenterVO zone = _dcDao.findById(zoneId);
+                        zoneName = zone.getName();
+                        secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId);
+
+                    s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName);
+
+                // Make sure the template is downloaded to all the necessary secondary storage hosts
+
+                for (HostVO secondaryStorageHost : secondaryStorageHosts) {
+                        long hostId = secondaryStorageHost.getId();
+                        List<VMTemplateHostVO> templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId);
+                        for (VMTemplateHostVO templateHostVO : templateHostVOs) {
+                        if (templateHostVO.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) {
+                                 String errorMsg = "Please specify a template that is not currently being downloaded.";
+                                 s_logger.debug("Template: " + template.getName() + " is currently being downloaded to secondary storage host: " + secondaryStorageHost.getName() + ".");
+                                 throw new CloudRuntimeException(errorMsg);
+                        }
+                        String installPath = templateHostVO.getInstallPath();
+                        if (installPath != null) {
+                              HostVO ssvmhost = _ssvmMgr.pickSsvmHost(secondaryStorageHost);
+                              if( ssvmhost == null ) {
+                                 s_logger.warn("prepareOVAPacking (hyervisorTemplateAdapter): There is no secondary storage VM for secondary storage host " + secondaryStorageHost.getName());
+                                 throw new CloudRuntimeException("PrepareExtractTemplate: can't locate ssvm for SecStorage Host.");
+                              }
+                           //Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, new PrepareOVAPackingCommand(secondaryStorageHost.getStorageUrl(), installPath));
+                              cmd = new PrepareOVAPackingCommand(secondaryStorageHost.getStorageUrl(), installPath);
+
+                              if (cmd == null) {
+                                    s_logger.debug("Fang: PrepareOVAPacking cmd can't created. cmd is null .");
+                                    throw new CloudRuntimeException("PrepareExtractTemplate: can't create a new cmd to packing ova.");
+                              } else {
+                                    cmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
+                              }
+                              Answer answer = null;
+                              s_logger.debug("Fang: PrepareOVAPAcking cmd, before send out. cmd: " + cmd.toString());
+                              try {
+                                   answer = _agentMgr.send(ssvmhost.getId(), cmd);
+                                } catch (AgentUnavailableException e) {
+                                    s_logger.warn("Unable to packOVA for template: id: " + templateId + ", name " + ssvmhost.getName(), e);
+                                } catch (OperationTimedoutException e) {
+                                    s_logger.warn("Unable to packOVA for template timeout. template id: " + templateId);
+                                    e.printStackTrace();
+                                }
+
+                                  if (answer == null || !answer.getResult()) {
+                                      s_logger.debug("Failed to create OVA for template " + templateHostVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails()));
+                                      throw new CloudRuntimeException("PrepareExtractTemplate: Failed to create OVA for template extraction. ");
+                                  }
+                       }
+              }
+           }
+         }  else {
+			s_logger.debug("Failed to create OVA for template " + template + " due to zone non-existing.");
+                        throw new CloudRuntimeException("PrepareExtractTemplate: Failed to create OVA for template extraction. ");
+		}
+         }
+		return profile;
+        }
+
 	@Override @DB
 	public boolean delete(TemplateProfile profile) {
 		boolean success = true;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/server/src/com/cloud/template/TemplateAdapter.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/template/TemplateAdapter.java b/server/src/com/cloud/template/TemplateAdapter.java
index 1f8f491..9a2d877 100755
--- a/server/src/com/cloud/template/TemplateAdapter.java
+++ b/server/src/com/cloud/template/TemplateAdapter.java
@@ -22,6 +22,7 @@ import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
 import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
 import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
 import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
+import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd;
 
 import com.cloud.exception.ResourceAllocationException;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -56,6 +57,8 @@ public interface TemplateAdapter extends Adapter {
 
 	public TemplateProfile prepareDelete(DeleteIsoCmd cmd);
 
+	public TemplateProfile prepareExtractTemplate(ExtractTemplateCmd cmd);
+
 	public boolean delete(TemplateProfile profile);
 	
 	public TemplateProfile prepare(boolean isIso, Long userId, String name, String displayText, Integer bits,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/server/src/com/cloud/template/TemplateAdapterBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java
index d3fd165..0940d3e 100755
--- a/server/src/com/cloud/template/TemplateAdapterBase.java
+++ b/server/src/com/cloud/template/TemplateAdapterBase.java
@@ -26,6 +26,7 @@ import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
 import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
 import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
 import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
+import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
@@ -340,6 +341,18 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
 		return new TemplateProfile(userId, template, zoneId);
 	}
 
+	public TemplateProfile prepareExtractTemplate(ExtractTemplateCmd cmd) {
+		Long templateId = cmd.getId();
+		Long userId = UserContext.current().getCallerUserId();
+	        Long zoneId = cmd.getZoneId();
+
+		VMTemplateVO template = _tmpltDao.findById(templateId.longValue());
+		if (template == null) {
+			throw new InvalidParameterValueException("unable to find template with id " + templateId);
+		}
+		return new TemplateProfile(userId, template, zoneId);
+	}
+
 	public TemplateProfile prepareDelete(DeleteIsoCmd cmd) {
 		Long templateId = cmd.getId();
         Long userId = UserContext.current().getCallerUserId();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/server/src/com/cloud/template/TemplateManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java
index 63c6f6e..8b5ee3a 100755
--- a/server/src/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/com/cloud/template/TemplateManagerImpl.java
@@ -367,6 +367,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
         String mode = cmd.getMode();
         Long eventId = cmd.getStartEventId();
 
+        VirtualMachineTemplate template = getTemplate(templateId);
+        if (template == null) {
+            throw new InvalidParameterValueException("unable to find template with id " + templateId);
+        }
+        TemplateAdapter adapter = getAdapter(template.getHypervisorType());
+        TemplateProfile profile = adapter.prepareExtractTemplate(cmd);
+
         // FIXME: async job needs fixing
         Long uploadId = extract(caller, templateId, url, zoneId, mode, eventId, false, null, _asyncMgr);
         if (uploadId != null){

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f1012410/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
----------------------------------------------------------------------
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
index 4503349..660d963 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
@@ -1281,6 +1281,7 @@ public class VirtualMachineMO extends BaseMO {
 					long totalBytesDownloaded = 0;
 
 					List<HttpNfcLeaseDeviceUrl> deviceUrls = leaseInfo.getDeviceUrl();
+					s_logger.info("volss: copy vmdk and ovf file starts " + System.currentTimeMillis());
 					if(deviceUrls != null) {
 						OvfFile[] ovfFiles = new OvfFile[deviceUrls.size()];
 						for (int i = 0; i < deviceUrls.size(); i++) {
@@ -1328,7 +1329,7 @@ public class VirtualMachineMO extends BaseMO {
 
 						// tar files into OVA
 						if(packToOva) {
-						    // Important! we need to sync file system before we can safely use tar to work around a linux kernal bug(or feature)
+                                                    // Important! we need to sync file system before we can safely use tar to work around a linux kernal bug(or feature)
                             s_logger.info("Sync file system before we package OVA...");
 
 						    Script commandSync = new Script(true, "sync", 0, s_logger);
@@ -1351,8 +1352,11 @@ public class VirtualMachineMO extends BaseMO {
 					        } else {
 					            s_logger.error(exportDir + File.separator + exportName + ".ova is not created as expected");
 					        }
+						} else {
+							success = true;
 						}
 					}
+					s_logger.info("volss: copy vmdk and ovf file finishes " + System.currentTimeMillis());
 				} catch(Throwable e) {
 					s_logger.error("Unexpected exception ", e);
 				} finally {


Mime
View raw message