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/06/20 09:19:51 UTC

[18/50] [abbrv] Merge branch 'master' (up to commit c30d9be3cea30339cfff40c1002906634291b373) into object_store.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/resource/ResourceManagerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/resource/ResourceManagerImpl.java
index 837fdfb,c6e8d7d..fe91cb3
--- a/server/src/com/cloud/resource/ResourceManagerImpl.java
+++ b/server/src/com/cloud/resource/ResourceManagerImpl.java
@@@ -45,12 -45,6 +45,7 @@@ import org.apache.cloudstack.api.comman
  import org.apache.cloudstack.api.command.admin.storage.ListS3sCmd;
  import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd;
  import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd;
- import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
- import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle;
- import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
- import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
- import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
 +import org.apache.cloudstack.region.dao.RegionDao;
  import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
  import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
  import org.apache.log4j.Logger;
@@@ -208,59 -202,57 +202,61 @@@ public class ResourceManagerImpl extend
      @Inject
      protected ConfigurationDao _configDao;
      @Inject
 -    protected HostTagsDao                    _hostTagsDao;
 +    protected HostTagsDao _hostTagsDao;
      @Inject
 -    protected GuestOSCategoryDao             _guestOSCategoryDao;
 +    protected GuestOSCategoryDao _guestOSCategoryDao;
      @Inject
 -    protected PrimaryDataStoreDao                _storagePoolDao;
 +    protected PrimaryDataStoreDao _storagePoolDao;
      @Inject
 -    protected DataCenterIpAddressDao         _privateIPAddressDao;
 +    protected DataCenterIpAddressDao _privateIPAddressDao;
      @Inject
 -    protected IPAddressDao                   _publicIPAddressDao;
 +    protected IPAddressDao _publicIPAddressDao;
      @Inject
 -    protected VirtualMachineManager          _vmMgr;
 +    protected VirtualMachineManager _vmMgr;
      @Inject
 -    protected VMInstanceDao                  _vmDao;
 +    protected VMInstanceDao _vmDao;
      @Inject
 -    protected HighAvailabilityManager        _haMgr;
 +    protected HighAvailabilityManager _haMgr;
      @Inject
 -    protected StorageService                 _storageSvr;
 +    protected StorageService _storageSvr;
      @Inject
      PlannerHostReservationDao _plannerHostReserveDao;
+     @Inject
+     protected DedicatedResourceDao           _dedicatedDao;
  
      protected List<? extends Discoverer> _discoverers;
 +
      public List<? extends Discoverer> getDiscoverers() {
 -		return _discoverers;
 -	}
 -	public void setDiscoverers(List<? extends Discoverer> _discoverers) {
 -		this._discoverers = _discoverers;
 -	}
 +        return _discoverers;
 +    }
 +
 +    public void setDiscoverers(List<? extends Discoverer> _discoverers) {
 +        this._discoverers = _discoverers;
 +    }
  
 -	@Inject
 -    protected ClusterManager                 _clusterMgr;
      @Inject
 -    protected StoragePoolHostDao             _storagePoolHostDao;
 +    protected ClusterManager _clusterMgr;
 +    @Inject
 +    protected StoragePoolHostDao _storagePoolHostDao;
 +
 +    protected List<PodAllocator> _podAllocators;
  
 -	protected List<PodAllocator> _podAllocators;
      public List<PodAllocator> getPodAllocators() {
 -		return _podAllocators;
 -	}
 -	public void setPodAllocators(List<PodAllocator> _podAllocators) {
 -		this._podAllocators = _podAllocators;
 -	}
 +        return _podAllocators;
 +    }
 +
 +    public void setPodAllocators(List<PodAllocator> _podAllocators) {
 +        this._podAllocators = _podAllocators;
 +    }
  
 -	@Inject
 -    protected VMTemplateDao  _templateDao;
      @Inject
 -    protected ConfigurationManager 			 _configMgr;
 +    protected VMTemplateDao _templateDao;
      @Inject
 -    protected ClusterVSMMapDao				 _clusterVSMMapDao;
 +    protected ConfigurationManager _configMgr;
 +    @Inject
 +    protected ClusterVSMMapDao _clusterVSMMapDao;
  
 -    protected long                           _nodeId  = ManagementServerNode.getManagementServerId();
 +    protected long _nodeId = ManagementServerNode.getManagementServerId();
  
      protected HashMap<String, ResourceStateAdapter> _resourceStateAdapters = new HashMap<String, ResourceStateAdapter>();
  
@@@ -391,10 -401,11 +388,10 @@@
          }
  
          Account account = UserContext.current().getCaller();
 -		if (Grouping.AllocationState.Disabled == zone.getAllocationState()
 -				&& !_accountMgr.isRootAdmin(account.getType())) {
 -			PermissionDeniedException ex = new PermissionDeniedException(
 -					"Cannot perform this operation, Zone with specified id is currently disabled");
 +        if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) {
 +            PermissionDeniedException ex = new PermissionDeniedException(
 +                    "Cannot perform this operation, Zone with specified id is currently disabled");
-             ex.addProxyObject(zone, dcId, "dcId");
+             ex.addProxyObject(zone.getUuid(), "dcId");
              throw ex;
          }
  
@@@ -421,15 -436,26 +419,22 @@@
          }
  
          if (cmd.getHypervisor() == null || cmd.getHypervisor().isEmpty()) {
 -			throw new InvalidParameterValueException(
 -					"Please specify a hypervisor");
 +            throw new InvalidParameterValueException("Please specify a hypervisor");
          }
  
 -		Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType
 -				.getType(cmd.getHypervisor());
 +        Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.getType(cmd.getHypervisor());
          if (hypervisorType == null) {
 -			s_logger.error("Unable to resolve " + cmd.getHypervisor()
 -					+ " to a valid supported hypervisor type");
 -			throw new InvalidParameterValueException("Unable to resolve "
 -					+ cmd.getHypervisor() + " to a supported ");
 +            s_logger.error("Unable to resolve " + cmd.getHypervisor() + " to a valid supported hypervisor type");
 +            throw new InvalidParameterValueException("Unable to resolve " + cmd.getHypervisor() + " to a supported ");
          }
  
+         if (zone.isSecurityGroupEnabled() && zone.getNetworkType().equals(NetworkType.Advanced)) {
+             if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer
+                     && hypervisorType != HypervisorType.Simulator) {
+                 throw new InvalidParameterValueException("Don't support hypervisor type " + hypervisorType + " in advanced security enabled zone");
+             }
+         }
+ 
          Cluster.ClusterType clusterType = null;
          if (cmd.getClusterType() != null && !cmd.getClusterType().isEmpty()) {
              clusterType = Cluster.ClusterType.valueOf(cmd.getClusterType());
@@@ -473,11 -506,12 +478,11 @@@
              cluster = _clusterDao.persist(cluster);
          } catch (Exception e) {
              // no longer tolerate exception during the cluster creation phase
 -			CloudRuntimeException ex = new CloudRuntimeException(
 -					"Unable to create cluster " + clusterName
 -							+ " in pod and data center with specified ids", e);
 +            CloudRuntimeException ex = new CloudRuntimeException("Unable to create cluster " + clusterName
 +                    + " in pod and data center with specified ids", e);
              // Get the pod VO object's table name.
-             ex.addProxyObject(pod, podId, "podId");
-             ex.addProxyObject(zone, dcId, "dcId");
+             ex.addProxyObject(pod.getUuid(), "podId");
+             ex.addProxyObject(zone.getUuid(), "dcId");
              throw ex;
          }
          clusterId = cluster.getId();
@@@ -600,9 -651,9 +606,9 @@@
                  if (cluster.getGuid() == null) {
                      List<HostVO> hosts = listAllHostsInCluster(clusterId);
                      if (!hosts.isEmpty()) {
 -						CloudRuntimeException ex = new CloudRuntimeException(
 -								"Guid is not updated for cluster with specified cluster id; need to wait for hosts in this cluster to come up");
 +                        CloudRuntimeException ex = new CloudRuntimeException(
 +                                "Guid is not updated for cluster with specified cluster id; need to wait for hosts in this cluster to come up");
-                         ex.addProxyObject(cluster, clusterId, "clusterId");
+                         ex.addProxyObject(cluster.getUuid(), "clusterId");
                          throw ex;
                      }
                  }
@@@ -655,10 -705,11 +661,10 @@@
          }
  
          Account account = UserContext.current().getCaller();
 -		if (Grouping.AllocationState.Disabled == zone.getAllocationState()
 -				&& !_accountMgr.isRootAdmin(account.getType())) {
 -			PermissionDeniedException ex = new PermissionDeniedException(
 -					"Cannot perform this operation, Zone with specified id is currently disabled");
 +        if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) {
 +            PermissionDeniedException ex = new PermissionDeniedException(
 +                    "Cannot perform this operation, Zone with specified id is currently disabled");
-             ex.addProxyObject(zone, dcId, "dcId");
+             ex.addProxyObject(zone.getUuid(), "dcId");
              throw ex;
          }
  
