You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by al...@apache.org on 2012/07/06 20:43:22 UTC

[2/6] Resource tags: 1) Remove tag records when correspdonding cloudStack object gets removed 2) added "tags" request parameter to the banch of list* Api commands (listVirtualMachines, listSnapshots - all commands are listed in the resource tags function

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/network/rules/RulesManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java
index eae922c..666e269 100755
--- a/server/src/com/cloud/network/rules/RulesManagerImpl.java
+++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java
@@ -52,6 +52,9 @@ import com.cloud.network.rules.FirewallRule.Purpose;
 import com.cloud.network.rules.dao.PortForwardingRulesDao;
 import com.cloud.offering.NetworkOffering;
 import com.cloud.projects.Project.ListProjectResourcesCriteria;
+import com.cloud.server.ResourceTag.TaggedResourceType;
+import com.cloud.tags.ResourceTagVO;
+import com.cloud.tags.dao.ResourceTagDao;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
 import com.cloud.user.DomainManager;
@@ -69,7 +72,6 @@ import com.cloud.utils.db.SearchCriteria.Op;
 import com.cloud.utils.db.Transaction;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.net.Ip;
-import com.cloud.utils.AnnotationHelper;
 import com.cloud.vm.Nic;
 import com.cloud.vm.UserVmVO;
 import com.cloud.vm.VirtualMachine;
@@ -110,6 +112,8 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
     ConfigurationManager _configMgr;
     @Inject
     NicDao _nicDao;
+    @Inject
+    ResourceTagDao _resourceTagDao;
 
     @Override
     public void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller) {
@@ -583,6 +587,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
     public List<? extends PortForwardingRule> listPortForwardingRules(ListPortForwardingRulesCmd cmd) {
         Long ipId = cmd.getIpAddressId();
         Long id = cmd.getId();
+        Map<String, String> tags = cmd.getTags();
 
         Account caller = UserContext.current().getCaller();
         List<Long> permittedAccounts = new ArrayList<Long>();
@@ -608,6 +613,19 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
         sb.and("id", sb.entity().getId(), Op.EQ);
         sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ);
         sb.and("purpose", sb.entity().getPurpose(), Op.EQ);
+        
+        if (tags != null && !tags.isEmpty()) {
+            SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
+            for (int count=0; count < tags.size(); count++) {
+                tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
+                tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
+                tagSearch.cp();
+            }
+            tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
+            sb.groupBy(sb.entity().getId());
+            sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
+        }
+
 
         SearchCriteria<PortForwardingRuleVO> sc = sb.create();
         _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
@@ -615,6 +633,16 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
         if (id != null) {
             sc.setParameters("id", id);
         }
+        
+        if (tags != null && !tags.isEmpty()) {
+            int count = 0;
+            sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.PortForwardingRule.toString());
+            for (String key : tags.keySet()) {
+                sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key);
+                sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key));
+                count++;
+            }
+        }
 
         if (ipId != null) {
             sc.setParameters("ip", ipId);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java
index e9fb111..a1ed6d7 100755
--- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java
+++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java
@@ -77,6 +77,9 @@ import com.cloud.network.security.dao.VmRulesetLogDao;
 import com.cloud.projects.Project.ListProjectResourcesCriteria;
 import com.cloud.projects.ProjectManager;
 import com.cloud.server.ManagementServer;
+import com.cloud.server.ResourceTag.TaggedResourceType;
+import com.cloud.tags.ResourceTagVO;
+import com.cloud.tags.dao.ResourceTagDao;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
 import com.cloud.user.DomainManager;
@@ -93,6 +96,7 @@ import com.cloud.utils.concurrency.NamedThreadFactory;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.Filter;
 import com.cloud.utils.db.GlobalLock;
+import com.cloud.utils.db.JoinBuilder;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.Transaction;
@@ -155,6 +159,8 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
     ProjectManager _projectMgr;
     @Inject
     UsageEventDao _usageEventDao;
+    @Inject
+    ResourceTagDao _resourceTagDao;
     
     ScheduledExecutorService _executorPool;
     ScheduledExecutorService _cleanupExecutor;
@@ -1093,6 +1099,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
         Long id = cmd.getId();
         Object keyword = cmd.getKeyword();
         List<Long> permittedAccounts = new ArrayList<Long>();
+        Map<String, String> tags = cmd.getTags();
 
         if (instanceId != null) {
             UserVmVO userVM = _userVMDao.findById(instanceId);
@@ -1117,6 +1124,18 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
 
         sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
         sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
+        
+        if (tags != null && !tags.isEmpty()) {
+            SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
+            for (int count=0; count < tags.size(); count++) {
+                tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
+                tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
+                tagSearch.cp();
+            }
+            tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
+            sb.groupBy(sb.entity().getId());
+            sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
+        }
 
         SearchCriteria<SecurityGroupVO> sc = sb.create();
         _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
@@ -1124,6 +1143,16 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
         if (id != null) {
             sc.setParameters("id", id);
         }
+        
+        if (tags != null && !tags.isEmpty()) {
+            int count = 0;
+            sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.SecurityGroup.toString());
+            for (String key : tags.keySet()) {
+                sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key);
+                sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key));
+                count++;
+            }
+        }
 
         if (securityGroup != null) {
             sc.setParameters("name", securityGroup);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java b/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java
index a962e85..7f921a2 100644
--- a/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java
+++ b/server/src/com/cloud/network/security/dao/SecurityGroupDaoImpl.java
@@ -21,19 +21,26 @@ import java.util.List;
 import javax.ejb.Local;
 
 import com.cloud.network.security.SecurityGroupVO;
+import com.cloud.server.ResourceTag.TaggedResourceType;
+import com.cloud.tags.dao.ResourceTagsDaoImpl;
+import com.cloud.utils.component.ComponentLocator;
+import com.cloud.utils.db.DB;
 import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
-
-@Local(value={SecurityGroupDao.class})
-public class SecurityGroupDaoImpl extends GenericDaoBase<SecurityGroupVO, Long> implements SecurityGroupDao {
+import com.cloud.utils.db.Transaction;
+
+@Local(value={SecurityGroupDao.class})
+public class SecurityGroupDaoImpl extends GenericDaoBase<SecurityGroupVO, Long> implements SecurityGroupDao {
     private SearchBuilder<SecurityGroupVO> AccountIdSearch;
     private SearchBuilder<SecurityGroupVO> AccountIdNameSearch;
     private SearchBuilder<SecurityGroupVO> AccountIdNamesSearch;
-
-    protected SecurityGroupDaoImpl() {
-        AccountIdSearch = createSearchBuilder();
-        AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
+    ResourceTagsDaoImpl _tagsDao = ComponentLocator.inject(ResourceTagsDaoImpl.class);
+
+
+    protected SecurityGroupDaoImpl() {
+        AccountIdSearch = createSearchBuilder();
+        AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
         AccountIdSearch.done();
         
         AccountIdNameSearch = createSearchBuilder();
@@ -88,8 +95,23 @@ public class SecurityGroupDaoImpl extends GenericDaoBase<SecurityGroupVO, Long>
 	}
 	@Override
 	public int removeByAccountId(long accountId) {
-	    SearchCriteria sc = AccountIdSearch.create();
+	    SearchCriteria<SecurityGroupVO> sc = AccountIdSearch.create();
 	    sc.setParameters("accountId", accountId);
 	    return expunge(sc);
 	} 
-}
+
+	
+	@Override
+    @DB
+    public boolean remove(Long id) {
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
+        SecurityGroupVO entry = findById(id);
+        if (entry != null) {
+            _tagsDao.removeBy(id, TaggedResourceType.SecurityGroup);
+        }
+        boolean result = super.remove(id);
+        txn.commit();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/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 1151fcd..ddcf751 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -170,6 +170,7 @@ import com.cloud.projects.Project;
 import com.cloud.projects.Project.ListProjectResourcesCriteria;
 import com.cloud.projects.ProjectManager;
 import com.cloud.resource.ResourceManager;
+import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.service.ServiceOfferingVO;
 import com.cloud.service.dao.ServiceOfferingDao;
 import com.cloud.storage.DiskOfferingVO;
@@ -196,6 +197,8 @@ import com.cloud.storage.secondary.SecondaryStorageVmManager;
 import com.cloud.storage.snapshot.SnapshotManager;
 import com.cloud.storage.swift.SwiftManager;
 import com.cloud.storage.upload.UploadMonitor;
+import com.cloud.tags.ResourceTagVO;
+import com.cloud.tags.dao.ResourceTagDao;
 import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
@@ -248,6 +251,7 @@ import com.cloud.vm.dao.NicDao;
 import com.cloud.vm.dao.SecondaryStorageVmDao;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.VMInstanceDao;
+
 import edu.emory.mathcs.backport.java.util.Arrays;
 import edu.emory.mathcs.backport.java.util.Collections;
 
@@ -303,6 +307,7 @@ public class ManagementServerImpl implements ManagementServer {
     private final HypervisorCapabilitiesDao _hypervisorCapabilitiesDao;
     private final Adapters<HostAllocator> _hostAllocators;
     private final ConfigurationManager _configMgr;
+    private final ResourceTagDao _resourceTagDao;
     
     @Inject
     ProjectManager _projectMgr;
@@ -378,6 +383,7 @@ public class ManagementServerImpl implements ManagementServer {
         _ksMgr = locator.getManager(KeystoreManager.class);
         _resourceMgr = locator.getManager(ResourceManager.class);
         _configMgr = locator.getManager(ConfigurationManager.class);
+        _resourceTagDao = locator.getDao(ResourceTagDao.class);
 
         _hypervisorCapabilitiesDao = locator.getDao(HypervisorCapabilitiesDao.class);
 
@@ -1252,6 +1258,7 @@ public class ManagementServerImpl implements ManagementServer {
     public Set<Pair<Long, Long>> listIsos(ListIsosCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
         TemplateFilter isoFilter = TemplateFilter.valueOf(cmd.getIsoFilter());
         Account caller = UserContext.current().getCaller();
+        Map<String, String> tags = cmd.getTags();
 
         boolean listAll = (caller.getType() != Account.ACCOUNT_TYPE_NORMAL && (isoFilter != null && isoFilter == TemplateFilter.all));
         List<Long> permittedAccountIds = new ArrayList<Long>();
@@ -1266,14 +1273,14 @@ public class ManagementServerImpl implements ManagementServer {
 
         HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor());
         return listTemplates(cmd.getId(), cmd.getIsoName(), cmd.getKeyword(), isoFilter, true, cmd.isBootable(), cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, true,
-                cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria);
+                cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags);
     }
 
     @Override
     public Set<Pair<Long, Long>> listTemplates(ListTemplatesCmd cmd) throws IllegalArgumentException, InvalidParameterValueException {
         TemplateFilter templateFilter = TemplateFilter.valueOf(cmd.getTemplateFilter());
         Long id = cmd.getId();
-
+        Map<String, String> tags = cmd.getTags();
         Account caller = UserContext.current().getCaller();
 
         boolean listAll = (caller.getType() != Account.ACCOUNT_TYPE_NORMAL && (templateFilter != null && templateFilter == TemplateFilter.all));
@@ -1290,11 +1297,11 @@ public class ManagementServerImpl implements ManagementServer {
         HypervisorType hypervisorType = HypervisorType.getType(cmd.getHypervisor());
 
         return listTemplates(id, cmd.getTemplateName(), cmd.getKeyword(), templateFilter, false, null, cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), hypervisorType, showDomr,
-                cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria);
+                cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags);
     }
 
     private Set<Pair<Long, Long>> listTemplates(Long templateId, String name, String keyword, TemplateFilter templateFilter, boolean isIso, Boolean bootable, Long pageSize, Long startIndex,
-            Long zoneId, HypervisorType hyperType, boolean showDomr, boolean onlyReady, List<Account> permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria) {
+            Long zoneId, HypervisorType hyperType, boolean showDomr, boolean onlyReady, List<Account> permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria, Map<String, String> tags) {
 
         VMTemplateVO template = null;
         if (templateId != null) {
@@ -1330,10 +1337,12 @@ public class ManagementServerImpl implements ManagementServer {
         Set<Pair<Long, Long>> templateZonePairSet = new HashSet<Pair<Long, Long>>();
         if (_swiftMgr.isSwiftEnabled()) {
             if (template == null) {
-                templateZonePairSet = _templateDao.searchSwiftTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr,
+                templateZonePairSet = _templateDao.searchSwiftTemplates(name, keyword, templateFilter, isIso, 
+                        hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr,
                         permittedAccounts, caller);
                 Set<Pair<Long, Long>> templateZonePairSet2 = new HashSet<Pair<Long, Long>>();
-                templateZonePairSet2 = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr,
+                templateZonePairSet2 = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, 
+                        bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr,
                         permittedAccounts, caller, listProjectResourcesCriteria);
                 for (Pair<Long, Long> tmpltPair : templateZonePairSet2) {
                     if (!templateZonePairSet.contains(new Pair<Long, Long>(tmpltPair.first(), -1L))) {
@@ -1351,7 +1360,8 @@ public class ManagementServerImpl implements ManagementServer {
             }
         } else {
             if (template == null) {
-                templateZonePairSet = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr,
+                templateZonePairSet = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, 
+                        bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr,
                         permittedAccounts, caller, listProjectResourcesCriteria);
             } else {
                 // if template is not public, perform permission check here
@@ -1675,6 +1685,7 @@ public class ManagementServerImpl implements ManagementServer {
         Long ipId = cmd.getId();
         Boolean sourceNat = cmd.getIsSourceNat();
         Boolean staticNat = cmd.getIsStaticNat();
+        Map<String, String> tags = cmd.getTags();
 
         Account caller = UserContext.current().getCaller();
         List<Long> permittedAccounts = new ArrayList<Long>();
@@ -1712,6 +1723,19 @@ public class ManagementServerImpl implements ManagementServer {
         if (keyword != null && address == null) {
             sb.and("addressLIKE", sb.entity().getAddress(), SearchCriteria.Op.LIKE);
         }
+        
+        if (tags != null && !tags.isEmpty()) {
+            SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
+            for (int count=0; count < tags.size(); count++) {
+                tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
+                tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
+                tagSearch.cp();
+            }
+            tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
+            sb.groupBy(sb.entity().getId());
+            sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
+        }
+
 
         SearchBuilder<VlanVO> vlanSearch = _vlanDao.createSearchBuilder();
         vlanSearch.and("vlanType", vlanSearch.entity().getVlanType(), SearchCriteria.Op.EQ);
@@ -1739,6 +1763,16 @@ public class ManagementServerImpl implements ManagementServer {
         _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
 
         sc.setJoinParameters("vlanSearch", "vlanType", vlanType);
+        
+        if (tags != null && !tags.isEmpty()) {
+            int count = 0;
+            sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.PublicIpAddress.toString());
+            for (String key : tags.keySet()) {
+                sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key);
+                sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key));
+                count++;
+            }
+        }
 
         if (zone != null) {
             sc.setParameters("dataCenterId", zone);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/storage/StorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java
index 3fe27ae..8f18b04 100755
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@ -132,6 +132,7 @@ import com.cloud.projects.Project.ListProjectResourcesCriteria;
 import com.cloud.resource.ResourceManager;
 import com.cloud.resource.ResourceState;
 import com.cloud.server.ManagementServer;
+import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.service.ServiceOfferingVO;
 import com.cloud.service.dao.ServiceOfferingDao;
 import com.cloud.storage.Storage.ImageFormat;
@@ -156,6 +157,8 @@ import com.cloud.storage.listener.StoragePoolMonitor;
 import com.cloud.storage.secondary.SecondaryStorageVmManager;
 import com.cloud.storage.snapshot.SnapshotManager;
 import com.cloud.storage.snapshot.SnapshotScheduler;
+import com.cloud.tags.ResourceTagVO;
+import com.cloud.tags.dao.ResourceTagDao;
 import com.cloud.template.TemplateManager;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
@@ -320,6 +323,8 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
     protected CheckPointManager _checkPointMgr;
     @Inject
     protected DownloadMonitor _downloadMonitor;
+    @Inject
+    protected ResourceTagDao _resourceTagDao;
 
     @Inject(adapter = StoragePoolAllocator.class)
     protected Adapters<StoragePoolAllocator> _storagePoolAllocators;
@@ -3725,6 +3730,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
         String name = cmd.getVolumeName();
         String keyword = cmd.getKeyword();
         String type = cmd.getType();
+        Map<String, String> tags = cmd.getTags();
 
         Long zoneId = cmd.getZoneId();
         Long podId = null;
@@ -3764,6 +3770,18 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
         vmSearch.and("type", vmSearch.entity().getType(), SearchCriteria.Op.NIN);
         vmSearch.or("nulltype", vmSearch.entity().getType(), SearchCriteria.Op.NULL);
         sb.join("vmSearch", vmSearch, sb.entity().getInstanceId(), vmSearch.entity().getId(), JoinBuilder.JoinType.LEFTOUTER);
+        
+        if (tags != null && !tags.isEmpty()) {
+        SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
+            for (int count=0; count < tags.size(); count++) {
+                tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
+                tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
+                tagSearch.cp();
+            }
+            tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
+            sb.groupBy(sb.entity().getId());
+            sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
+        }
 
         // now set the SC criteria...
         SearchCriteria<VolumeVO> sc = sb.create();
@@ -3782,6 +3800,16 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
         }
 
         sc.setJoinParameters("diskOfferingSearch", "systemUse", 1);
+        
+        if (tags != null && !tags.isEmpty()) {
+            int count = 0;
+            sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.Volume.toString());
+            for (String key : tags.keySet()) {
+                sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key);
+                sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key));
+                count++;
+            }
+        }
 
         if (id != null) {
             sc.setParameters("id", id);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
index c0e09bf..ae657bf 100644
--- a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java
@@ -24,13 +24,15 @@ import javax.ejb.Local;
 
 import org.apache.log4j.Logger;
 
+import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.Snapshot.Type;
 import com.cloud.storage.SnapshotVO;
-import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
 import com.cloud.storage.Volume;
 import com.cloud.storage.VolumeVO;
+import com.cloud.tags.dao.ResourceTagsDaoImpl;
 import com.cloud.utils.component.ComponentLocator;
+import com.cloud.utils.db.DB;
 import com.cloud.utils.db.Filter;
 import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.GenericSearchBuilder;
@@ -60,6 +62,7 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
     private final SearchBuilder<SnapshotVO> InstanceIdSearch;
     private final SearchBuilder<SnapshotVO> StatusSearch;
     private final GenericSearchBuilder<SnapshotVO, Long> CountSnapshotsByAccount;
+    ResourceTagsDaoImpl _tagsDao = ComponentLocator.inject(ResourceTagsDaoImpl.class);
     
     protected final VMInstanceDaoImpl _instanceDao = ComponentLocator.inject(VMInstanceDaoImpl.class);
     protected final VolumeDaoImpl _volumeDao = ComponentLocator.inject(VolumeDaoImpl.class);
@@ -290,4 +293,18 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
     	sc.setParameters("status", (Object[])status);
     	return listBy(sc, null);
     }
+    
+    @Override
+    @DB
+    public boolean remove(Long id) {
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
+        SnapshotVO entry = findById(id);
+        if (entry != null) {
+            _tagsDao.removeBy(id, TaggedResourceType.Snapshot);
+        }
+        boolean result = super.remove(id);
+        txn.commit();
+        return result;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
index bb5f5ed..e8b6b26 100755
--- a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
@@ -33,6 +33,7 @@ import javax.naming.ConfigurationException;
 import org.apache.log4j.Logger;
 
 import com.cloud.api.BaseCmd;
+import com.cloud.configuration.Resource;
 import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.dc.dao.DataCenterDao;
 import com.cloud.domain.DomainVO;
@@ -42,14 +43,18 @@ import com.cloud.host.HostVO;
 import com.cloud.host.dao.HostDao;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.projects.Project.ListProjectResourcesCriteria;
+import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.storage.Storage;
+import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.Storage.TemplateType;
 import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
 import com.cloud.storage.VMTemplateVO;
 import com.cloud.storage.VMTemplateZoneVO;
+import com.cloud.tags.dao.ResourceTagsDaoImpl;
 import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
 import com.cloud.user.Account;
 import com.cloud.utils.Pair;
+import com.cloud.utils.component.ComponentLocator;
 import com.cloud.utils.component.Inject;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.Filter;
@@ -103,12 +108,15 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
     private SearchBuilder<VMTemplateVO> PublicIsoSearch;
     private GenericSearchBuilder<VMTemplateVO, Long> CountTemplatesByAccount;
 
-    private String routerTmpltName;
-    private String consoleProxyTmpltName;
-    
-    protected VMTemplateDaoImpl() {
-    }
-    
+    ResourceTagsDaoImpl _tagsDao = ComponentLocator.inject(ResourceTagsDaoImpl.class);
+
+
+    private String routerTmpltName;
+    private String consoleProxyTmpltName;
+    
+    protected VMTemplateDaoImpl() {
+    }
+    
     @Override
     public List<VMTemplateVO> listByPublic() {
     	SearchCriteria<VMTemplateVO> sc = PublicSearch.create();
@@ -789,12 +797,25 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
     }
     
     @Override
+    @DB
     public boolean remove(Long id) {
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
         VMTemplateVO template = createForUpdate();
         template.setRemoved(new Date());
+        if (template != null) {
+            if (template.getFormat() == ImageFormat.ISO) {
+                _tagsDao.removeBy(id, TaggedResourceType.ISO);
+            } else {
+                _tagsDao.removeBy(id, TaggedResourceType.Template);
+            }
+        }
 
-        return update(id, template);
+        boolean result = update(id, template);
+        txn.commit();
+        return result;
     }
+    
     private boolean isAdmin(short accountType) {
 	    return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
 	    	    (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) ||

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/dao/VolumeDaoImpl.java b/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
index 95fa568..49e248b 100755
--- a/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
+++ b/server/src/com/cloud/storage/dao/VolumeDaoImpl.java
@@ -28,13 +28,16 @@ import javax.ejb.Local;
 import org.apache.log4j.Logger;
 
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.Volume;
 import com.cloud.storage.Volume.Event;
 import com.cloud.storage.Volume.State;
 import com.cloud.storage.Volume.Type;
 import com.cloud.storage.VolumeVO;
+import com.cloud.tags.dao.ResourceTagsDaoImpl;
 import com.cloud.utils.Pair;
+import com.cloud.utils.component.ComponentLocator;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.GenericDaoBase;
 import com.cloud.utils.db.GenericSearchBuilder;
@@ -56,6 +59,7 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
     protected final SearchBuilder<VolumeVO> InstanceStatesSearch;
     protected final SearchBuilder<VolumeVO> AllFieldsSearch;
     protected GenericSearchBuilder<VolumeVO, Long> CountByAccount;
+    ResourceTagsDaoImpl _tagsDao = ComponentLocator.inject(ResourceTagsDaoImpl.class);
     
     protected static final String SELECT_VM_SQL = "SELECT DISTINCT instance_id from volumes v where v.host_id = ? and v.mirror_state = ?";
     protected static final String SELECT_HYPERTYPE_FROM_VOLUME = "SELECT c.hypervisor_type from volumes v, storage_pool s, cluster c where v.pool_id = s.id and s.cluster_id = c.id and v.id = ?";
@@ -395,4 +399,18 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
         SumCount sumCount = results.get(0);
         return new Pair<Long, Long>(sumCount.count, sumCount.sum);
     }
+    
+    @Override
+    @DB
+    public boolean remove(Long id) {
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
+        VolumeVO entry = findById(id);
+        if (entry != null) {
+            _tagsDao.removeBy(id, TaggedResourceType.Volume);
+        }
+        boolean result = super.remove(id);
+        txn.commit();
+        return result;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index b07f736..50dcf38 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -71,6 +71,7 @@ import com.cloud.org.Grouping;
 import com.cloud.projects.Project.ListProjectResourcesCriteria;
 import com.cloud.projects.ProjectManager;
 import com.cloud.resource.ResourceManager;
+import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.Snapshot.Status;
 import com.cloud.storage.Snapshot.Type;
@@ -93,6 +94,8 @@ import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.storage.secondary.SecondaryStorageVmManager;
 import com.cloud.storage.swift.SwiftManager;
+import com.cloud.tags.ResourceTagVO;
+import com.cloud.tags.dao.ResourceTagDao;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
 import com.cloud.user.AccountVO;
@@ -112,6 +115,7 @@ import com.cloud.utils.component.Inject;
 import com.cloud.utils.component.Manager;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.Filter;
+import com.cloud.utils.db.JoinBuilder;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.Transaction;
@@ -183,6 +187,9 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
     private DomainManager _domainMgr;
     @Inject
     private VolumeDao _volumeDao;
+    @Inject
+    private ResourceTagDao _resourceTagDao;
+    
     String _name;
     private int _totalRetries;
     private int _pauseInterval;
@@ -898,6 +905,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
         String keyword = cmd.getKeyword();
         String snapshotTypeStr = cmd.getSnapshotType();
         String intervalTypeStr = cmd.getIntervalType();
+        Map<String, String> tags = cmd.getTags();
         
         Account caller = UserContext.current().getCaller();
         List<Long> permittedAccounts = new ArrayList<Long>();
@@ -926,6 +934,18 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
         sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
         sb.and("snapshotTypeEQ", sb.entity().getsnapshotType(), SearchCriteria.Op.IN);
         sb.and("snapshotTypeNEQ", sb.entity().getsnapshotType(), SearchCriteria.Op.NEQ);
+        
+        if (tags != null && !tags.isEmpty()) {
+        SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
+        for (int count=0; count < tags.size(); count++) {
+            tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
+            tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
+            tagSearch.cp();
+        }
+        tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
+        sb.groupBy(sb.entity().getId());
+        sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
+    }
 
         SearchCriteria<SnapshotVO> sc = sb.create();
         _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
@@ -933,6 +953,16 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
         if (volumeId != null) {
             sc.setParameters("volumeId", volumeId);
         }
+        
+        if (tags != null && !tags.isEmpty()) {
+            int count = 0;
+            sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.Snapshot.toString());
+            for (String key : tags.keySet()) {
+                sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key);
+                sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key));
+                count++;
+            }
+        }
 
         if (name != null) {
             sc.setParameters("name", "%" + name + "%");

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/tags/TaggedResourceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java
index d84b6b5..075ca48 100644
--- a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java
+++ b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java
@@ -411,4 +411,10 @@ public class TaggedResourceManagerImpl implements TaggedResourceService, Manager
 
         return true;
     }
+
+
+    @Override
+    public List<? extends ResourceTag> listByResourceTypeAndId(TaggedResourceType type, long resourceId) {
+        return _resourceTagDao.listBy(resourceId, type);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/tags/dao/ResourceTagDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/tags/dao/ResourceTagDao.java b/server/src/com/cloud/tags/dao/ResourceTagDao.java
index efe9595..58b2aeb 100644
--- a/server/src/com/cloud/tags/dao/ResourceTagDao.java
+++ b/server/src/com/cloud/tags/dao/ResourceTagDao.java
@@ -16,6 +16,10 @@
 // under the License.
 package com.cloud.tags.dao;
 
+import java.util.List;
+
+import com.cloud.server.ResourceTag;
+import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.tags.ResourceTagVO;
 import com.cloud.utils.db.GenericDao;
 
@@ -24,4 +28,13 @@ import com.cloud.utils.db.GenericDao;
  */
 public interface ResourceTagDao extends GenericDao<ResourceTagVO, Long>{
 
+    /**
+     * @param resourceId
+     * @param resourceType
+     * @return
+     */
+    boolean removeBy(long resourceId, TaggedResourceType resourceType);
+    
+    List<? extends ResourceTag> listBy(long resourceId, TaggedResourceType resourceType);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java b/server/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
index 7f43a04..ae7895b 100644
--- a/server/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
+++ b/server/src/com/cloud/tags/dao/ResourceTagsDaoImpl.java
@@ -16,10 +16,17 @@
 // under the License.
 package com.cloud.tags.dao;
 
+import java.util.List;
+
 import javax.ejb.Local;
 
+import com.cloud.server.ResourceTag;
+import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.tags.ResourceTagVO;
 import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
 
 /**
  * @author Alena Prokharchyk
@@ -27,7 +34,29 @@ import com.cloud.utils.db.GenericDaoBase;
 
 @Local(value = { ResourceTagDao.class })
 public class ResourceTagsDaoImpl extends GenericDaoBase<ResourceTagVO, Long> implements ResourceTagDao{
+    final SearchBuilder<ResourceTagVO> AllFieldsSearch;
+    
+    protected ResourceTagsDaoImpl() {
+        AllFieldsSearch = createSearchBuilder();
+        AllFieldsSearch.and("resourceId", AllFieldsSearch.entity().getResourceId(), Op.EQ);
+        AllFieldsSearch.and("resourceType", AllFieldsSearch.entity().getResourceType(), Op.EQ);
+        AllFieldsSearch.done();
+    }
     
-    protected ResourceTagsDaoImpl() {  
+    @Override
+    public boolean removeBy(long resourceId, ResourceTag.TaggedResourceType resourceType) {
+        SearchCriteria<ResourceTagVO> sc = AllFieldsSearch.create();
+        sc.setParameters("resourceId", resourceId);
+        sc.setParameters("resourceType", resourceType);
+        remove(sc);
+        return true;
+    }
+
+    @Override
+    public List<? extends ResourceTag> listBy(long resourceId, TaggedResourceType resourceType) {
+        SearchCriteria<ResourceTagVO> sc = AllFieldsSearch.create();
+        sc.setParameters("resourceId", resourceId);
+        sc.setParameters("resourceType", resourceType);
+        return listBy(sc);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/vm/UserVmManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java
index e489676..11d2c64 100755
--- a/server/src/com/cloud/vm/UserVmManager.java
+++ b/server/src/com/cloud/vm/UserVmManager.java
@@ -95,9 +95,10 @@ public interface UserVmManager extends VirtualMachineGuru<UserVmVO>, UserVmServi
      * @param permittedAccounts TODO
      * @param listAll TODO
      * @param listProjectResourcesCriteria TODO
+     * @param tags TODO
      * @return List of UserVMs.
      */
-    List<UserVmVO> searchForUserVMs(Criteria c, Account caller, Long domainId, boolean isRecursive, List<Long> permittedAccounts, boolean listAll, ListProjectResourcesCriteria listProjectResourcesCriteria);
+    List<UserVmVO> searchForUserVMs(Criteria c, Account caller, Long domainId, boolean isRecursive, List<Long> permittedAccounts, boolean listAll, ListProjectResourcesCriteria listProjectResourcesCriteria, Map<String, String> tags);
 
     String getChecksum(Long hostId, String templatePath);
     

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 87d88a4..b3fac70 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -149,6 +149,7 @@ import com.cloud.projects.ProjectManager;
 import com.cloud.resource.ResourceManager;
 import com.cloud.resource.ResourceState;
 import com.cloud.server.Criteria;
+import com.cloud.server.ResourceTag.TaggedResourceType;
 import com.cloud.service.ServiceOfferingVO;
 import com.cloud.service.dao.ServiceOfferingDao;
 import com.cloud.storage.DiskOfferingVO;
@@ -182,6 +183,8 @@ import com.cloud.storage.dao.VMTemplateZoneDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.storage.dao.VolumeHostDao;
 import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.tags.ResourceTagVO;
+import com.cloud.tags.dao.ResourceTagDao;
 import com.cloud.template.VirtualMachineTemplate;
 import com.cloud.template.VirtualMachineTemplate.BootloaderType;
 import com.cloud.user.Account;
@@ -342,6 +345,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
     @Inject
     protected ItWorkDao _workDao;
     VolumeHostDao _volumeHostDao;
+    @Inject
+    ResourceTagDao _resourceTagDao;
 
 
     protected ScheduledExecutorService _executor = null;
@@ -2888,6 +2893,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
          String hypervisor = cmd.getHypervisor();
          boolean listAll = cmd.listAll();
          Long id = cmd.getId();
+         Map<String, String> tags = cmd.getTags();
 
          Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null);
         _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, listAll, false);
@@ -2927,11 +2933,12 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
         }
         c.addCriteria(Criteria.ISADMIN, _accountMgr.isAdmin(caller.getType()));
 
-        return searchForUserVMs(c, caller, domainId, isRecursive, permittedAccounts, listAll, listProjectResourcesCriteria);
+        return searchForUserVMs(c, caller, domainId, isRecursive, permittedAccounts, listAll, listProjectResourcesCriteria, tags);
     }
 
     @Override
-    public List<UserVmVO> searchForUserVMs(Criteria c, Account caller, Long domainId, boolean isRecursive, List<Long> permittedAccounts, boolean listAll, ListProjectResourcesCriteria listProjectResourcesCriteria) {
+    public List<UserVmVO> searchForUserVMs(Criteria c, Account caller, Long domainId, boolean isRecursive, 
+            List<Long> permittedAccounts, boolean listAll, ListProjectResourcesCriteria listProjectResourcesCriteria, Map<String, String> tags) {
         Filter searchFilter = new Filter(UserVmVO.class, c.getOrderBy(), c.getAscending(), c.getOffset(), c.getLimit());
 
         SearchBuilder<UserVmVO> sb = _vmDao.createSearchBuilder();
@@ -2974,6 +2981,18 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
             groupSearch.and("groupId", groupSearch.entity().getGroupId(), SearchCriteria.Op.EQ);
             sb.join("groupSearch", groupSearch, sb.entity().getId(), groupSearch.entity().getInstanceId(), JoinBuilder.JoinType.INNER);
         }
+        
+        if (tags != null && !tags.isEmpty()) {
+            SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
+            for (int count=0; count < tags.size(); count++) {
+                tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
+                tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
+                tagSearch.cp();
+            }
+            tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
+            sb.groupBy(sb.entity().getId());
+            sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
+        }
 
         if (networkId != null) {
             SearchBuilder<NicVO> nicSearch = _nicDao.createSearchBuilder();
@@ -2996,6 +3015,16 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
         SearchCriteria<UserVmVO> sc = sb.create();
         _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
         
+        if (tags != null && !tags.isEmpty()) {
+            int count = 0;
+            sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.UserVm.toString());
+            for (String key : tags.keySet()) {
+                sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key);
+                sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key));
+                count++;
+            }
+        }
+        
         if (groupId != null && (Long) groupId == -1) {
             sc.setJoinParameters("vmSearch", "instanceId", (Object) null);
         } else if (groupId != null) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7acf8585/server/src/com/cloud/vm/dao/UserVmDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/dao/UserVmDao.java b/server/src/com/cloud/vm/dao/UserVmDao.java
index aa09e45..9fbcde3 100755
--- a/server/src/com/cloud/vm/dao/UserVmDao.java
+++ b/server/src/com/cloud/vm/dao/UserVmDao.java
@@ -70,4 +70,5 @@ public interface UserVmDao extends GenericDao<UserVmVO, Long> {
     public Long countAllocatedVMsForAccount(long accountId);
 
     Hashtable<Long, UserVmData> listVmDetails(Hashtable<Long, UserVmData> userVmData);
+   
 }