You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ab...@apache.org on 2014/10/22 01:32:46 UTC

[3/7] JCLOUDS-756. Add support for tags to CloudStack.

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/VirtualMachine.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/VirtualMachine.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/VirtualMachine.java
index 0e23a38..920914c 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/VirtualMachine.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/VirtualMachine.java
@@ -111,6 +111,7 @@ public class VirtualMachine {
       protected Set<NIC> nics = ImmutableSet.of();
       protected String hypervisor;
       protected Set<SecurityGroup> securityGroups = ImmutableSet.of();
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see VirtualMachine#getId()
@@ -464,12 +465,24 @@ public class VirtualMachine {
          return securityGroups(ImmutableSet.copyOf(in));
       }
 
+      /**
+       * @see VirtualMachine#getTags()
+       */
+      public T tags(Set<Tag> tags) {
+         this.tags = ImmutableSet.copyOf(checkNotNull(tags, "tags"));
+         return self();
+      }
+
+      public T tags(Tag... in) {
+         return tags(ImmutableSet.copyOf(in));
+      }
+
       public VirtualMachine build() {
          return new VirtualMachine(id, account, cpuCount, cpuSpeed, cpuUsed, displayName, created, domain, domainId,
                usesVirtualNetwork, group, groupId, guestOSId, HAEnabled, hostId, hostname, IPAddress, ISODisplayText, ISOId,
                ISOName, jobId, jobStatus, memory, name, networkKbsRead, networkKbsWrite, password, passwordEnabled, publicIP,
                publicIPId, rootDeviceId, rootDeviceType, serviceOfferingId, serviceOfferingName, state, templateDisplayText,
-               templateId, templateName, zoneId, zoneName, nics, hypervisor, securityGroups);
+               templateId, templateName, zoneId, zoneName, nics, hypervisor, securityGroups, tags);
       }
 
       public T fromVirtualMachine(VirtualMachine in) {
@@ -516,7 +529,8 @@ public class VirtualMachine {
                .zoneName(in.getZoneName())
                .nics(in.getNICs())
                .hypervisor(in.getHypervisor())
-               .securityGroups(in.getSecurityGroups());
+               .securityGroups(in.getSecurityGroups())
+               .tags(in.getTags());
       }
    }
 