@@@ -927,11 -1022,19 +939,16 @@@
          }
  
          // delete the op_host_capacity entry
 -		Object[] capacityTypes = { Capacity.CAPACITY_TYPE_CPU,
 -				Capacity.CAPACITY_TYPE_MEMORY };
 -		SearchCriteria<CapacityVO> hostCapacitySC = _capacityDao
 -				.createSearchCriteria();
 +        Object[] capacityTypes = { Capacity.CAPACITY_TYPE_CPU, Capacity.CAPACITY_TYPE_MEMORY };
 +        SearchCriteria<CapacityVO> hostCapacitySC = _capacityDao.createSearchCriteria();
          hostCapacitySC.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
 -		hostCapacitySC.addAnd("capacityType", SearchCriteria.Op.IN,
 -				capacityTypes);
 +        hostCapacitySC.addAnd("capacityType", SearchCriteria.Op.IN, capacityTypes);
          _capacityDao.remove(hostCapacitySC);
+         // remove from dedicated resources
+         DedicatedResourceVO dr = _dedicatedDao.findByHostId(hostId);
+         if (dr != null) {
+             _dedicatedDao.remove(dr.getId());
+         }
          txn.commit();
          return true;
      }
@@@ -970,36 -1078,49 +987,41 @@@
              List<HostVO> hosts = listAllHostsInCluster(cmd.getId());
              if (hosts.size() > 0) {
                  if (s_logger.isDebugEnabled()) {
 -					s_logger.debug("Cluster: " + cmd.getId()
 -							+ " still has hosts, can't remove");
 +                    s_logger.debug("Cluster: " + cmd.getId() + " still has hosts, can't remove");
                  }
                  txn.rollback();
 -				throw new CloudRuntimeException("Cluster: " + cmd.getId()
 -						+ " cannot be removed. Cluster still has hosts");
 +                throw new CloudRuntimeException("Cluster: " + cmd.getId() + " cannot be removed. Cluster still has hosts");
              }
  
 -			// don't allow to remove the cluster if it has non-removed storage
 -			// pools
 -			List<StoragePoolVO> storagePools = _storagePoolDao
 -					.listPoolsByCluster(cmd.getId());
 +            // don't allow to remove the cluster if it has non-removed storage
 +            // pools
 +            List<StoragePoolVO> storagePools = _storagePoolDao.listPoolsByCluster(cmd.getId());
              if (storagePools.size() > 0) {
                  if (s_logger.isDebugEnabled()) {
 -					s_logger.debug("Cluster: " + cmd.getId()
 -							+ " still has storage pools, can't remove");
 +                    s_logger.debug("Cluster: " + cmd.getId() + " still has storage pools, can't remove");
                  }
                  txn.rollback();
 -				throw new CloudRuntimeException("Cluster: " + cmd.getId()
 -						+ " cannot be removed. Cluster still has storage pools");
 +                throw new CloudRuntimeException("Cluster: " + cmd.getId() + " cannot be removed. Cluster still has storage pools");
              }
  
 -			if (_clusterDao.remove(cmd.getId())) {
 +            if (_clusterDao.remove(cmd.getId())) {
                  _capacityDao.removeBy(null, null, null, cluster.getId(), null);
 -				// If this cluster is of type vmware, and if the nexus vswitch
 -				// global parameter setting is turned
 +                // If this cluster is of type vmware, and if the nexus vswitch
 +                // global parameter setting is turned
                  // on, remove the row in cluster_vsm_map for this cluster id.
 -				if (hypervisorType == HypervisorType.VMware
 -						&& Boolean.parseBoolean(_configDao
 -								.getValue(Config.VmwareUseNexusVSwitch
 -										.toString()))) {
 -				    _clusterVSMMapDao.removeByClusterId(cmd.getId());
 -				}
 +                if (hypervisorType == HypervisorType.VMware && Boolean.parseBoolean(_configDao.getValue(Config.VmwareUseNexusVSwitch.toString()))) {
 +                    _clusterVSMMapDao.removeByClusterId(cmd.getId());
 +                }
+ 				// remove from dedicated resources
+ 				DedicatedResourceVO dr = _dedicatedDao.findByClusterId(cluster.getId());
+ 				if (dr != null) {
+ 				    _dedicatedDao.remove(dr.getId());
+ 				}
 -			}
 +            }
  
 -			txn.commit();
 +            txn.commit();
              return true;
 -		} catch (CloudRuntimeException e) {
 +        } catch (CloudRuntimeException e) {
              throw e;
          } catch (Throwable t) {
              s_logger.error("Unable to delete cluster: " + cmd.getId(), t);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/server/ConfigurationServerImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/server/ManagementServerImpl.java
index 17444eb,96c72e4..5c2917f
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@@ -24,8 -29,11 +24,9 @@@ import java.util.Calendar
  import java.util.Comparator;
  import java.util.Date;
  import java.util.HashMap;
 -import java.util.HashSet;
+ import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
 -import java.util.Set;
  import java.util.TimeZone;
  import java.util.concurrent.Executors;
  import java.util.concurrent.ScheduledExecutorService;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/server/StatsCollector.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/server/StatsCollector.java
index 3feb10b,8d84c6c..e510435
--- a/server/src/com/cloud/server/StatsCollector.java
+++ b/server/src/com/cloud/server/StatsCollector.java
@@@ -67,14 -70,26 +73,21 @@@ import com.cloud.storage.VolumeStats
  import com.cloud.storage.VolumeVO;
  import com.cloud.storage.dao.StoragePoolHostDao;
  import com.cloud.storage.dao.VolumeDao;
 -import com.cloud.storage.secondary.SecondaryStorageVmManager;
 -import com.cloud.user.UserStatisticsVO;
 -import com.cloud.user.UserStatsLogVO;
+ import com.cloud.user.VmDiskStatisticsVO;
+ import com.cloud.user.dao.VmDiskStatisticsDao;
  import com.cloud.utils.NumbersUtil;
  import com.cloud.utils.component.ComponentMethodInterceptable;
  import com.cloud.utils.component.ManagerBase;
  import com.cloud.utils.concurrency.NamedThreadFactory;
+ import com.cloud.utils.db.Filter;
+ import com.cloud.utils.db.GlobalLock;
  import com.cloud.utils.db.SearchCriteria;
+ import com.cloud.utils.db.Transaction;
+ import com.cloud.utils.net.MacAddress;
  import com.cloud.vm.UserVmManager;
  import com.cloud.vm.UserVmVO;
  import com.cloud.vm.VmStats;
+ import com.cloud.vm.VirtualMachine;
 -import com.cloud.vm.VirtualMachine.State;
  import com.cloud.vm.dao.UserVmDao;
  
  /**
@@@ -94,13 -109,13 +107,15 @@@ public class StatsCollector extends Man
  	@Inject private UserVmDao _userVmDao;
  	@Inject private VolumeDao _volsDao;
  	@Inject private PrimaryDataStoreDao _storagePoolDao;
 +	@Inject private ImageStoreDao _imageStoreDao;
  	@Inject private StorageManager _storageManager;
  	@Inject private StoragePoolHostDao _storagePoolHostDao;
 -	@Inject private SecondaryStorageVmManager _ssvmMgr;
 +	@Inject private DataStoreManager _dataStoreMgr;
  	@Inject private ResourceManager _resourceMgr;
      @Inject private ConfigurationDao _configDao;
 +    @Inject private EndPointSelector _epSelector;
+     @Inject private VmDiskStatisticsDao _vmDiskStatsDao;
+     @Inject private ManagementServerHostDao _msHostDao;
  
  	private ConcurrentHashMap<Long, HostStats> _hostStats = new ConcurrentHashMap<Long, HostStats>();
  	private final ConcurrentHashMap<Long, VmStats> _VmStats = new ConcurrentHashMap<Long, VmStats>();
@@@ -112,6 -127,15 +127,15 @@@
  	long hostAndVmStatsInterval = -1L;
  	long storageStatsInterval = -1L;
  	long volumeStatsInterval = -1L;
+ 	int vmDiskStatsInterval = 0;
 -	
++
+ 	private ScheduledExecutorService _diskStatsUpdateExecutor;
+     private int _usageAggregationRange = 1440;
+     private String _usageTimeZone = "GMT";
+     private final long mgmtSrvrId = MacAddress.getMacAddress().toLong();
+     private static final int ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION = 5;    // 5 seconds
+     private static final int USAGE_AGGREGATION_RANGE_MIN = 10; // 10 minutes, same to com.cloud.usage.UsageManagerImpl.USAGE_AGGREGATION_RANGE_MIN
+     private boolean _dailyOrHourly = false;
  
  	//private final GlobalLock m_capacityCheckLock = GlobalLock.getInternLock("capacity.check");
  
@@@ -153,13 -178,62 +178,62 @@@
  		 if (storageStatsInterval > 0) {
  		     _executor.scheduleWithFixedDelay(new StorageCollector(), 15000L, storageStatsInterval, TimeUnit.MILLISECONDS);
  		 }
 -		 
 +
+ 		 if (vmDiskStatsInterval > 0) {
+                      if (vmDiskStatsInterval < 300)
+                          vmDiskStatsInterval = 300;
+              _executor.scheduleAtFixedRate(new VmDiskStatsTask(), vmDiskStatsInterval, vmDiskStatsInterval, TimeUnit.SECONDS);
+          }
 -		
++
  		// -1 means we don't even start this thread to pick up any data.
  		if (volumeStatsInterval > 0) {
  			_executor.scheduleWithFixedDelay(new VolumeCollector(), 15000L, volumeStatsInterval, TimeUnit.MILLISECONDS);
  		} else {
  			s_logger.info("Disabling volume stats collector");
  		}
 -		
++
+         //Schedule disk stats update task
+         _diskStatsUpdateExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DiskStatsUpdater"));
+         String aggregationRange = configs.get("usage.stats.job.aggregation.range");
+         _usageAggregationRange  = NumbersUtil.parseInt(aggregationRange, 1440);
+         _usageTimeZone = configs.get("usage.aggregation.timezone");
+         if(_usageTimeZone == null){
+             _usageTimeZone = "GMT";
+         }
+         TimeZone usageTimezone = TimeZone.getTimeZone(_usageTimeZone);
+         Calendar cal = Calendar.getInstance(usageTimezone);
+         cal.setTime(new Date());
+         long endDate = 0;
+         int HOURLY_TIME = 60;
+         final int DAILY_TIME = 60 * 24;
+         if (_usageAggregationRange == DAILY_TIME) {
+             cal.set(Calendar.HOUR_OF_DAY, 0);
+             cal.set(Calendar.MINUTE, 0);
+             cal.set(Calendar.SECOND, 0);
+             cal.set(Calendar.MILLISECOND, 0);
+             cal.roll(Calendar.DAY_OF_YEAR, true);
+             cal.add(Calendar.MILLISECOND, -1);
+             endDate = cal.getTime().getTime();
+             _dailyOrHourly = true;
+         } else if (_usageAggregationRange == HOURLY_TIME) {
+             cal.set(Calendar.MINUTE, 0);
+             cal.set(Calendar.SECOND, 0);
+             cal.set(Calendar.MILLISECOND, 0);
+             cal.roll(Calendar.HOUR_OF_DAY, true);
+             cal.add(Calendar.MILLISECOND, -1);
+             endDate = cal.getTime().getTime();
+             _dailyOrHourly = true;
+         } else {
+             endDate = cal.getTime().getTime();
+             _dailyOrHourly = false;
+         }
+         if (_usageAggregationRange < USAGE_AGGREGATION_RANGE_MIN) {
+             s_logger.warn("Usage stats job aggregation range is to small, using the minimum value of " + USAGE_AGGREGATION_RANGE_MIN);
+             _usageAggregationRange = USAGE_AGGREGATION_RANGE_MIN;
+         }
+         _diskStatsUpdateExecutor.scheduleAtFixedRate(new VmDiskStatsUpdaterTask(), (endDate - System.currentTimeMillis()),
+                 (_usageAggregationRange * 60 * 1000), TimeUnit.MILLISECONDS);
 -        
++
  	}
  
  	class HostCollector implements Runnable {
@@@ -254,7 -328,11 +328,11 @@@
  										statsInMemory.setNumCPUs(statsForCurrentIteration.getNumCPUs());
  										statsInMemory.setNetworkReadKBs(statsInMemory.getNetworkReadKBs() + statsForCurrentIteration.getNetworkReadKBs());
  										statsInMemory.setNetworkWriteKBs(statsInMemory.getNetworkWriteKBs() + statsForCurrentIteration.getNetworkWriteKBs());
+ 										statsInMemory.setDiskWriteKBs(statsInMemory.getDiskWriteKBs() + statsForCurrentIteration.getDiskWriteKBs());
+                                                                                 statsInMemory.setDiskReadIOs(statsInMemory.getDiskReadIOs() + statsForCurrentIteration.getDiskReadIOs());
+                                                                                 statsInMemory.setDiskWriteIOs(statsInMemory.getDiskWriteIOs() + statsForCurrentIteration.getDiskWriteIOs());
+                                                                                 statsInMemory.setDiskReadKBs(statsInMemory.getDiskReadKBs() + statsForCurrentIteration.getDiskReadKBs());
 -										
 +
  										_VmStats.put(vmId, statsInMemory);
  									}
  								}
@@@ -275,7 -353,176 +353,176 @@@
  	public VmStats getVmStats(long id) {
  		return _VmStats.get(id);
  	}
 -	
 +
+     class VmDiskStatsUpdaterTask implements Runnable {
+         @Override
+         public void run() {
+             GlobalLock scanLock = GlobalLock.getInternLock("vm.disk.stats");
+             try {
+                 if(scanLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_COOPERATION)) {
+                     //Check for ownership
+                     //msHost in UP state with min id should run the job
+                     ManagementServerHostVO msHost = _msHostDao.findOneInUpState(new Filter(ManagementServerHostVO.class, "id", true, 0L, 1L));
+                     if(msHost == null || (msHost.getMsid() != mgmtSrvrId)){
+                         s_logger.debug("Skipping aggregate disk stats update");
+                         scanLock.unlock();
+                         return;
+                     }
+                     Transaction txn = Transaction.open(Transaction.CLOUD_DB);
+                     try {
+                         txn.start();
+                         //get all stats with delta > 0
+                         List<VmDiskStatisticsVO> updatedVmNetStats = _vmDiskStatsDao.listUpdatedStats();
+                         for(VmDiskStatisticsVO stat : updatedVmNetStats){
+                             if (_dailyOrHourly) {
 -                                //update agg bytes                    
++                                //update agg bytes
+                                 stat.setAggBytesRead(stat.getCurrentBytesRead() + stat.getNetBytesRead());
+                                 stat.setAggBytesWrite(stat.getCurrentBytesWrite() + stat.getNetBytesWrite());
+                                 stat.setAggIORead(stat.getCurrentIORead() + stat.getNetIORead());
+                                 stat.setAggIOWrite(stat.getCurrentIOWrite() + stat.getNetIOWrite());
+                                 _vmDiskStatsDao.update(stat.getId(), stat);
+                             }
+                         }
+                         s_logger.debug("Successfully updated aggregate vm disk stats");
+                         txn.commit();
+                     } catch (Exception e){
+                         txn.rollback();
+                         s_logger.debug("Failed to update aggregate disk stats", e);
+                     } finally {
+                         scanLock.unlock();
+                         txn.close();
+                     }
+                 }
+             } catch (Exception e){
+                 s_logger.debug("Exception while trying to acquire disk stats lock", e);
+             }  finally {
+                 scanLock.releaseRef();
+             }
+         }
+     }
 -    
++
+     class VmDiskStatsTask implements Runnable {
+         @Override
+         public void run() {
+             // collect the vm disk statistics(total) from hypervisor. added by weizhou, 2013.03.
+             Transaction txn = Transaction.open(Transaction.CLOUD_DB);
+             try {
+                 txn.start();
+                 SearchCriteria<HostVO> sc = _hostDao.createSearchCriteria();
+                 sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString());
+                 sc.addAnd("resourceState", SearchCriteria.Op.NIN, ResourceState.Maintenance, ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance);
+                 sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.Routing.toString());
+                 List<HostVO> hosts = _hostDao.search(sc, null);
 -                
++
+                 for (HostVO host : hosts) {
+                     List<UserVmVO> vms = _userVmDao.listRunningByHostId(host.getId());
+                     List<Long> vmIds = new ArrayList<Long>();
 -                    
++
+                     for (UserVmVO vm : vms) {
+                         if (vm.getType() == VirtualMachine.Type.User) // user vm
+                             vmIds.add(vm.getId());
+                     }
 -                    
++
+                     HashMap<Long, List<VmDiskStatsEntry>> vmDiskStatsById = _userVmMgr.getVmDiskStatistics(host.getId(), host.getName(), vmIds);
+                     if (vmDiskStatsById == null)
+                         continue;
 -                
++
+                     Set<Long> vmIdSet = vmDiskStatsById.keySet();
+                     for(Long vmId : vmIdSet)
+                     {
+                         List<VmDiskStatsEntry> vmDiskStats = vmDiskStatsById.get(vmId);
+                         if (vmDiskStats == null)
+                                 continue;
+                         UserVmVO userVm = _userVmDao.findById(vmId);
+                         for (VmDiskStatsEntry vmDiskStat:vmDiskStats) {
+                             SearchCriteria<VolumeVO> sc_volume = _volsDao.createSearchCriteria();
+                             sc_volume.addAnd("path", SearchCriteria.Op.EQ, vmDiskStat.getPath());
+                             VolumeVO volume = _volsDao.search(sc_volume, null).get(0);
+                             VmDiskStatisticsVO previousVmDiskStats = _vmDiskStatsDao.findBy(userVm.getAccountId(), userVm.getDataCenterId(), vmId, volume.getId());
+                             VmDiskStatisticsVO vmDiskStat_lock = _vmDiskStatsDao.lock(userVm.getAccountId(), userVm.getDataCenterId(), vmId, volume.getId());
 -                            
++
+                             if ((vmDiskStat.getBytesRead() == 0) && (vmDiskStat.getBytesWrite() == 0)
+                                     && (vmDiskStat.getIORead() == 0) && (vmDiskStat.getIOWrite() == 0)) {
+                                 s_logger.debug("IO/bytes read and write are all 0. Not updating vm_disk_statistics");
+                                 continue;
+                             }
 -                            
++
+                             if (vmDiskStat_lock == null) {
+                                 s_logger.warn("unable to find vm disk stats from host for account: " + userVm.getAccountId() + " with vmId: " + userVm.getId()+ " and volumeId:" + volume.getId());
+                                 continue;
+                             }
+ 
+                             if (previousVmDiskStats != null
+                                     && ((previousVmDiskStats.getCurrentBytesRead() != vmDiskStat_lock.getCurrentBytesRead())
+                                     || (previousVmDiskStats.getCurrentBytesWrite() != vmDiskStat_lock.getCurrentBytesWrite())
+                                     || (previousVmDiskStats.getCurrentIORead() != vmDiskStat_lock.getCurrentIORead())
+                                     || (previousVmDiskStats.getCurrentIOWrite() != vmDiskStat_lock.getCurrentIOWrite()))) {
+                                 s_logger.debug("vm disk stats changed from the time GetVmDiskStatsCommand was sent. " +
 -                                        "Ignoring current answer. Host: " + host.getName()  + " . VM: " + vmDiskStat.getVmName() + 
++                                        "Ignoring current answer. Host: " + host.getName()  + " . VM: " + vmDiskStat.getVmName() +
+                                         " Read(Bytes): " + vmDiskStat.getBytesRead() + " write(Bytes): " + vmDiskStat.getBytesWrite() +
+                                         " Read(IO): " + vmDiskStat.getIORead() + " write(IO): " + vmDiskStat.getIOWrite());
+                                 continue;
+                             }
+ 
+                             if (vmDiskStat_lock.getCurrentBytesRead() > vmDiskStat.getBytesRead()) {
+                                 if (s_logger.isDebugEnabled()) {
+                                     s_logger.debug("Read # of bytes that's less than the last one.  " +
+                                             "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
+                                             " Reported: " + vmDiskStat.getBytesRead() + " Stored: " + vmDiskStat_lock.getCurrentBytesRead());
+                                 }
+                                 vmDiskStat_lock.setNetBytesRead(vmDiskStat_lock.getNetBytesRead() + vmDiskStat_lock.getCurrentBytesRead());
+                             }
+                             vmDiskStat_lock.setCurrentBytesRead(vmDiskStat.getBytesRead());
+                             if (vmDiskStat_lock.getCurrentBytesWrite() > vmDiskStat.getBytesWrite()) {
+                                 if (s_logger.isDebugEnabled()) {
+                                     s_logger.debug("Write # of bytes that's less than the last one.  " +
+                                             "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
+                                             " Reported: " + vmDiskStat.getBytesWrite() + " Stored: " + vmDiskStat_lock.getCurrentBytesWrite());
+                                 }
+                                 vmDiskStat_lock.setNetBytesWrite(vmDiskStat_lock.getNetBytesWrite() + vmDiskStat_lock.getCurrentBytesWrite());
+                             }
+                             vmDiskStat_lock.setCurrentBytesWrite(vmDiskStat.getBytesWrite());
+                             if (vmDiskStat_lock.getCurrentIORead() > vmDiskStat.getIORead()) {
+                                 if (s_logger.isDebugEnabled()) {
+                                     s_logger.debug("Read # of IO that's less than the last one.  " +
+                                             "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
+                                             " Reported: " + vmDiskStat.getIORead() + " Stored: " + vmDiskStat_lock.getCurrentIORead());
+                                 }
+                                 vmDiskStat_lock.setNetIORead(vmDiskStat_lock.getNetIORead() + vmDiskStat_lock.getCurrentIORead());
+                             }
+                             vmDiskStat_lock.setCurrentIORead(vmDiskStat.getIORead());
+                             if (vmDiskStat_lock.getCurrentIOWrite() > vmDiskStat.getIOWrite()) {
+                                 if (s_logger.isDebugEnabled()) {
+                                     s_logger.debug("Write # of IO that's less than the last one.  " +
+                                             "Assuming something went wrong and persisting it. Host: " + host.getName() + " . VM: " + vmDiskStat.getVmName() +
+                                             " Reported: " + vmDiskStat.getIOWrite() + " Stored: " + vmDiskStat_lock.getCurrentIOWrite());
+                                 }
+                                 vmDiskStat_lock.setNetIOWrite(vmDiskStat_lock.getNetIOWrite() + vmDiskStat_lock.getCurrentIOWrite());
+                             }
+                             vmDiskStat_lock.setCurrentIOWrite(vmDiskStat.getIOWrite());
 -                            
++
+                             if (! _dailyOrHourly) {
 -                                //update agg bytes 
++                                //update agg bytes
+                                 vmDiskStat_lock.setAggBytesWrite(vmDiskStat_lock.getNetBytesWrite() + vmDiskStat_lock.getCurrentBytesWrite());
+                                 vmDiskStat_lock.setAggBytesRead(vmDiskStat_lock.getNetBytesRead() + vmDiskStat_lock.getCurrentBytesRead());
+                                 vmDiskStat_lock.setAggIOWrite(vmDiskStat_lock.getNetIOWrite() + vmDiskStat_lock.getCurrentIOWrite());
+                                 vmDiskStat_lock.setAggIORead(vmDiskStat_lock.getNetIORead() + vmDiskStat_lock.getCurrentIORead());
+                             }
+ 
+                             _vmDiskStatsDao.update(vmDiskStat_lock.getId(), vmDiskStat_lock);
+                         }
+                     }
+                 }
+                 txn.commit();
+             } catch (Exception e) {
+                 s_logger.warn("Error while collecting vm disk stats from hosts", e);
+             } finally {
+                 txn.close();
+             }
 -            
++
+         }
+     }
+ 
  	class StorageCollector implements Runnable {
  		@Override
          public void run() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/storage/StorageManagerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/storage/StorageManagerImpl.java
index 1146179,d38b35e..687c4da
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@@ -662,11 -768,32 +662,30 @@@ public class StorageManagerImpl extend
          }
  
          if (scopeType == ScopeType.CLUSTER && clusterId == null) {
 -            throw new InvalidParameterValueException(
 -                    "cluster id can't be null, if scope is cluster");
 +            throw new InvalidParameterValueException("cluster id can't be null, if scope is cluster");
          } else if (scopeType == ScopeType.ZONE && zoneId == null) {
 -            throw new InvalidParameterValueException(
 -                    "zone id can't be null, if scope is zone");
 +            throw new InvalidParameterValueException("zone id can't be null, if scope is zone");
          }
  
+         HypervisorType hypervisorType = HypervisorType.KVM;
+         if (scopeType == ScopeType.ZONE) {
+             String hypervisor = cmd.getHypervisor();
+             if (hypervisor != null) {
+                 try {
+                     hypervisorType = HypervisorType.getType(hypervisor);
+                 } catch (Exception e) {
+                     throw new InvalidParameterValueException("invalid hypervisor type" + hypervisor);
+                 }
+             } else {
+                 throw new InvalidParameterValueException(
+                         "Missing parameter hypervisor. Hypervisor type is required to create zone wide primary storage.");
+             }
+             if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.VMware) {
+                 throw new InvalidParameterValueException(
+                         "zone wide storage pool is not suported for hypervisor type " + hypervisor);
+             }
+         }
+ 
          Map ds = cmd.getDetails();
          Map<String, String> details = new HashMap<String, String>();
          if (ds != null) {
@@@ -1618,231 -1883,4 +1637,231 @@@
          return null;
      }
  
 +    @Override
 +    public ImageStore discoverImageStore(AddImageStoreCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException {
 +        String providerName = cmd.getProviderName();
 +        DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName);
 +
 +        if (storeProvider == null) {
 +            storeProvider = _dataStoreProviderMgr.getDefaultImageDataStoreProvider();
 +            if (storeProvider == null) {
 +                throw new InvalidParameterValueException("can't find image store provider: " + providerName);
 +            }
 +            providerName = storeProvider.getName(); // ignored passed provider name and use default image store provider name
 +        }
 +
 +        Long dcId = cmd.getZoneId();
 +        String url = cmd.getUrl();
 +        Map details = cmd.getDetails();
 +        ScopeType scopeType = ScopeType.ZONE;
 +        if (dcId == null) {
 +            scopeType = ScopeType.REGION;
 +        }
 +
 +        // check if scope is supported by store provider
 +        if (!((ImageStoreProvider) storeProvider).isScopeSupported(scopeType)) {
 +            throw new InvalidParameterValueException("Image store provider " + providerName + " does not support scope " + scopeType);
 +        }
 +
 +        // check if we have already image stores from other different providers,
 +        // we currently are not supporting image stores from different
 +        // providers co-existing
 +        List<ImageStoreVO> imageStores = _imageStoreDao.listImageStores();
 +        for (ImageStoreVO store : imageStores) {
 +            if (!store.getProviderName().equalsIgnoreCase(providerName)) {
 +                throw new InvalidParameterValueException("You can only add new image stores from the same provider " + store.getProviderName()
 +                        + " already added");
 +            }
 +        }
 +
 +        if (dcId != null) {
 +            // Check if the zone exists in the system
 +            DataCenterVO zone = _dcDao.findById(dcId);
 +            if (zone == null) {
 +                throw new InvalidParameterValueException("Can't find zone by id " + dcId);
 +            }
 +
 +            Account account = UserContext.current().getCaller();
 +            if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) {
 +                PermissionDeniedException ex = new PermissionDeniedException(
 +                        "Cannot perform this operation, Zone with specified id is currently disabled");
-                 ex.addProxyObject(zone, dcId, "dcId");
++                ex.addProxyObject(zone.getUuid(), "dcId");
 +                throw ex;
 +            }
 +        }
 +
 +        Map<String, Object> params = new HashMap<String, Object>();
 +        params.put("zoneId", dcId);
 +        params.put("url", cmd.getUrl());
 +        params.put("name", cmd.getName());
 +        params.put("details", details);
 +        params.put("scope", scopeType);
 +        params.put("providerName", storeProvider.getName());
 +        params.put("role", DataStoreRole.Image);
 +
 +        DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle();
 +        DataStore store = null;
 +        try {
 +            store = lifeCycle.initialize(params);
 +        } catch (Exception e) {
 +            s_logger.debug("Failed to add data store", e);
 +            throw new CloudRuntimeException("Failed to add data store", e);
 +        }
 +
 +        if (((ImageStoreProvider) storeProvider).needDownloadSysTemplate()) {
 +            // trigger system vm template download
 +            this._imageSrv.downloadBootstrapSysTemplate(store);
 +        }
 +        else {
 +            // populate template_store_ref table
 +            this._imageSrv.addSystemVMTemplatesToSecondary(store);
 +        }
 +
 +        // associate builtin template with zones associated with this image
 +        // store
 +        this.associateCrosszoneTemplatesToZone(dcId);
 +
 +        return (ImageStore) _dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Image);
 +    }
 +
 +    private void associateCrosszoneTemplatesToZone(Long zoneId) {
 +        VMTemplateZoneVO tmpltZone;
 +
 +        List<VMTemplateVO> allTemplates = _vmTemplateDao.listAll();
 +        List<Long> dcIds = new ArrayList<Long>();
 +        if (zoneId != null) {
 +            dcIds.add(zoneId);
 +        } else {
 +            List<DataCenterVO> dcs = _dcDao.listAll();
 +            if (dcs != null) {
 +                for (DataCenterVO dc : dcs) {
 +                    dcIds.add(dc.getId());
 +                }
 +            }
 +        }
 +
 +        for (VMTemplateVO vt : allTemplates) {
 +            if (vt.isCrossZones()) {
 +                for (Long dcId : dcIds) {
 +                    tmpltZone = _vmTemplateZoneDao.findByZoneTemplate(dcId, vt.getId());
 +                    if (tmpltZone == null) {
 +                        VMTemplateZoneVO vmTemplateZone = new VMTemplateZoneVO(dcId, vt.getId(), new Date());
 +                        _vmTemplateZoneDao.persist(vmTemplateZone);
 +                    }
 +                }
 +            }
 +        }
 +    }
 +
 +    @Override
 +    public boolean deleteImageStore(DeleteImageStoreCmd cmd) {
 +        long storeId = cmd.getId();
 +        User caller = _accountMgr.getActiveUser(UserContext.current().getCallerUserId());
 +        // Verify that image store exists
 +        ImageStoreVO store = _imageStoreDao.findById(storeId);
 +        if (store == null) {
 +            throw new InvalidParameterValueException("Image store with id " + storeId + " doesn't exist");
 +        }
 +        _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), store.getDataCenterId());
 +
 +        // Verify that there are no live snapshot, template, volume on the image
 +        // store to be deleted
 +        List<SnapshotDataStoreVO> snapshots = _snapshotStoreDao.listByStoreId(storeId, DataStoreRole.Image);
 +        if (snapshots != null && snapshots.size() > 0) {
 +            throw new InvalidParameterValueException("Cannot delete image store with active snapshots backup!");
 +        }
 +        List<VolumeDataStoreVO> volumes = _volumeStoreDao.listByStoreId(storeId);
 +        if (volumes != null && volumes.size() > 0) {
 +            throw new InvalidParameterValueException("Cannot delete image store with active volumes backup!");
 +        }
 +
 +        // search if there are user templates stored on this image store, excluding system, builtin templates
 +        List<TemplateJoinVO> templates = this._templateViewDao.listActiveTemplates(storeId);
 +        if (templates != null && templates.size() > 0) {
 +            throw new InvalidParameterValueException("Cannot delete image store with active templates backup!");
 +        }
 +
 +        // ready to delete
 +        Transaction txn = Transaction.currentTxn();
 +        txn.start();
 +        // first delete from image_store_details table, we need to do that since
 +        // we are not actually deleting record from main
 +        // image_data_store table, so delete cascade will not work
 +        _imageStoreDetailsDao.deleteDetails(storeId);
 +        _snapshotStoreDao.deletePrimaryRecordsForStore(storeId);
 +        _volumeStoreDao.deletePrimaryRecordsForStore(storeId);
 +        _templateStoreDao.deletePrimaryRecordsForStore(storeId);
 +        _imageStoreDao.remove(storeId);
 +        txn.commit();
 +        return true;
 +    }
 +
 +    @Override
 +    public ImageStore createCacheStore(CreateCacheStoreCmd cmd) {
 +        String providerName = cmd.getProviderName();
 +        DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName);
 +
 +        if (storeProvider == null) {
 +            storeProvider = _dataStoreProviderMgr.getDefaultCacheDataStoreProvider();
 +            if (storeProvider == null) {
 +                throw new InvalidParameterValueException("can't find cache store provider: " + providerName);
 +            }
 +        }
 +
 +        Long dcId = cmd.getZoneId();
 +
 +        ScopeType scopeType = null;
 +        String scope = cmd.getScope();
 +        if (scope != null) {
 +            try {
 +                scopeType = Enum.valueOf(ScopeType.class, scope.toUpperCase());
 +
 +            } catch (Exception e) {
 +                throw new InvalidParameterValueException("invalid scope" + scope);
 +            }
 +
 +            if (scopeType != ScopeType.ZONE) {
 +                throw new InvalidParameterValueException("Only zone wide cache storage is supported");
 +            }
 +        }
 +
 +        if (scopeType == ScopeType.ZONE && dcId == null) {
 +            throw new InvalidParameterValueException("zone id can't be null, if scope is zone");
 +        }
 +
 +        // Check if the zone exists in the system
 +        DataCenterVO zone = _dcDao.findById(dcId);
 +        if (zone == null) {
 +            throw new InvalidParameterValueException("Can't find zone by id " + dcId);
 +        }
 +
 +        Account account = UserContext.current().getCaller();
 +        if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(account.getType())) {
 +            PermissionDeniedException ex = new PermissionDeniedException(
 +                    "Cannot perform this operation, Zone with specified id is currently disabled");
-             ex.addProxyObject(zone, dcId, "dcId");
++            ex.addProxyObject(zone.getUuid(), "dcId");
 +            throw ex;
 +        }
 +
 +        Map<String, Object> params = new HashMap<String, Object>();
 +        params.put("zoneId", dcId);
 +        params.put("url", cmd.getUrl());
 +        params.put("name", cmd.getUrl());
 +        params.put("details", cmd.getDetails());
 +        params.put("scope", scopeType);
 +        params.put("providerName", storeProvider.getName());
 +        params.put("role", DataStoreRole.ImageCache);
 +
 +        DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle();
 +        DataStore store = null;
 +        try {
 +            store = lifeCycle.initialize(params);
 +        } catch (Exception e) {
 +            s_logger.debug("Failed to add data store", e);
 +            throw new CloudRuntimeException("Failed to add data store", e);
 +        }
 +
 +        return (ImageStore) _dataStoreMgr.getDataStore(store.getId(), DataStoreRole.ImageCache);
 +    }
 +
  }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/storage/VolumeManager.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/storage/VolumeManager.java
index 5f533ca,47fbda8..ffa20d3
--- a/server/src/com/cloud/storage/VolumeManager.java
+++ b/server/src/com/cloud/storage/VolumeManager.java
@@@ -114,5 -106,7 +114,8 @@@ public interface VolumeManager extends 
              DiskOfferingVO offering, VMTemplateVO template, VMInstanceVO vm,
              Account owner);
  
 +
+     String getVmNameFromVolumeId(long volumeId);
+ 
+     String getStoragePoolOfVolume(long volumeId);
  }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/storage/VolumeManagerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/storage/VolumeManagerImpl.java
index 5abd432,43f3681..eca8428
--- a/server/src/com/cloud/storage/VolumeManagerImpl.java
+++ b/server/src/com/cloud/storage/VolumeManagerImpl.java
@@@ -388,15 -368,15 +393,15 @@@ public class VolumeManagerImpl extends 
          String url = cmd.getUrl();
          String format = cmd.getFormat();
          String imageStoreUuid = cmd.getImageStoreUuid();
 -        DataStore store = this._tmpltMgr.getImageStore(imageStoreUuid, zoneId);
 +        DataStore store = _tmpltMgr.getImageStore(imageStoreUuid, zoneId);
  
          validateVolume(caller, ownerId, zoneId, volumeName, url, format);
 -        
 +
-         VolumeVO volume = persistVolume(caller, ownerId, zoneId, volumeName,
+         VolumeVO volume = persistVolume(owner, zoneId, volumeName,
                  url, cmd.getFormat());
 -        
 -        VolumeInfo vol = this.volFactory.getVolume(volume.getId());
 -        
 +
 +        VolumeInfo vol = volFactory.getVolume(volume.getId());
 +
          RegisterVolumePayload payload = new RegisterVolumePayload(cmd.getUrl(), cmd.getChecksum(),
                  cmd.getFormat());
          vol.addPayload(payload);
@@@ -719,17 -704,15 +724,15 @@@
      public String getRandomVolumeName() {
          return UUID.randomUUID().toString();
      }
 -    
 +
-     private VolumeVO persistVolume(Account caller, long ownerId, Long zoneId,
+     private VolumeVO persistVolume(Account owner, Long zoneId,
              String volumeName, String url, String format) {
  
          Transaction txn = Transaction.currentTxn();
          txn.start();
  
 -        VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1,
 +        VolumeVO volume = new VolumeVO(volumeName, zoneId, -1L, -1L, -1,
                  new Long(-1), null, null, 0, Volume.Type.DATADISK);
-         Account owner = (caller.getId() == ownerId) ? caller : _accountMgr
-                           .getActiveAccountById(ownerId);
          volume.setPoolId(null);
          volume.setDataCenterId(zoneId);
          volume.setPodId(null);
@@@ -2547,187 -2619,16 +2560,198 @@@
      }
  
  
- 
- 
      @Override
 +    public Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account) throws ResourceAllocationException {
 +        VolumeInfo volume = volFactory.getVolume(volumeId);
 +        if (volume == null) {
 +            throw new InvalidParameterValueException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist");
 +        }
 +
 +        if (volume.getState() != Volume.State.Ready) {
 +            throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot.");
 +        }
 +
 +        CreateSnapshotPayload payload = new CreateSnapshotPayload();
 +        payload.setSnapshotId(snapshotId);
 +        payload.setSnapshotPolicyId(policyId);
 +        payload.setAccount(account);
 +        volume.addPayload(payload);
 +        return volService.takeSnapshot(volume);
 +    }
 +
 +    @Override
 +    public Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException {
 +        Account caller = UserContext.current().getCaller();
 +
 +        VolumeInfo volume = volFactory.getVolume(volumeId);
 +        if (volume == null) {
 +            throw new InvalidParameterValueException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist");
 +        }
 +        DataCenter zone = _dcDao.findById(volume.getDataCenterId());
 +        if (zone == null) {
 +            throw new InvalidParameterValueException("Can't find zone by id " + volume.getDataCenterId());
 +        }
 +
 +        if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) {
 +            throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zone.getName());
 +        }
 +
 +        if (volume.getState() != Volume.State.Ready) {
 +            throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot.");
 +        }
 +
 +        if ( volume.getTemplateId() != null ) {
 +            VMTemplateVO  template = _templateDao.findById(volume.getTemplateId());
 +            if( template != null && template.getTemplateType() == Storage.TemplateType.SYSTEM ) {
 +                throw new InvalidParameterValueException("VolumeId: " + volumeId + " is for System VM , Creating snapshot against System VM volumes is not supported");
 +            }
 +        }
 +
 +        StoragePool storagePool = (StoragePool)volume.getDataStore();
 +        if (storagePool == null) {
 +            throw new InvalidParameterValueException("VolumeId: " + volumeId + " please attach this volume to a VM before create snapshot for it");
 +        }
 +
 +        return snapshotMgr.allocSnapshot(volumeId, policyId);
 +    }
 +
 +
 +    @Override
 +    @ActionEvent(eventType = EventTypes.EVENT_VOLUME_EXTRACT, eventDescription = "extracting volume", async = true)
 +    public String extractVolume(ExtractVolumeCmd cmd) {
 +        Long volumeId = cmd.getId();
 +        Long zoneId = cmd.getZoneId();
 +        String mode = cmd.getMode();
 +        Account account = UserContext.current().getCaller();
 +
 +        if (!_accountMgr.isRootAdmin(account.getType()) && ApiDBUtils.isExtractionDisabled()) {
 +            throw new PermissionDeniedException("Extraction has been disabled by admin");
 +        }
 +
 +        VolumeVO volume = _volumeDao.findById(volumeId);
 +        if (volume == null) {
 +            InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find volume with specified volumeId");
-             ex.addProxyObject(volume, volumeId, "volumeId");
++            ex.addProxyObject(volumeId.toString(), "volumeId");
 +            throw ex;
 +        }
 +
 +        // perform permission check
 +        _accountMgr.checkAccess(account, null, true, volume);
 +
 +        if (_dcDao.findById(zoneId) == null) {
 +            throw new InvalidParameterValueException("Please specify a valid zone.");
 +        }
 +        if (volume.getPoolId() == null) {
 +            throw new InvalidParameterValueException("The volume doesnt belong to a storage pool so cant extract it");
 +        }
 +        // Extract activity only for detached volumes or for volumes whose
 +        // instance is stopped
 +        if (volume.getInstanceId() != null && ApiDBUtils.findVMInstanceById(volume.getInstanceId()).getState() != State.Stopped) {
 +            s_logger.debug("Invalid state of the volume with ID: " + volumeId
 +                    + ". It should be either detached or the VM should be in stopped state.");
 +            PermissionDeniedException ex = new PermissionDeniedException(
 +                    "Invalid state of the volume with specified ID. It should be either detached or the VM should be in stopped state.");
-             ex.addProxyObject(volume, volumeId, "volumeId");
++            ex.addProxyObject(volume.getUuid(), "volumeId");
 +            throw ex;
 +        }
 +
 +        if (volume.getVolumeType() != Volume.Type.DATADISK) {
 +            // Datadisk dont have any template dependence.
 +
 +            VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
 +            if (template != null) { // For ISO based volumes template = null and
 +                // we allow extraction of all ISO based
 +                // volumes
 +                boolean isExtractable = template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;
 +                if (!isExtractable && account != null && account.getType() != Account.ACCOUNT_TYPE_ADMIN) {
 +                    // Global admins are always allowed to extract
 +                    PermissionDeniedException ex = new PermissionDeniedException("The volume with specified volumeId is not allowed to be extracted");
-                     ex.addProxyObject(volume, volumeId, "volumeId");
++                    ex.addProxyObject(volume.getUuid(), "volumeId");
 +                    throw ex;
 +                }
 +            }
 +        }
 +
 +        Upload.Mode extractMode;
 +        if (mode == null || (!mode.equals(Upload.Mode.FTP_UPLOAD.toString()) && !mode.equals(Upload.Mode.HTTP_DOWNLOAD.toString()))) {
 +            throw new InvalidParameterValueException("Please specify a valid extract Mode ");
 +        } else {
 +            extractMode = mode.equals(Upload.Mode.FTP_UPLOAD.toString()) ? Upload.Mode.FTP_UPLOAD : Upload.Mode.HTTP_DOWNLOAD;
 +        }
 +
 +        // Clean up code to remove all those previous uploadVO and uploadMonitor code. Previous code is trying to fake an async operation purely in
 +        // db table with uploadVO and async_job entry, but internal implementation is actually synchronous.
 +        StoragePool srcPool = (StoragePool) this.dataStoreMgr.getPrimaryDataStore(volume.getPoolId());
 +        ImageStoreEntity secStore = (ImageStoreEntity) this.dataStoreMgr.getImageStore(zoneId);
 +        String secondaryStorageURL = secStore.getUri();
 +
 +        String value = this._configDao.getValue(Config.CopyVolumeWait.toString());
 +        int copyvolumewait = NumbersUtil.parseInt(value, Integer.parseInt(Config.CopyVolumeWait.getDefaultValue()));
 +        // Copy volume from primary to secondary storage
 +        VolumeInfo srcVol = this.volFactory.getVolume(volume.getId());
 +        AsyncCallFuture<VolumeApiResult> cvAnswer = this.volService.copyVolume(srcVol, secStore);
 +        // Check if you got a valid answer.
 +        VolumeApiResult cvResult = null;
 +        try {
 +            cvResult = cvAnswer.get();
 +        } catch (InterruptedException e1) {
 +            s_logger.debug("failed copy volume", e1);
 +            throw new CloudRuntimeException("Failed to copy volume", e1);
 +        } catch (ExecutionException e1) {
 +            s_logger.debug("failed copy volume", e1);
 +            throw new CloudRuntimeException("Failed to copy volume", e1);
 +        }
 +        if (cvResult == null || cvResult.isFailed()) {
 +            String errorString = "Failed to copy the volume from the source primary storage pool to secondary storage.";
 +            throw new CloudRuntimeException(errorString);
 +        }
 +
 +        VolumeInfo vol = cvResult.getVolume();
 +        String volumeLocalPath = vol.getPath();
 +        String volumeName = StringUtils.substringBeforeLast(StringUtils.substringAfterLast(volumeLocalPath, "/"), ".");
 +        // volss, handle the ova special case;
 +        if (getFormatForPool(srcPool) == "ova") {
 +            // TODO: need to handle this for S3 as secondary storage
 +            CreateVolumeOVACommand cvOVACmd = new CreateVolumeOVACommand(secondaryStorageURL, volumeLocalPath, volumeName, srcPool, copyvolumewait);
 +            CreateVolumeOVAAnswer OVAanswer = null;
 +
 +            try {
 +                cvOVACmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
 +                // for extract volume, create the ova file here;
 +                OVAanswer = (CreateVolumeOVAAnswer) storageMgr.sendToPool(srcPool, cvOVACmd);
 +            } catch (StorageUnavailableException e) {
 +                s_logger.debug("Storage unavailable");
 +            }
 +        }
 +        return secStore.createEntityExtractUrl(vol.getPath(), vol.getFormat());
 +    }
 +
 +    private String getFormatForPool(StoragePool pool) {
 +        ClusterVO cluster = ApiDBUtils.findClusterById(pool.getClusterId());
 +
 +        if (cluster.getHypervisorType() == HypervisorType.XenServer) {
 +            return "vhd";
 +        } else if (cluster.getHypervisorType() == HypervisorType.KVM) {
 +            return "qcow2";
 +        } else if (cluster.getHypervisorType() == HypervisorType.VMware) {
 +            return "ova";
 +        } else if (cluster.getHypervisorType() == HypervisorType.Ovm) {
 +            return "raw";
 +        } else {
 +            return null;
 +        }
 +    }
++
++    @Override
+     public String getVmNameFromVolumeId(long volumeId) {
+         Long instanceId;
+         VolumeVO volume = _volsDao.findById(volumeId);
+         return getVmNameOnVolume(volume);
+     }
+ 
+     @Override
+     public String getStoragePoolOfVolume(long volumeId) {
+         VolumeVO vol = _volsDao.findById(volumeId);
+         return dataStoreMgr.getPrimaryDataStore(vol.getPoolId()).getUuid();
+     }
  }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/storage/listener/StoragePoolMonitor.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
index 586f770,c343286..954c7e9
--- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
+++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java
@@@ -525,21 -537,29 +525,29 @@@ public class SecondaryStorageManagerImp
  
          DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
          DataCenter dc = _dcDao.findById(plan.getDataCenterId());
 -        
 +
+         NetworkVO defaultNetwork = null;
+         if (dc.getNetworkType() == NetworkType.Advanced && dc.isSecurityGroupEnabled()) {
+             List<NetworkVO> networks = _networkDao.listByZoneSecurityGroup(dataCenterId);
+             if (networks == null || networks.size() == 0) {
+                 throw new CloudRuntimeException("Can not found security enabled network in SG Zone " + dc);
+             }
+             defaultNetwork = networks.get(0);
+         } else {
 -            TrafficType defaultTrafficType = TrafficType.Public;
 +        TrafficType defaultTrafficType = TrafficType.Public;
+ 
 -            if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) {
 -                defaultTrafficType = TrafficType.Guest;
 -            }
 -            List<NetworkVO> defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType);
 +        if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) {
 +        	defaultTrafficType = TrafficType.Guest;
 +        }
- 
 +        List<NetworkVO> defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType);
- 
-         //api should never allow this situation to happen
+             // api should never allow this situation to happen
 -            if (defaultNetworks.size() != 1) {
 +        if (defaultNetworks.size() != 1) {
-         	throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1");
+                 throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type "
+                                 + defaultTrafficType + " when expect to find 1");
+             }
+             defaultNetwork = defaultNetworks.get(0);
          }
  
-         NetworkVO defaultNetwork = defaultNetworks.get(0);
- 
          List<? extends NetworkOffering> offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork, NetworkOfferingVO.SystemManagementNetwork, NetworkOfferingVO.SystemStorageNetwork);
          List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>(offerings.size() + 1);
          NicProfile defaultNic = new NicProfile();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index a7e6137,92d80ee..a1a4c90
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@@ -932,80 -1007,49 +932,84 @@@ public class SnapshotManagerImpl extend
              throw new InvalidParameterValueException("Ovm won't support taking snapshot");
          }
  
 -        // Verify permissions
 -        _accountMgr.checkAccess(caller, null, true, volume);
 -        Type snapshotType = getSnapshotType(policyId);
 -        Account owner = _accountMgr.getAccount(volume.getAccountId());
 +		if (volume.getHypervisorType().equals(HypervisorType.KVM)) {
 +			List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(cluster.getId());
 +			if (hosts != null && !hosts.isEmpty()) {
 +				HostVO host = hosts.get(0);
 +				if (!hostSupportSnapsthot(host)) {
 +					throw new CloudRuntimeException("KVM Snapshot is not supported on cluster: " + host.getId());
 +				}
 +			}
 +		}
 +
 +		// if volume is attached to a vm in destroyed or expunging state; disallow
 +		if (volume.getInstanceId() != null) {
 +			UserVmVO userVm = _vmDao.findById(volume.getInstanceId());
 +			if (userVm != null) {
- 				if (userVm.getState().equals(State.Destroyed) || userVm.getState().equals(State.Expunging)) {
- 					throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volume.getId() + " is associated with vm:" + userVm.getInstanceName() + " is in "
- 							+ userVm.getState().toString() + " state");
- 				}
++                if (userVm.getState().equals(State.Destroyed) || userVm.getState().equals(State.Expunging)) {
++                    throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volume.getId()
++                            + " is associated with vm:" + userVm.getInstanceName() + " is in "
++                            + userVm.getState().toString() + " state");
++                }
  
- 				if(userVm.getHypervisorType() == HypervisorType.VMware || userVm.getHypervisorType() == HypervisorType.KVM) {
- 					List<SnapshotVO> activeSnapshots = _snapshotDao.listByInstanceId(volume.getInstanceId(), Snapshot.State.Creating,  Snapshot.State.CreatedOnPrimary,  Snapshot.State.BackingUp);
- 					if(activeSnapshots.size() > 1)
- 						throw new CloudRuntimeException("There is other active snapshot tasks on the instance to which the volume is attached, please try again later");
- 				}
 -        try{
 -            _resourceLimitMgr.checkResourceLimit(owner, ResourceType.snapshot);
 -            if (backup) {
 -                _resourceLimitMgr.checkResourceLimit(owner, ResourceType.secondary_storage, new Long(volume.getSize()));
 -            } else {
 -                _resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, new Long(volume.getSize()));
++                if (userVm.getHypervisorType() == HypervisorType.VMware
++                        || userVm.getHypervisorType() == HypervisorType.KVM) {
++                    List<SnapshotVO> activeSnapshots = _snapshotDao.listByInstanceId(volume.getInstanceId(),
++                            Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp);
++                    if (activeSnapshots.size() > 1)
++                        throw new CloudRuntimeException(
++                                "There is other active snapshot tasks on the instance to which the volume is attached, please try again later");
++                }
 +
- 				  List<VMSnapshotVO> activeVMSnapshots = _vmSnapshotDao.listByInstanceId(userVm.getId(),
- 			                VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging);
- 			        if (activeVMSnapshots.size() > 0) {
- 			            throw new CloudRuntimeException(
- 			                    "There is other active vm snapshot tasks on the instance to which the volume is attached, please try again later");
- 			        }
++                List<VMSnapshotVO> activeVMSnapshots = _vmSnapshotDao.listByInstanceId(userVm.getId(),
++                        VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging);
++                if (activeVMSnapshots.size() > 0) {
++                    throw new CloudRuntimeException(
++                            "There is other active vm snapshot tasks on the instance to which the volume is attached, please try again later");
++                }
 +			}
 +		}
 +
 +		return true;
 +	}
 +    @Override
 +    public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationException {
 +        CreateSnapshotPayload payload = (CreateSnapshotPayload)volume.getpayload();
 +        Long snapshotId = payload.getSnapshotId();
 +        Account snapshotOwner = payload.getAccount();
 +        SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotId, volume.getDataStore());
 +        boolean processed = false;
 +
 +        try {
 +            for (SnapshotStrategy strategy : snapshotStrategies) {
 +                if (strategy.canHandle(snapshot)) {
 +                    processed = true;
 +                    snapshot = strategy.takeSnapshot(snapshot);
 +                    break;
 +                }
              }
 -        } catch (ResourceAllocationException e) {
 -            if (snapshotType != Type.MANUAL){
 -                String msg = "Snapshot resource limit exceeded for account id : " + owner.getId() + ". Failed to create recurring snapshots";
 -                s_logger.warn(msg);
 -                _alertMgr.sendAlert(AlertManager.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg,
 -                        "Snapshot resource limit exceeded for account id : " + owner.getId() + ". Failed to create recurring snapshots; please use updateResourceLimit to increase the limit");
 +            if (!processed) {
 +                throw new CloudRuntimeException("Can't find snapshot strategy to deal with snapshot:" + snapshotId);
              }
 -            throw e;
 -        }
 +            postCreateSnapshot(volume.getId(), snapshotId, payload.getSnapshotPolicyId());
  
 -        // Determine the name for this snapshot
 -        // Snapshot Name: VMInstancename + volumeName + timeString
 -        String timeString = DateUtil.getDateDisplayString(DateUtil.GMT_TIMEZONE, new Date(), DateUtil.YYYYMMDD_FORMAT);
 +            UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SNAPSHOT_CREATE, snapshot.getAccountId(),
 +                    snapshot.getDataCenterId(), snapshotId, snapshot.getName(), null, null,
 +                    volume.getSize(), snapshot.getClass().getName(), snapshot.getUuid());
  
 -        String snapshotName = volume.getUuid() + "_" + timeString;
  
 -        // Create the Snapshot object and save it so we can return it to the
 -        // user        
 -        HypervisorType hypervisorType = this._volsDao.getHypervisorType(volumeId);
 -        SnapshotVO snapshotVO = new SnapshotVO(volume.getDataCenterId(), volume.getAccountId(), volume.getDomainId(), volume.getId(), volume.getDiskOfferingId(), null, snapshotName,
 -                (short) snapshotType.ordinal(), snapshotType.name(), volume.getSize(), hypervisorType);
 -        SnapshotVO snapshot = _snapshotDao.persist(snapshotVO);
 -        if (snapshot == null) {
 -            throw new CloudRuntimeException("Failed to create snapshot for volume: "+volumeId);
 -        }
 -        if (backup) {
 -            _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.secondary_storage,
 -                    new Long(volume.getSize()));
 -        } else {
 -            _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.primary_storage,
 -                    new Long(volume.getSize()));
 +            _resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot);
 +
 +        } catch(Exception e) {
 +            s_logger.debug("Failed to create snapshot", e);
 +            if (backup) {
 +                _resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), ResourceType.secondary_storage,
 +                        new Long(volume.getSize()));
 +            } else {
 +                _resourceLimitMgr.decrementResourceCount(snapshotOwner.getId(), ResourceType.primary_storage,
 +                        new Long(volume.getSize()));
 +            }
 +            throw new CloudRuntimeException("Failed to create snapshot", e);
          }
          return snapshot;
      }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/18aeef3e/server/src/com/cloud/template/TemplateManagerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/template/TemplateManagerImpl.java
index c15bd6b,517d4ba..273614c
--- a/server/src/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/com/cloud/template/TemplateManagerImpl.java
@@@ -1673,96 -2125,52 +1673,96 @@@ public class TemplateManagerImpl extend
      }
  
      @Override
 -    public List<HostVO> getSecondaryStorageHosts(long zoneId) {
 -        List<HostVO> hosts = _ssvmMgr
 -                .listSecondaryStorageHostsInOneZone(zoneId);
 -        if (hosts == null || hosts.size() == 0) {
 -            hosts = _ssvmMgr.listLocalSecondaryStorageHostsInOneZone(zoneId);
 -            if (hosts.isEmpty()) {
 -                return new ArrayList<HostVO>();
 -            }
 -        }
 -        return hosts;
 +    public VMTemplateVO updateTemplate(UpdateIsoCmd cmd) {
 +        return updateTemplateOrIso(cmd);
      }
 -    
 +
      @Override
 -    public Long getTemplateSize(long templateId, long zoneId) {
 -        SearchCriteria<VMTemplateHostVO> sc = HostTemplateStatesSearch.create();
 -        sc.setParameters("id", templateId);
 -        sc.setParameters(
 -                "state",
 -                com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
 -        sc.setJoinParameters("host", "dcId", zoneId);
 -        List<VMTemplateSwiftVO> tsvs = _tmpltSwiftDao
 -                .listByTemplateId(templateId);
 -        Long size = null;
 -        if (tsvs != null && tsvs.size() > 0) {
 -            size = tsvs.get(0).getSize();
 -        }
 -
 -        if (size == null && _s3Mgr.isS3Enabled()) {
 -            VMTemplateS3VO vmTemplateS3VO = _vmS3TemplateDao
 -                    .findOneByTemplateId(templateId);
 -            if (vmTemplateS3VO != null) {
 -                size = vmTemplateS3VO.getSize();
 +    public VMTemplateVO updateTemplate(UpdateTemplateCmd cmd) {
 +        return updateTemplateOrIso(cmd);
 +    }
 +
 +    private VMTemplateVO updateTemplateOrIso(BaseUpdateTemplateOrIsoCmd cmd) {
 +        Long id = cmd.getId();
 +        String name = cmd.getTemplateName();
 +        String displayText = cmd.getDisplayText();
 +        String format = cmd.getFormat();
 +        Long guestOSId = cmd.getOsTypeId();
 +        Boolean passwordEnabled = cmd.isPasswordEnabled();
 +        Boolean bootable = cmd.isBootable();
 +        Integer sortKey = cmd.getSortKey();
 +        Account account = UserContext.current().getCaller();
 +
 +        // verify that template exists
 +        VMTemplateVO template = _tmpltDao.findById(id);
 +        if (template == null || template.getRemoved() != null) {
 +            InvalidParameterValueException ex = new InvalidParameterValueException("unable to find template/iso with specified id");
-             ex.addProxyObject(template, id, "templateId");
++            ex.addProxyObject(String.valueOf(id), "templateId");
 +            throw ex;
 +        }
 +
 +        // Don't allow to modify system template
 +        if (id == Long.valueOf(1)) {
 +            InvalidParameterValueException ex = new InvalidParameterValueException("Unable to update template/iso of specified id");
-             ex.addProxyObject(template, id, "templateId");
++            ex.addProxyObject(String.valueOf(id), "templateId");
 +            throw ex;
 +        }
 +
 +        // do a permission check
 +        _accountMgr.checkAccess(account, AccessType.ModifyEntry, true, template);
 +
 +        boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null
 +                && bootable == null && sortKey == null);
 +        if (!updateNeeded) {
 +            return template;
 +        }
 +
 +        template = _tmpltDao.createForUpdate(id);
 +
 +        if (name != null) {
 +            template.setName(name);
 +        }
 +
 +        if (displayText != null) {
 +            template.setDisplayText(displayText);
 +        }
 +
 +        if (sortKey != null) {
 +            template.setSortKey(sortKey);
 +        }
 +
 +        ImageFormat imageFormat = null;
 +        if (format != null) {
 +            try {
 +                imageFormat = ImageFormat.valueOf(format.toUpperCase());
 +            } catch (IllegalArgumentException e) {
 +                throw new InvalidParameterValueException("Image format: " + format + " is incorrect. Supported formats are "
 +                        + EnumUtils.listValues(ImageFormat.values()));
              }
 +
 +            template.setFormat(imageFormat);
          }
  
 -        if (size == null) {
 -            List<VMTemplateHostVO> sss = this.templateHostDao.search(sc, null);
 -            if (sss == null || sss.size() == 0) {
 -                throw new CloudRuntimeException("Template "
 -                        + templateId
 -                        + " has not been completely downloaded to zone "
 -                        + zoneId);
 +        if (guestOSId != null) {
 +            GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
 +
 +            if (guestOS == null) {
 +                throw new InvalidParameterValueException("Please specify a valid guest OS ID.");
 +            } else {
 +                template.setGuestOSId(guestOSId);
              }
 -            size = sss.get(0).getSize();
          }
 -        return size;
 -    }
  
 +        if (passwordEnabled != null) {
 +            template.setEnablePassword(passwordEnabled);
 +        }
 +
 +        if (bootable != null) {
 +            template.setBootable(bootable);
 +        }
 +
 +        _tmpltDao.update(id, template);
 +
 +        return _tmpltDao.findById(id);
 +    }
  }