@@ -570,9 +584,10 @@ public class VirtualMachine {
    private final Set<NIC> nics;
    private final String hypervisor;
    private final Set<SecurityGroup> securityGroups;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
-         "id", "account", "cpunumber", "cpuspeed", "cpuused", "displayname", "created", "domain", "domainid", "forvirtualnetwork", "group", "groupid", "guestosid", "haenable", "hostid", "hostname", "ipaddress", "isodisplaytext", "isoid", "isoname", "jobid", "jobstatus", "memory", "name", "networkkbsread", "networkkbswrite", "password", "passwordenabled", "publicip", "publicipid", "rootdeviceid", "rootdevicetype", "serviceofferingid", "serviceofferingname", "state", "templatedisplaytext", "templateid", "templatename", "zoneid", "zonename", "nic", "hypervisor", "securitygroup"
+         "id", "account", "cpunumber", "cpuspeed", "cpuused", "displayname", "created", "domain", "domainid", "forvirtualnetwork", "group", "groupid", "guestosid", "haenable", "hostid", "hostname", "ipaddress", "isodisplaytext", "isoid", "isoname", "jobid", "jobstatus", "memory", "name", "networkkbsread", "networkkbswrite", "password", "passwordenabled", "publicip", "publicipid", "rootdeviceid", "rootdevicetype", "serviceofferingid", "serviceofferingname", "state", "templatedisplaytext", "templateid", "templatename", "zoneid", "zonename", "nic", "hypervisor", "securitygroup", "tags"
    })
    protected VirtualMachine(String id, @Nullable String account, long cpuCount, long cpuSpeed, @Nullable String cpuUsed,
                             @Nullable String displayName, @Nullable Date created, @Nullable String domain, @Nullable String domainId,
@@ -584,7 +599,7 @@ public class VirtualMachine {
                             @Nullable String rootDeviceType, @Nullable String serviceOfferingId, @Nullable String serviceOfferingName,
                             @Nullable VirtualMachine.State state, @Nullable String templateDisplayText, @Nullable String templateId,
                             @Nullable String templateName, @Nullable String zoneId, @Nullable String zoneName, @Nullable Set<NIC> nics,
-                            @Nullable String hypervisor, @Nullable Set<SecurityGroup> securityGroups) {
+                            @Nullable String hypervisor, @Nullable Set<SecurityGroup> securityGroups, @Nullable Set<Tag> tags) {
       Preconditions.checkArgument(Strings.isNullOrEmpty(cpuUsed) || cpuUsed.matches("^[0-9\\.|,\\-]+%$"), "cpuUsed value should be a decimal number followed by %");
       this.id = checkNotNull(id, "id");
       this.account = account;
@@ -629,6 +644,7 @@ public class VirtualMachine {
       this.nics = nics == null ? ImmutableSet.<NIC>of() : ImmutableSet.copyOf(nics);
       this.hypervisor = hypervisor;
       this.securityGroups = securityGroups == null ? ImmutableSet.<SecurityGroup>of() : ImmutableSet.copyOf(securityGroups);
+      this.tags = tags != null ? ImmutableSet.copyOf(tags) : ImmutableSet.<Tag> of();
    }
 
    /**
@@ -971,9 +987,16 @@ public class VirtualMachine {
       return this.securityGroups;
    }
 
+   /**
+    * @return the tags for the virtual machine
+    */
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(id, account, cpuCount, cpuSpeed, cpuUsed, displayName, created, domain, domainId, usesVirtualNetwork, group, groupId, guestOSId, HAEnabled, hostId, hostname, IPAddress, ISODisplayText, ISOId, ISOName, jobId, jobStatus, memory, name, networkKbsRead, networkKbsWrite, password, passwordEnabled, publicIP, publicIPId, rootDeviceId, rootDeviceType, serviceOfferingId, serviceOfferingName, state, templateDisplayText, templateId, templateName, zoneId, zoneName, nics, hypervisor, securityGroups);
+      return Objects.hashCode(id, account, cpuCount, cpuSpeed, cpuUsed, displayName, created, domain, domainId, usesVirtualNetwork, group, groupId, guestOSId, HAEnabled, hostId, hostname, IPAddress, ISODisplayText, ISOId, ISOName, jobId, jobStatus, memory, name, networkKbsRead, networkKbsWrite, password, passwordEnabled, publicIP, publicIPId, rootDeviceId, rootDeviceType, serviceOfferingId, serviceOfferingName, state, templateDisplayText, templateId, templateName, zoneId, zoneName, nics, hypervisor, securityGroups, tags);
    }
 
    @Override
@@ -1023,7 +1046,8 @@ public class VirtualMachine {
             && Objects.equal(this.zoneName, that.zoneName)
             && Objects.equal(this.nics, that.nics)
             && Objects.equal(this.hypervisor, that.hypervisor)
-            && Objects.equal(this.securityGroups, that.securityGroups);
+            && Objects.equal(this.securityGroups, that.securityGroups)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
@@ -1038,7 +1062,8 @@ public class VirtualMachine {
             .add("publicIP", publicIP).add("publicIPId", publicIPId).add("rootDeviceId", rootDeviceId).add("rootDeviceType", rootDeviceType)
             .add("serviceOfferingId", serviceOfferingId).add("serviceOfferingName", serviceOfferingName).add("state", state)
             .add("templateDisplayText", templateDisplayText).add("templateId", templateId).add("templateName", templateName)
-            .add("zoneId", zoneId).add("zoneName", zoneName).add("nics", nics).add("hypervisor", hypervisor).add("securityGroups", securityGroups);
+            .add("zoneId", zoneId).add("zoneName", zoneName).add("nics", nics).add("hypervisor", hypervisor).add("securityGroups", securityGroups)
+            .add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Volume.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Volume.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Volume.java
index 563c0cc..30e3a4f 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Volume.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Volume.java
@@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import java.beans.ConstructorProperties;
 import java.util.Date;
 import java.util.Map;
+import java.util.Set;
 
 import org.jclouds.javax.annotation.Nullable;
 
@@ -152,6 +153,7 @@ public class Volume {
       protected VirtualMachine.State vmState;
       protected String zoneId;
       protected String zoneName;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see Volume#getId()
@@ -401,8 +403,20 @@ public class Volume {
          return self();
       }
 
+      /**
+       * @see Volume#getTags()
+       */
+      public T tags(Set<Tag> tags) {
+         this.tags = ImmutableSet.copyOf(checkNotNull(tags, "tags"));
+         return self();
+      }
+
+      public T tags(Tag... in) {
+         return tags(ImmutableSet.copyOf(in));
+      }
+
       public Volume build() {
-         return new Volume(id, account, attached, created, destroyed, deviceId, diskOfferingDisplayText, diskOfferingId, diskOfferingName, domain, domainId, hypervisor, isExtractable, jobId, jobStatus, name, serviceOfferingDisplayText, serviceOfferingId, serviceOfferingName, size, snapshotId, state, storage, storageType, type, virtualMachineId, vmDisplayName, vmName, vmState, zoneId, zoneName);
+         return new Volume(id, account, attached, created, destroyed, deviceId, diskOfferingDisplayText, diskOfferingId, diskOfferingName, domain, domainId, hypervisor, isExtractable, jobId, jobStatus, name, serviceOfferingDisplayText, serviceOfferingId, serviceOfferingName, size, snapshotId, state, storage, storageType, type, virtualMachineId, vmDisplayName, vmName, vmState, zoneId, zoneName, tags);
       }
 
       public T fromVolume(Volume in) {
@@ -437,7 +451,8 @@ public class Volume {
                .vmName(in.getVmName())
                .vmState(in.getVmState())
                .zoneId(in.getZoneId())
-               .zoneName(in.getZoneName());
+               .zoneName(in.getZoneName())
+               .tags(in.getTags());
       }
    }
 
@@ -479,9 +494,10 @@ public class Volume {
    private final VirtualMachine.State vmState;
    private final String zoneId;
    private final String zoneName;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
-         "id", "account", "attached", "created", "destroyed", "deviceid", "diskofferingdisplaytext", "diskofferingid", "diskofferingname", "domain", "domainid", "hypervisor", "isextractable", "jobid", "jobstatus", "name", "serviceofferingdisplaytext", "serviceofferingid", "serviceofferingname", "size", "snapshotid", "state", "storage", "storagetype", "type", "virtualmachineid", "vmdisplayname", "vmname", "vmstate", "zoneid", "zonename"
+         "id", "account", "attached", "created", "destroyed", "deviceid", "diskofferingdisplaytext", "diskofferingid", "diskofferingname", "domain", "domainid", "hypervisor", "isextractable", "jobid", "jobstatus", "name", "serviceofferingdisplaytext", "serviceofferingid", "serviceofferingname", "size", "snapshotid", "state", "storage", "storagetype", "type", "virtualmachineid", "vmdisplayname", "vmname", "vmstate", "zoneid", "zonename", "tags"
    })
    protected Volume(String id, @Nullable String account, @Nullable Date attached, @Nullable Date created, boolean destroyed,
                     @Nullable String deviceId, @Nullable String diskOfferingDisplayText, @Nullable String diskOfferingId,
@@ -491,7 +507,7 @@ public class Volume {
                     long size, @Nullable String snapshotId, @Nullable Volume.State state, @Nullable String storage,
                     @Nullable String storageType, @Nullable Volume.Type type, @Nullable String virtualMachineId,
                     @Nullable String vmDisplayName, @Nullable String vmName, @Nullable VirtualMachine.State vmState,
-                    @Nullable String zoneId, @Nullable String zoneName) {
+                    @Nullable String zoneId, @Nullable String zoneName, @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.account = account;
       this.attached = attached;
@@ -523,6 +539,7 @@ public class Volume {
       this.vmState = vmState;
       this.zoneId = zoneId;
       this.zoneName = zoneName;
+      this.tags = tags != null ? ImmutableSet.copyOf(tags) : ImmutableSet.<Tag> of();
    }
 
    public String getId() {
@@ -676,9 +693,16 @@ public class Volume {
       return this.zoneName;
    }
 
+   /**
+    * @return the tags for the volume
+    */
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(id, account, attached, created, destroyed, deviceId, diskOfferingDisplayText, diskOfferingId, diskOfferingName, domain, domainId, hypervisor, isExtractable, jobId, jobStatus, name, serviceOfferingDisplayText, serviceOfferingId, serviceOfferingName, size, snapshotId, state, storage, storageType, type, virtualMachineId, vmDisplayName, vmName, vmState, zoneId, zoneName);
+      return Objects.hashCode(id, account, attached, created, destroyed, deviceId, diskOfferingDisplayText, diskOfferingId, diskOfferingName, domain, domainId, hypervisor, isExtractable, jobId, jobStatus, name, serviceOfferingDisplayText, serviceOfferingId, serviceOfferingName, size, snapshotId, state, storage, storageType, type, virtualMachineId, vmDisplayName, vmName, vmState, zoneId, zoneName, tags);
    }
 
    @Override
@@ -716,7 +740,8 @@ public class Volume {
             && Objects.equal(this.vmName, that.vmName)
             && Objects.equal(this.vmState, that.vmState)
             && Objects.equal(this.zoneId, that.zoneId)
-            && Objects.equal(this.zoneName, that.zoneName);
+            && Objects.equal(this.zoneName, that.zoneName)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
@@ -728,7 +753,8 @@ public class Volume {
             .add("serviceOfferingDisplayText", serviceOfferingDisplayText).add("serviceOfferingId", serviceOfferingId)
             .add("serviceOfferingName", serviceOfferingName).add("size", size).add("snapshotId", snapshotId).add("state", state)
             .add("storage", storage).add("storageType", storageType).add("type", type).add("virtualMachineId", virtualMachineId)
-            .add("vmDisplayName", vmDisplayName).add("vmName", vmName).add("vmState", vmState).add("zoneId", zoneId).add("zoneName", zoneName);
+            .add("vmDisplayName", vmDisplayName).add("vmName", vmName).add("vmState", vmState).add("zoneId", zoneId).add("zoneName", zoneName)
+            .add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Zone.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Zone.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Zone.java
index 81cec1e..1548507 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Zone.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Zone.java
@@ -20,7 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.beans.ConstructorProperties;
 import java.util.List;
+import java.util.Set;
 
+import com.google.common.collect.ImmutableSet;
 import org.jclouds.javax.annotation.Nullable;
 
 import com.google.common.base.MoreObjects;
@@ -58,6 +60,7 @@ public class Zone implements Comparable<Zone> {
       protected AllocationState allocationState;
       protected String dhcpProvider;
       protected String zoneToken;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see Zone#getId()
@@ -181,9 +184,21 @@ public class Zone implements Comparable<Zone> {
          return self();
       }
 
+      /**
+       * @see Zone#getTags()
+       */
+      public T tags(Set<Tag> tags) {
+         this.tags = ImmutableSet.copyOf(checkNotNull(tags, "tags"));
+         return self();
+      }
+
+      public T tags(Tag... in) {
+         return tags(ImmutableSet.copyOf(in));
+      }
+
       public Zone build() {
          return new Zone(id, description, displayText, DNS1, DNS2, domain, domainId, guestCIDRAddress, internalDNS1, internalDNS2,
-               name, networkType, VLAN, securityGroupsEnabled, allocationState, dhcpProvider, zoneToken);
+               name, networkType, VLAN, securityGroupsEnabled, allocationState, dhcpProvider, zoneToken, tags);
       }
 
       public T fromZone(Zone in) {
@@ -202,7 +217,8 @@ public class Zone implements Comparable<Zone> {
                .securityGroupsEnabled(in.isSecurityGroupsEnabled())
                .allocationState(in.getAllocationState())
                .dhcpProvider(in.getDhcpProvider())
-               .zoneToken(in.getZoneToken());
+               .zoneToken(in.getZoneToken())
+               .tags(in.getTags());
       }
    }
 
@@ -230,15 +246,16 @@ public class Zone implements Comparable<Zone> {
    private final AllocationState allocationState;
    private final String dhcpProvider;
    private final String zoneToken;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
-         "id", "description", "displaytext", "dns1", "dns2", "domain", "domainid", "guestcidraddress", "internaldns1", "internaldns2", "name", "networktype", "vlan", "securitygroupsenabled", "allocationstate", "dhcpprovider", "zonetoken"
+         "id", "description", "displaytext", "dns1", "dns2", "domain", "domainid", "guestcidraddress", "internaldns1", "internaldns2", "name", "networktype", "vlan", "securitygroupsenabled", "allocationstate", "dhcpprovider", "zonetoken", "tags"
    })
    protected Zone(String id, @Nullable String description, @Nullable String displayText, @Nullable String DNS1, @Nullable String DNS2,
                   @Nullable String domain, @Nullable String domainId, @Nullable String guestCIDRAddress, @Nullable String internalDNS1,
                   @Nullable String internalDNS2, @Nullable String name, @Nullable NetworkType networkType, @Nullable String VLAN,
                   boolean securityGroupsEnabled, @Nullable AllocationState allocationState, @Nullable String dhcpProvider,
-                  @Nullable String zoneToken) {
+                  @Nullable String zoneToken, @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.description = description;
       this.displayText = displayText;
@@ -256,6 +273,7 @@ public class Zone implements Comparable<Zone> {
       this.allocationState = allocationState;
       this.dhcpProvider = dhcpProvider;
       this.zoneToken = zoneToken;
+      this.tags = tags != null ? ImmutableSet.copyOf(tags) : ImmutableSet.<Tag> of();
    }
 
    /**
@@ -384,10 +402,17 @@ public class Zone implements Comparable<Zone> {
       return this.zoneToken;
    }
 
+   /**
+    * @return the tags for the zone
+    */
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
       return Objects.hashCode(id, description, displayText, DNS1, DNS2, domain, domainId, guestCIDRAddress, internalDNS1,
-            internalDNS2, name, networkType, VLAN, securityGroupsEnabled, allocationState, dhcpProvider, zoneToken);
+            internalDNS2, name, networkType, VLAN, securityGroupsEnabled, allocationState, dhcpProvider, zoneToken, tags);
    }
 
    @Override
@@ -411,7 +436,8 @@ public class Zone implements Comparable<Zone> {
             && Objects.equal(this.securityGroupsEnabled, that.securityGroupsEnabled)
             && Objects.equal(this.allocationState, that.allocationState)
             && Objects.equal(this.dhcpProvider, that.dhcpProvider)
-            && Objects.equal(this.zoneToken, that.zoneToken);
+            && Objects.equal(this.zoneToken, that.zoneToken)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
@@ -420,7 +446,7 @@ public class Zone implements Comparable<Zone> {
             .add("domain", domain).add("domainId", domainId).add("guestCIDRAddress", guestCIDRAddress).add("internalDNS1", internalDNS1)
             .add("internalDNS2", internalDNS2).add("name", name).add("networkType", networkType).add("VLAN", VLAN)
             .add("securityGroupsEnabled", securityGroupsEnabled).add("allocationState", allocationState).add("dhcpProvider", dhcpProvider)
-            .add("zoneToken", zoneToken);
+            .add("zoneToken", zoneToken).add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TagApi.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TagApi.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TagApi.java
new file mode 100644
index 0000000..96e9f36
--- /dev/null
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TagApi.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.cloudstack.features;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.core.MediaType;
+import java.util.Set;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.Tag;
+import org.jclouds.cloudstack.filters.AuthenticationFilter;
+import org.jclouds.cloudstack.options.CreateTagsOptions;
+import org.jclouds.cloudstack.options.DeleteTagsOptions;
+import org.jclouds.cloudstack.options.ListTagsOptions;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Unwrap;
+
+/**
+ * Provides synchronous access to cloudstack via their REST API.
+ * <p/>
+ * 
+ * @see <a href="http://cloudstack.apache.org/docs/api/apidocs-4.3/TOC_Root_Admin.html" />
+ */
+@RequestFilters(AuthenticationFilter.class)
+@QueryParams(keys = "response", values = "json")
+public interface TagApi {
+
+   /**
+    * Lists tags
+    * 
+    * @param options
+    *           if present, how to constrain the list.
+    * @return tags matching query, or empty set, if no tags are found
+    */
+   @Named("listTags")
+   @GET
+   @QueryParams(keys = { "command", "listAll" }, values = { "listTags", "true" })
+   @SelectJson("tag")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<Tag> listTags(ListTagsOptions... options);
+
+   /**
+    * Creates one or more tags on the specified resources.
+    *
+    * @param options arguments
+    * @return an asynchronous job structure
+    */
+   @Named("createTags")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @QueryParams(keys = "command", values = "createTags")
+   @Unwrap
+   AsyncCreateResponse createTags(CreateTagsOptions options);
+
+   /**
+    * Deletes one or more tags from the specified resources.
+    *
+    * @param options arguments
+    * @return an asynchronous job structure
+    */
+   @Named("deleteTags")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @QueryParams(keys = "command", values = "deleteTags")
+   @Unwrap
+   AsyncCreateResponse deleteTags(DeleteTagsOptions options);
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateTagsOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateTagsOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateTagsOptions.java
new file mode 100644
index 0000000..4263dbe
--- /dev/null
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateTagsOptions.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.cloudstack.options;
+
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.cloudstack.domain.Tag;
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+/**
+ * Options used to control how tags are created.
+ *
+ * @see <a
+ *      href="http://cloudstack.apache.org/docs/api/apidocs-4.3/root_admin/createTags.html"
+ *      />
+ */
+public class CreateTagsOptions extends BaseHttpRequestOptions {
+
+   public static final CreateTagsOptions NONE = new CreateTagsOptions();
+
+   /**
+    * Customer - optional
+    */
+   public CreateTagsOptions customer(String customer) {
+      this.queryParameters.replaceValues("customer", ImmutableSet.of(customer));
+      return this;
+   }
+
+   /**
+    * Resource ID(s) to tag
+    */
+   public CreateTagsOptions resourceIds(Set<String> resourceIds) {
+      this.queryParameters.replaceValues("resourceids", ImmutableSet.of(Joiner.on(",").join(resourceIds)));
+      return this;
+   }
+
+   /**
+    * Resource ID(s) to tag
+    */
+   public CreateTagsOptions resourceIds(String... resourceIds) {
+      this.queryParameters.replaceValues("resourceids", ImmutableSet.of(Joiner.on(",").join(resourceIds)));
+      return this;
+   }
+
+   /**
+    * Resource type
+    */
+   public CreateTagsOptions resourceType(String resourceType) {
+      this.queryParameters.replaceValues("resourcetype", ImmutableSet.of(resourceType));
+      return this;
+   }
+
+   /**
+    * Resource type
+    */
+   public CreateTagsOptions resourceType(Tag.ResourceType resourceType) {
+      this.queryParameters.replaceValues("resourcetype", ImmutableSet.of(resourceType.toString()));
+      return this;
+   }
+
+   /**
+    * Tags to create
+    */
+   public CreateTagsOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
+   public static class Builder {
+
+      public static CreateTagsOptions customer(String customer) {
+         CreateTagsOptions options = new CreateTagsOptions();
+         return options.customer(customer);
+      }
+
+      public static CreateTagsOptions resourceIds(Set<String> resourceIds) {
+         CreateTagsOptions options = new CreateTagsOptions();
+         return options.resourceIds(resourceIds);
+      }
+
+      public static CreateTagsOptions resourceIds(String... resourceIds) {
+         CreateTagsOptions options = new CreateTagsOptions();
+         return options.resourceIds(resourceIds);
+      }
+
+      public static CreateTagsOptions resourceType(String resourceType) {
+         CreateTagsOptions options = new CreateTagsOptions();
+         return options.resourceType(resourceType);
+      }
+
+      public static CreateTagsOptions resourceType(Tag.ResourceType resourceType) {
+         CreateTagsOptions options = new CreateTagsOptions();
+         return options.resourceType(resourceType);
+      }
+
+      public static CreateTagsOptions tags(Map<String, String> tags) {
+         CreateTagsOptions options = new CreateTagsOptions();
+         return options.tags(tags);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeleteTagsOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeleteTagsOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeleteTagsOptions.java
new file mode 100644
index 0000000..83c7c3f
--- /dev/null
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeleteTagsOptions.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.cloudstack.options;
+
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.cloudstack.domain.Tag;
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+/**
+ * Options used to control how tags are created.
+ *
+ * @see <a
+ *      href="http://cloudstack.apache.org/docs/api/apidocs-4.3/root_admin/createTags.html"
+ *      />
+ */
+public class DeleteTagsOptions extends BaseHttpRequestOptions {
+
+   public static final DeleteTagsOptions NONE = new DeleteTagsOptions();
+
+   /**
+    * Resource ID(s) to un-tag
+    */
+   public DeleteTagsOptions resourceIds(Set<String> resourceIds) {
+      this.queryParameters.replaceValues("resourceids", ImmutableSet.of(Joiner.on(",").join(resourceIds)));
+      return this;
+   }
+
+   /**
+    * Resource ID(s) to un-tag
+    */
+   public DeleteTagsOptions resourceIds(String... resourceIds) {
+      this.queryParameters.replaceValues("resourceids", ImmutableSet.of(Joiner.on(",").join(resourceIds)));
+      return this;
+   }
+
+   /**
+    * Resource type
+    */
+   public DeleteTagsOptions resourceType(String resourceType) {
+      this.queryParameters.replaceValues("resourcetype", ImmutableSet.of(resourceType));
+      return this;
+   }
+
+   /**
+    * Resource type
+    */
+   public DeleteTagsOptions resourceType(Tag.ResourceType resourceType) {
+      this.queryParameters.replaceValues("resourcetype", ImmutableSet.of(resourceType.toString()));
+      return this;
+   }
+
+   /**
+    * Tags to delete
+    */
+   public DeleteTagsOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
+   public static class Builder {
+
+      public static DeleteTagsOptions resourceIds(Set<String> resourceIds) {
+         DeleteTagsOptions options = new DeleteTagsOptions();
+         return options.resourceIds(resourceIds);
+      }
+
+      public static DeleteTagsOptions resourceIds(String... resourceIds) {
+         DeleteTagsOptions options = new DeleteTagsOptions();
+         return options.resourceIds(resourceIds);
+      }
+
+      public static DeleteTagsOptions resourceType(String resourceType) {
+         DeleteTagsOptions options = new DeleteTagsOptions();
+         return options.resourceType(resourceType);
+      }
+
+      public static DeleteTagsOptions resourceType(Tag.ResourceType resourceType) {
+         DeleteTagsOptions options = new DeleteTagsOptions();
+         return options.resourceType(resourceType);
+      }
+
+      public static DeleteTagsOptions tags(Map<String, String> tags) {
+         DeleteTagsOptions options = new DeleteTagsOptions();
+         return options.tags(tags);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListEgressFirewallRulesOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListEgressFirewallRulesOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListEgressFirewallRulesOptions.java
index 2f2ce02..5d8537c 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListEgressFirewallRulesOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListEgressFirewallRulesOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -84,6 +86,22 @@ public class ListEgressFirewallRulesOptions extends AccountInDomainOptions {
       return this;
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListEgressFirewallRulesOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
+
    public static class Builder {
 
       /**
@@ -158,6 +176,13 @@ public class ListEgressFirewallRulesOptions extends AccountInDomainOptions {
          return options.domainId(id);
       }
 
+      /**
+       * @see ListEgressFirewallRulesOptions#tags
+       */
+      public static ListEgressFirewallRulesOptions tags(Map<String, String> tags) {
+         ListEgressFirewallRulesOptions options = new ListEgressFirewallRulesOptions();
+         return options.tags(tags);
+      }
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListFirewallRulesOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListFirewallRulesOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListFirewallRulesOptions.java
index 7f83213..8a8925d 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListFirewallRulesOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListFirewallRulesOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -75,6 +77,22 @@ public class ListFirewallRulesOptions extends AccountInDomainOptions {
       return this;
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListFirewallRulesOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
+
    public static class Builder {
 
       /**
@@ -141,6 +159,13 @@ public class ListFirewallRulesOptions extends AccountInDomainOptions {
          return options.domainId(id);
       }
 
+      /**
+       * @see ListFirewallRulesOptions#tags
+       */
+      public static ListFirewallRulesOptions tags(Map<String, String> tags) {
+         ListFirewallRulesOptions options = new ListFirewallRulesOptions();
+         return options.tags(tags);
+      }
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListIPForwardingRulesOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListIPForwardingRulesOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListIPForwardingRulesOptions.java
index a55936e..a6a3dcf 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListIPForwardingRulesOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListIPForwardingRulesOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -68,6 +70,22 @@ public class ListIPForwardingRulesOptions extends AccountInDomainOptions {
 
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListIPForwardingRulesOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
+
    public static class Builder {
 
       /**
@@ -117,6 +135,14 @@ public class ListIPForwardingRulesOptions extends AccountInDomainOptions {
          ListIPForwardingRulesOptions options = new ListIPForwardingRulesOptions();
          return options.projectId(projectId);
       }
+
+      /**
+       * @see ListIPForwardingRulesOptions#tags
+       */
+      public static ListIPForwardingRulesOptions tags(Map<String, String> tags) {
+         ListIPForwardingRulesOptions options = new ListIPForwardingRulesOptions();
+         return options.tags(tags);
+      }
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListISOsOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListISOsOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListISOsOptions.java
index 0659d51..d0f9b26 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListISOsOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListISOsOptions.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
 import java.util.Set;
 
 import org.jclouds.cloudstack.domain.ISO;
@@ -138,6 +139,21 @@ public class ListISOsOptions extends AccountInDomainOptions {
       return this;
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListISOsOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
    public static class Builder {
       /**
        * @param account the account of the ISO file. Must be used with the domainId parameter.
@@ -243,5 +259,12 @@ public class ListISOsOptions extends AccountInDomainOptions {
       public static ListISOsOptions zoneId(String zoneId) {
          return new ListISOsOptions().zoneId(zoneId);
       }
+
+      /**
+       * @param tags
+       */
+      public static ListISOsOptions tags(Map<String, String> tags) {
+         return new ListISOsOptions().tags(tags);
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListNetworksOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListNetworksOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListNetworksOptions.java
index 94e9de7..2691107 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListNetworksOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListNetworksOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import org.jclouds.cloudstack.domain.NetworkType;
 import org.jclouds.cloudstack.domain.TrafficType;
 
@@ -33,8 +35,7 @@ public class ListNetworksOptions extends AccountInDomainOptions {
    public static final ListNetworksOptions NONE = new ListNetworksOptions();
 
    /**
-    * @param isDefault
-    *           true if network is default, false otherwise
+    * @param isDefault true if network is default, false otherwise
     */
    public ListNetworksOptions isDefault(boolean isDefault) {
       this.queryParameters.replaceValues("isdefault", ImmutableSet.of(isDefault + ""));
@@ -42,8 +43,7 @@ public class ListNetworksOptions extends AccountInDomainOptions {
    }
 
    /**
-    * @param isShared
-    *           true if network is shared, false otherwise
+    * @param isShared true if network is shared, false otherwise
     */
    public ListNetworksOptions isShared(boolean isShared) {
       this.queryParameters.replaceValues("isshared", ImmutableSet.of(isShared + ""));
@@ -51,8 +51,7 @@ public class ListNetworksOptions extends AccountInDomainOptions {
    }
 
    /**
-    * @param isSystem
-    *           true if network is system, false otherwise
+    * @param isSystem true if network is system, false otherwise
     */
    public ListNetworksOptions isSystem(boolean isSystem) {
       this.queryParameters.replaceValues("issystem", ImmutableSet.of(isSystem + ""));
@@ -60,8 +59,7 @@ public class ListNetworksOptions extends AccountInDomainOptions {
    }
 
    /**
-    * @param type
-    *           the type of the network
+    * @param type the type of the network
     */
    public ListNetworksOptions type(NetworkType type) {
       this.queryParameters.replaceValues("type", ImmutableSet.of(type.toString()));
@@ -69,8 +67,7 @@ public class ListNetworksOptions extends AccountInDomainOptions {
    }
 
    /**
-    * @param id
-    *           list networks by id
+    * @param id list networks by id
     */
    public ListNetworksOptions id(String id) {
       this.queryParameters.replaceValues("id", ImmutableSet.of(id + ""));
@@ -78,8 +75,7 @@ public class ListNetworksOptions extends AccountInDomainOptions {
    }
 
    /**
-    * @param zoneId
-    *           the Zone ID of the network
+    * @param zoneId the Zone ID of the network
     */
    public ListNetworksOptions zoneId(String zoneId) {
       this.queryParameters.replaceValues("zoneid", ImmutableSet.of(zoneId + ""));
@@ -88,8 +84,7 @@ public class ListNetworksOptions extends AccountInDomainOptions {
    }
 
    /**
-    * @param projectId
-    *           the project ID of the network
+    * @param projectId the project ID of the network
     */
    public ListNetworksOptions projectId(String projectId) {
       this.queryParameters.replaceValues("projectid", ImmutableSet.of(projectId + ""));
@@ -98,8 +93,7 @@ public class ListNetworksOptions extends AccountInDomainOptions {
    }
 
    /**
-    * @param trafficType
-    *           type of the traffic
+    * @param trafficType type of the traffic
     */
    public ListNetworksOptions trafficType(TrafficType trafficType) {
       this.queryParameters.replaceValues("traffictype", ImmutableSet.of(trafficType.toString()));
@@ -122,6 +116,21 @@ public class ListNetworksOptions extends AccountInDomainOptions {
       return ListNetworksOptions.class.cast(super.domainId(domainId));
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListNetworksOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
    public static class Builder {
       /**
        * @see ListNetworksOptions#isDefault
@@ -202,6 +211,15 @@ public class ListNetworksOptions extends AccountInDomainOptions {
          ListNetworksOptions options = new ListNetworksOptions();
          return options.domainId(domainId);
       }
-   }
 
+      /**
+       * @see ListNetworksOptions#tags
+       */
+      public static ListNetworksOptions tags(Map<String, String> tags) {
+         ListNetworksOptions options = new ListNetworksOptions();
+         return options.tags(tags);
+      }
+   }
 }
+
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListPortForwardingRulesOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListPortForwardingRulesOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListPortForwardingRulesOptions.java
index b551f05..3ccbd69 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListPortForwardingRulesOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListPortForwardingRulesOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -57,6 +59,22 @@ public class ListPortForwardingRulesOptions extends AccountInDomainOptions {
       return this;
 
    }
+
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListPortForwardingRulesOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
    public static class Builder {
 
       /**
@@ -98,8 +116,17 @@ public class ListPortForwardingRulesOptions extends AccountInDomainOptions {
          ListPortForwardingRulesOptions options = new ListPortForwardingRulesOptions();
          return options.domainId(id);
       }
+
+      /**
+       * @see ListPortForwardingRulesOptions#tags
+       */
+      public static ListPortForwardingRulesOptions tags(Map<String, String> tags) {
+         ListPortForwardingRulesOptions options = new ListPortForwardingRulesOptions();
+         return options.tags(tags);
+      }
    }
 
+
    /**
     * {@inheritDoc}
     */

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListProjectsOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListProjectsOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListProjectsOptions.java
index 7b0b2ff..0eeaf80 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListProjectsOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListProjectsOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -85,6 +87,21 @@ public class ListProjectsOptions extends AccountInDomainOptions {
       return this;
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListProjectsOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
    public static class Builder {
 
       /**
@@ -150,6 +167,14 @@ public class ListProjectsOptions extends AccountInDomainOptions {
          ListProjectsOptions options = new ListProjectsOptions();
          return options.recursive(recursive);
       }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListProjectsOptions#tags
+       */
+      public static ListProjectsOptions tags(Map<String, String> tags) {
+         ListProjectsOptions options = new ListProjectsOptions();
+         return options.tags(tags);
+      }
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListPublicIPAddressesOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListPublicIPAddressesOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListPublicIPAddressesOptions.java
index 0cb38e9..2609d87 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListPublicIPAddressesOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListPublicIPAddressesOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -106,6 +108,21 @@ public class ListPublicIPAddressesOptions extends AccountInDomainOptions {
       return this;
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListPublicIPAddressesOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
    public static class Builder {
 
       /**
@@ -187,6 +204,14 @@ public class ListPublicIPAddressesOptions extends AccountInDomainOptions {
          ListPublicIPAddressesOptions options = new ListPublicIPAddressesOptions();
          return options.usesVirtualNetwork(usesVirtualNetwork);
       }
+
+      /**
+       * @see ListPublicIPAddressesOptions#tags
+       */
+      public static ListPublicIPAddressesOptions tags(Map<String, String> tags) {
+         ListPublicIPAddressesOptions options = new ListPublicIPAddressesOptions();
+         return options.tags(tags);
+      }
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSecurityGroupsOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSecurityGroupsOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSecurityGroupsOptions.java
index d9e22c3..32d6113 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSecurityGroupsOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSecurityGroupsOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -68,6 +70,21 @@ public class ListSecurityGroupsOptions extends AssociateIPAddressOptions {
       return this;
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListSecurityGroupsOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
    public static class Builder {
 
       /**
@@ -103,7 +120,7 @@ public class ListSecurityGroupsOptions extends AssociateIPAddressOptions {
       }
 
       /**
-       * @see DeployVirtualMachineOptions#accountInDomain
+       * @see ListSecurityGroupsOptions#accountInDomain
        */
       public static ListSecurityGroupsOptions accountInDomain(String account, String domain) {
          ListSecurityGroupsOptions options = new ListSecurityGroupsOptions();
@@ -111,12 +128,20 @@ public class ListSecurityGroupsOptions extends AssociateIPAddressOptions {
       }
 
       /**
-       * @see DeployVirtualMachineOptions#domainId
+       * @see ListSecurityGroupsOptions#domainId
        */
       public static ListSecurityGroupsOptions domainId(String domainId) {
          ListSecurityGroupsOptions options = new ListSecurityGroupsOptions();
          return options.domainId(domainId);
       }
+
+      /**
+       * @see ListSecurityGroupsOptions#tags
+       */
+      public static ListSecurityGroupsOptions tags(Map<String, String> tags) {
+         ListSecurityGroupsOptions options = new ListSecurityGroupsOptions();
+         return options.tags(tags);
+      }
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java
index fa366d0..35a076a 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import org.jclouds.cloudstack.domain.Snapshot;
 
 import com.google.common.collect.ImmutableSet;
@@ -94,6 +96,21 @@ public class ListSnapshotsOptions extends AccountInDomainOptions {
       return this;
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListSnapshotsOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
    public static class Builder {
 
       /**
@@ -166,6 +183,13 @@ public class ListSnapshotsOptions extends AccountInDomainOptions {
       public static ListSnapshotsOptions projectId(String projectId) {
          return new ListSnapshotsOptions().projectId(projectId);
       }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListSnapshotsOptions#tags(java.util.Map)
+       */
+      public static ListSnapshotsOptions tags(Map<String, String> tags) {
+         return new ListSnapshotsOptions().tags(tags);
+      }
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListTagsOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListTagsOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListTagsOptions.java
new file mode 100644
index 0000000..19e01bd
--- /dev/null
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListTagsOptions.java
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.cloudstack.options;
+
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.cloudstack.domain.Tag;
+
+/**
+ * Options used to control what tags are returned
+ * 
+ * @see <a href=
+ *      "http://cloudstack.apache.org/docs/api/apidocs-4.3/root_admin/listTags.html"
+ *      />
+ */
+public class ListTagsOptions extends AccountInDomainOptions {
+
+   public static final ListTagsOptions NONE = new ListTagsOptions();
+
+   /**
+    * @param customer
+    *    list by customer
+    */
+   public ListTagsOptions customer(String customer) {
+      this.queryParameters.replaceValues("customer", ImmutableSet.of(customer));
+      return this;
+   }
+
+   /**
+    * @param isRecursive
+    *           Should we recurse on this search?
+    */
+   public ListTagsOptions isRecursive(boolean isRecursive) {
+      this.queryParameters.replaceValues("isrecursive", ImmutableSet.of(isRecursive + ""));
+      return this;
+   }
+
+   /**
+    * @param key
+    *    list by key
+    */
+   public ListTagsOptions key(String key) {
+      this.queryParameters.replaceValues("key", ImmutableSet.of(key));
+      return this;
+   }
+
+   /**
+    * @param keyword
+    *    list by keyword
+    */
+   public ListTagsOptions keyword(String keyword) {
+      this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword));
+      return this;
+   }
+
+   /**
+    * @param projectId
+    *    list by project
+    */
+   public ListTagsOptions projectId(String projectId) {
+      this.queryParameters.replaceValues("projectid", ImmutableSet.of(projectId));
+      return this;
+   }
+
+   /**
+    * @param resourceId
+    *    list by resource ID
+    */
+   public ListTagsOptions resourceId(String resourceId) {
+      this.queryParameters.replaceValues("resourceid", ImmutableSet.of(resourceId));
+      return this;
+   }
+
+   /**
+    * @param resourceType
+    *    list by resource type
+    */
+   public ListTagsOptions resourceType(String resourceType) {
+      this.queryParameters.replaceValues("resourcetype", ImmutableSet.of(resourceType));
+      return this;
+   }
+
+   /**
+    * @param resourceType
+    *    list by resource type
+    */
+   public ListTagsOptions resourceType(Tag.ResourceType resourceType) {
+      this.queryParameters.replaceValues("resourcetype", ImmutableSet.of(resourceType.toString()));
+      return this;
+   }
+
+   /**
+    * @param value
+    *    list by value
+    */
+   public ListTagsOptions value(String value) {
+      this.queryParameters.replaceValues("value", ImmutableSet.of(value));
+      return this;
+   }
+
+   public ListTagsOptions page(long page) {
+      this.queryParameters.replaceValues("page", ImmutableSet.of(page + ""));
+      return this;
+   }
+
+   public ListTagsOptions pageSize(long pageSize) {
+      this.queryParameters.replaceValues("pagesize", ImmutableSet.of(pageSize + ""));
+      return this;
+   }
+
+   public static class Builder {
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#accountInDomain(String, String)
+       */
+      public static ListTagsOptions accountInDomain(String account, String domain) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.accountInDomain(account, domain);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#accountInDomain(String, String)
+       */
+      public static ListTagsOptions domainId(String domainId) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.domainId(domainId);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#customer(String)
+       */
+      public static ListTagsOptions customer(String customer) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.customer(customer);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#isRecursive(boolean)
+       */
+      public static ListTagsOptions isRecursive(boolean isRecursive) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.isRecursive(isRecursive);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#key(String)
+       */
+      public static ListTagsOptions key(String key) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.key(key);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#keyword
+       */
+      public static ListTagsOptions keyword(String keyword) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.keyword(keyword);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#projectId(String)
+       */
+      public static ListTagsOptions projectId(String projectId) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.projectId(projectId);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#resourceId(String)
+       */
+      public static ListTagsOptions resourceId(String resourceId) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.resourceId(resourceId);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#resourceType(String)
+       */
+      public static ListTagsOptions resourceType(String resourceType) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.resourceType(resourceType);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#resourceType(org.jclouds.cloudstack.domain.Tag.ResourceType)
+       */
+      public static ListTagsOptions resourceType(Tag.ResourceType resourceType) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.resourceType(resourceType);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#value(String)
+       */
+      public static ListTagsOptions value(String value) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.value(value);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#page
+       */
+      public static ListTagsOptions page(long page) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.page(page);
+      }
+
+      /**
+       * @see org.jclouds.cloudstack.options.ListTagsOptions#pageSize
+       */
+      public static ListTagsOptions pageSize(long pageSize) {
+         ListTagsOptions options = new ListTagsOptions();
+         return options.pageSize(pageSize);
+      }
+   }
+
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public ListTagsOptions accountInDomain(String account, String domain) {
+      return ListTagsOptions.class.cast(super.accountInDomain(account, domain));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public ListTagsOptions domainId(String domainId) {
+      return ListTagsOptions.class.cast(super.domainId(domainId));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListTemplatesOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListTemplatesOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListTemplatesOptions.java
index 4769920..f73c2e6 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListTemplatesOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListTemplatesOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import org.jclouds.cloudstack.domain.TemplateFilter;
 
 import com.google.common.collect.ImmutableSet;
@@ -90,6 +92,21 @@ public class ListTemplatesOptions extends AccountInDomainOptions {
       return this;
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListTemplatesOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
    public static class Builder {
 
       /**
@@ -155,6 +172,14 @@ public class ListTemplatesOptions extends AccountInDomainOptions {
          ListTemplatesOptions options = new ListTemplatesOptions();
          return options.hypervisor(hypervisor);
       }
+
+      /**
+       * @see ListTemplatesOptions#tags
+       */
+      public static ListTemplatesOptions tags(Map<String, String> tags) {
+         ListTemplatesOptions options = new ListTemplatesOptions();
+         return options.tags(tags);
+      }
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListVirtualMachinesOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListVirtualMachinesOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListVirtualMachinesOptions.java
index 4d1c7d6..294f32b 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListVirtualMachinesOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListVirtualMachinesOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -126,6 +128,21 @@ public class ListVirtualMachinesOptions extends AccountInDomainOptions {
       return this;
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListVirtualMachinesOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
+
    public static class Builder {
 
       /**
@@ -223,6 +240,14 @@ public class ListVirtualMachinesOptions extends AccountInDomainOptions {
          ListVirtualMachinesOptions options = new ListVirtualMachinesOptions();
          return options.usesVirtualNetwork(usesVirtualNetwork);
       }
+
+      /**
+       * @see ListVirtualMachinesOptions#tags
+       */
+      public static ListVirtualMachinesOptions tags(Map<String, String> tags) {
+         ListVirtualMachinesOptions options = new ListVirtualMachinesOptions();
+         return options.tags(tags);
+      }
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListVolumesOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListVolumesOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListVolumesOptions.java
index fb11c3b..0d27b08 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListVolumesOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListVolumesOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import org.jclouds.cloudstack.domain.Volume;
 
 import com.google.common.collect.ImmutableSet;
@@ -114,6 +116,20 @@ public class ListVolumesOptions extends AccountInDomainOptions {
 
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListVolumesOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
 
    public static class Builder {
 
@@ -213,6 +229,14 @@ public class ListVolumesOptions extends AccountInDomainOptions {
          ListVolumesOptions options = new ListVolumesOptions();
          return options.projectId(id);
       }
+
+      /**
+       * @see ListVolumesOptions#tags
+       */
+      public static ListVolumesOptions tags(Map<String, String> tags) {
+         ListVolumesOptions options = new ListVolumesOptions();
+         return options.tags(tags);
+      }
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListZonesOptions.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListZonesOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListZonesOptions.java
index db7dfb2..cd071c4 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListZonesOptions.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListZonesOptions.java
@@ -16,6 +16,8 @@
  */
 package org.jclouds.cloudstack.options;
 
+import java.util.Map;
+
 import org.jclouds.http.options.BaseHttpRequestOptions;
 
 import com.google.common.collect.ImmutableSet;
@@ -61,6 +63,20 @@ public class ListZonesOptions extends BaseHttpRequestOptions {
       return this;
    }
 
+   /**
+    * @param tags
+    *           Key/value pairs for tags that need to be matched.
+    */
+   public ListZonesOptions tags(Map<String, String> tags) {
+      int count = 0;
+      for (Map.Entry<String, String> entry : tags.entrySet()) {
+         this.queryParameters.replaceValues(String.format("tags[%d].key", count), ImmutableSet.of(entry.getKey()));
+         this.queryParameters.replaceValues(String.format("tags[%d].value", count),
+               ImmutableSet.of(entry.getValue()));
+         count += 1;
+      }
+      return this;
+   }
    public static class Builder {
 
       /**
@@ -87,5 +103,12 @@ public class ListZonesOptions extends BaseHttpRequestOptions {
          return options.id(id);
       }
 
+      /**
+       * @see ListZonesOptions#tags
+       */
+      public static ListZonesOptions tags(Map<String, String> tags) {
+         ListZonesOptions options = new ListZonesOptions();
+         return options.tags(tags);
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiExpectTest.java
index fdc2544..db6dbc5 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiExpectTest.java
@@ -22,17 +22,17 @@ import static org.testng.Assert.assertNull;
 import java.net.URI;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableSet;
 import org.jclouds.cloudstack.CloudStackContext;
 import org.jclouds.cloudstack.domain.AsyncCreateResponse;
 import org.jclouds.cloudstack.domain.FirewallRule;
 import org.jclouds.cloudstack.domain.PortForwardingRule;
+import org.jclouds.cloudstack.domain.Tag;
 import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.testng.annotations.Test;
 
-import com.google.common.collect.ImmutableSet;
-
 /**
  * Test the CloudStack FirewallApi
  */
@@ -64,7 +64,8 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
                .CIDRs(CIDRs).build(),
             FirewallRule.builder().id("10").protocol(FirewallRule.Protocol.TCP).startPort(22)
             .endPort(22).ipAddressId("8").ipAddress("10.27.27.57").state(FirewallRule.State.ACTIVE)
-               .CIDRs(CIDRs).build()
+               .CIDRs(CIDRs).tags(Tag.builder().account("1").domain("ROOT").domainId("1").key("some-tag").resourceId("10")
+                  .resourceType(Tag.ResourceType.FIREWALL_RULE).value("some-value").build()).build()
          ));
    }
 
@@ -173,13 +174,16 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
       Set<String> cidrs = ImmutableSet.of("0.0.0.0/1", "128.0.0.0/1");
 
       assertEquals(client.listPortForwardingRules(),
-         ImmutableSet.<PortForwardingRule>of(
-            PortForwardingRule.builder().id("15").privatePort(22).protocol(PortForwardingRule.Protocol.TCP)
-               .publicPort(2022).virtualMachineId("3").virtualMachineName("i-3-3-VM").IPAddressId("3")
-               .IPAddress("72.52.126.32").state(PortForwardingRule.State.ACTIVE).CIDRs(cidrs).build(),
-            PortForwardingRule.builder().id("18").privatePort(22).protocol(PortForwardingRule.Protocol.TCP)
-               .publicPort(22).virtualMachineId("89").virtualMachineName("i-3-89-VM").IPAddressId("34")
-               .IPAddress("72.52.126.63").state(PortForwardingRule.State.ACTIVE).build())
+            ImmutableSet.<PortForwardingRule>of(
+                  PortForwardingRule.builder().id("18").privatePort(22).protocol(PortForwardingRule.Protocol.TCP)
+                        .publicPort(22).virtualMachineId("89").virtualMachineName("i-3-89-VM").IPAddressId("34")
+                        .IPAddress("72.52.126.63").state(PortForwardingRule.State.ACTIVE).build(),
+                  PortForwardingRule.builder().id("15").privatePort(22).protocol(PortForwardingRule.Protocol.TCP)
+                        .publicPort(2022).virtualMachineId("3").virtualMachineName("i-3-3-VM").IPAddressId("3")
+                        .IPAddress("72.52.126.32").state(PortForwardingRule.State.ACTIVE)
+                        .CIDRs(cidrs).tags(Tag.builder().account("1").domain("ROOT").domainId("1").key("some-tag").resourceId("15")
+                        .resourceType(Tag.ResourceType.PORT_FORWARDING_RULE).value("some-value").build()).build()
+                  )
       );
    }
 
@@ -216,9 +220,11 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
       Set<String> cidrs = ImmutableSet.of("0.0.0.0/1", "128.0.0.0/1");
 
       assertEquals(client.getPortForwardingRule("15"),
-         PortForwardingRule.builder().id("15").privatePort(22).protocol(PortForwardingRule.Protocol.TCP)
-            .publicPort(2022).virtualMachineId("3").virtualMachineName("i-3-3-VM").IPAddressId("3")
-            .IPAddress("72.52.126.32").state(PortForwardingRule.State.ACTIVE).CIDRs(cidrs).build());
+            PortForwardingRule.builder().id("15").privatePort(22).protocol(PortForwardingRule.Protocol.TCP)
+                  .publicPort(2022).virtualMachineId("3").virtualMachineName("i-3-3-VM").IPAddressId("3")
+                  .IPAddress("72.52.126.32").state(PortForwardingRule.State.ACTIVE)
+                  .CIDRs(cidrs).tags(Tag.builder().account("1").domain("ROOT").domainId("1").key("some-tag").resourceId("15")
+                  .resourceType(Tag.ResourceType.PORT_FORWARDING_RULE).value("some-value").build()).build());
    }
 
    public void testGetPortForwardingRuleWhenResponseIs404() {
@@ -296,15 +302,16 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
       Set<String> CIDRs  = ImmutableSet.of("0.0.0.0/0");
       assertEquals(client.listEgressFirewallRules(),
               ImmutableSet.of(
-                      FirewallRule.builder().id("2017").protocol(FirewallRule.Protocol.TCP).startPort(30)
-                              .endPort(35).ipAddressId("2").ipAddress("10.27.27.51").state(FirewallRule.State.ACTIVE)
-                              .CIDRs(CIDRs).build(),
-                      FirewallRule.builder().id("2016").protocol(FirewallRule.Protocol.TCP).startPort(22)
-                              .endPort(22).ipAddressId("2").ipAddress("10.27.27.51").state(FirewallRule.State.ACTIVE)
-                              .CIDRs(CIDRs).build(),
-                      FirewallRule.builder().id("10").protocol(FirewallRule.Protocol.TCP).startPort(22)
-                              .endPort(22).ipAddressId("8").ipAddress("10.27.27.57").state(FirewallRule.State.ACTIVE)
-                              .CIDRs(CIDRs).build()
+                    FirewallRule.builder().id("2017").protocol(FirewallRule.Protocol.TCP).startPort(30)
+                          .endPort(35).ipAddressId("2").ipAddress("10.27.27.51").state(FirewallRule.State.ACTIVE)
+                          .CIDRs(CIDRs).build(),
+                    FirewallRule.builder().id("2016").protocol(FirewallRule.Protocol.TCP).startPort(22)
+                          .endPort(22).ipAddressId("2").ipAddress("10.27.27.51").state(FirewallRule.State.ACTIVE)
+                          .CIDRs(CIDRs).build(),
+                    FirewallRule.builder().id("10").protocol(FirewallRule.Protocol.TCP).startPort(22)
+                          .endPort(22).ipAddressId("8").ipAddress("10.27.27.57").state(FirewallRule.State.ACTIVE)
+                          .CIDRs(CIDRs).tags(Tag.builder().account("1").domain("ROOT").domainId("1").key("some-tag").resourceId("10")
+                          .resourceType(Tag.ResourceType.FIREWALL_RULE).value("some-value").build()).build()
               ));
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ProjectApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ProjectApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ProjectApiExpectTest.java
index b7665be..3bf640f 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ProjectApiExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ProjectApiExpectTest.java
@@ -22,6 +22,7 @@ import java.util.Set;
 
 import org.jclouds.cloudstack.CloudStackContext;
 import org.jclouds.cloudstack.domain.Project;
+import org.jclouds.cloudstack.domain.Tag;
 import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
@@ -50,22 +51,32 @@ public class ProjectApiExpectTest extends BaseCloudStackExpectTest<ProjectApi> {
             .build());
 
       Set<Project> projects = ImmutableSet.of(
-              Project.builder()
-                      .id("489da162-0b77-489d-b044-ce39aa018b1f")
-                      .account("thyde")
-                      .displayText("")
-                      .domain("ROOT")
-                      .domainId("41a4917b-7952-499d-ba7f-4c57464d3dc8")
-                      .name("NN-HA-T1")
-                      .state(Project.State.ACTIVE).build(),
-              Project.builder()
-                      .id("1c11f22c-15ac-4fa7-b833-4d748df317b7")
-                      .account("prasadm")
-                      .displayText("Hive")
-                      .domain("ROOT")
-                      .domainId("41a4917b-7952-499d-ba7f-4c57464d3dc8")
-                      .name("hive")
-                      .state(Project.State.ACTIVE).build());
+            Project.builder()
+                  .id("489da162-0b77-489d-b044-ce39aa018b1f")
+                  .account("thyde")
+                  .displayText("")
+                  .domain("ROOT")
+                  .domainId("41a4917b-7952-499d-ba7f-4c57464d3dc8")
+                  .name("NN-HA-T1")
+                  .state(Project.State.ACTIVE).build(),
+            Project.builder()
+                  .id("1c11f22c-15ac-4fa7-b833-4d748df317b7")
+                  .account("prasadm")
+                  .displayText("Hive")
+                  .domain("ROOT")
+                  .domainId("41a4917b-7952-499d-ba7f-4c57464d3dc8")
+                  .name("hive")
+                  .state(Project.State.ACTIVE)
+                  .tags(Tag.builder()
+                        .account("prasadm")
+                        .domain("ROOT")
+                        .domainId("41a4917b-7952-499d-ba7f-4c57464d3dc8")
+                        .key("some-tag")
+                        .resourceId("1c11f22c-15ac-4fa7-b833-4d748df317b7")
+                        .resourceType(Tag.ResourceType.PROJECT)
+                        .value("some-value")
+                        .build())
+                  .build());
 
       assertEquals(client.listProjects(), projects);
    }