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 21:40:10 UTC

[4/5] git commit: JCLOUDS-756. Add support for tags to CloudStack.

JCLOUDS-756. Add support for tags to CloudStack.


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

Branch: refs/heads/master
Commit: 43bb86f0858ccacb16ef8dbdcad823a948887854
Parents: b220d88
Author: Andrew Bayer <an...@gmail.com>
Authored: Tue Oct 21 14:18:12 2014 -0700
Committer: Andrew Bayer <an...@gmail.com>
Committed: Tue Oct 21 14:18:12 2014 -0700

----------------------------------------------------------------------
 .../org/jclouds/cloudstack/CloudStackApi.java   |   7 +
 .../jclouds/cloudstack/domain/FirewallRule.java |  41 ++-
 .../cloudstack/domain/IPForwardingRule.java     |  41 ++-
 .../java/org/jclouds/cloudstack/domain/ISO.java |  43 ++-
 .../jclouds/cloudstack/domain/IngressRule.java  |  46 ++-
 .../org/jclouds/cloudstack/domain/Network.java  |  45 ++-
 .../cloudstack/domain/PortForwardingRule.java   |  43 ++-
 .../org/jclouds/cloudstack/domain/Project.java  |  52 ++-
 .../cloudstack/domain/PublicIPAddress.java      |  40 ++-
 .../cloudstack/domain/SecurityGroup.java        |  39 +-
 .../org/jclouds/cloudstack/domain/Snapshot.java |  41 ++-
 .../java/org/jclouds/cloudstack/domain/Tag.java | 352 +++++++++++++++++++
 .../org/jclouds/cloudstack/domain/Template.java |  47 ++-
 .../cloudstack/domain/VirtualMachine.java       |  39 +-
 .../org/jclouds/cloudstack/domain/Volume.java   |  40 ++-
 .../org/jclouds/cloudstack/domain/Zone.java     |  40 ++-
 .../org/jclouds/cloudstack/features/TagApi.java |  89 +++++
 .../cloudstack/options/CreateTagsOptions.java   | 124 +++++++
 .../cloudstack/options/DeleteTagsOptions.java   | 111 ++++++
 .../options/ListEgressFirewallRulesOptions.java |  25 ++
 .../options/ListFirewallRulesOptions.java       |  25 ++
 .../options/ListIPForwardingRulesOptions.java   |  26 ++
 .../cloudstack/options/ListISOsOptions.java     |  23 ++
 .../cloudstack/options/ListNetworksOptions.java |  52 ++-
 .../options/ListPortForwardingRulesOptions.java |  27 ++
 .../cloudstack/options/ListProjectsOptions.java |  25 ++
 .../options/ListPublicIPAddressesOptions.java   |  25 ++
 .../options/ListSecurityGroupsOptions.java      |  29 +-
 .../options/ListSnapshotsOptions.java           |  24 ++
 .../cloudstack/options/ListTagsOptions.java     | 247 +++++++++++++
 .../options/ListTemplatesOptions.java           |  25 ++
 .../options/ListVirtualMachinesOptions.java     |  25 ++
 .../cloudstack/options/ListVolumesOptions.java  |  24 ++
 .../cloudstack/options/ListZonesOptions.java    |  23 ++
 .../features/FirewallApiExpectTest.java         |  51 +--
 .../features/ProjectApiExpectTest.java          |  43 ++-
 .../cloudstack/features/TagApiExpectTest.java   | 153 ++++++++
 .../cloudstack/features/TagApiLiveTest.java     | 147 ++++++++
 .../jclouds/cloudstack/features/TagApiTest.java | 123 +++++++
 .../cloudstack/features/ZoneApiExpectTest.java  |  19 +-
 .../options/CreateTagsOptionsTest.java          | 102 ++++++
 .../options/DeleteTagsOptionsTest.java          |  91 +++++
 .../ListIPForwardingRulesOptionsTest.java       |  19 +
 .../cloudstack/options/ListISOsOptionsTest.java |  19 +
 .../options/ListNetworksOptionsTest.java        |  19 +
 .../ListPortForwardingRulesOptionsTest.java     |  18 +
 .../ListPublicIPAddressesOptionsTest.java       |  18 +
 .../options/ListSecurityGroupsOptionsTest.java  |  18 +
 .../cloudstack/options/ListTagsOptionsTest.java | 152 ++++++++
 .../options/ListTemplatesOptionsTest.java       |  18 +
 .../options/ListVirtualMachesOptionsTest.java   | 152 --------
 .../options/ListVirtualMachinesOptionsTest.java | 170 +++++++++
 .../options/ListZonesOptionsTest.java           |  18 +
 .../parse/ListFirewallRulesResponseTest.java    |   7 +-
 .../ListIPForwardingRulesResponseTest.java      |   9 +-
 .../parse/ListNetworksResponseTest.java         |  11 +-
 .../ListPortForwardingRulesResponseTest.java    |  15 +-
 .../ListPublicIPAddressesResponseTest.java      |  13 +-
 .../parse/ListSecurityGroupsResponseTest.java   |  31 +-
 .../cloudstack/parse/ListTagsResponseTest.java  |  66 ++++
 .../parse/ListTemplatesResponseTest.java        |   3 +
 .../ListVirtualMachinesResponse3xTest.java      |  17 +-
 .../cloudstack/parse/ListZonesResponseTest.java |  25 +-
 .../src/test/resources/createtagsresponse.json  |   1 +
 .../src/test/resources/deletetagsresponse.json  |   1 +
 .../getportforwardingrulesresponse.json         |  19 +-
 .../listegressfirewallrulesresponse.json        |   5 +-
 .../resources/listfirewallrulesresponse.json    |   5 +-
 .../listipforwardingrulesresponse.json          |   3 +-
 .../test/resources/listnetworksresponse.json    |  96 ++++-
 .../listportforwardingrulesresponse.json        |  30 +-
 .../test/resources/listprojectsresponse.json    |  36 +-
 .../listpublicipaddressesresponse.json          |  32 +-
 .../resources/listsecuritygroupsresponse.json   | 118 ++++++-
 .../src/test/resources/listtagsresponse.json    |  16 +
 .../test/resources/listtemplatesresponse.json   | 130 ++++++-
 .../listvirtualmachinesresponse3x.json          |  57 ++-
 .../listvolumesreponse-imageextension.json      |   2 -
 .../src/test/resources/listzonesresponse.json   |  30 +-
 79 files changed, 3643 insertions(+), 390 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackApi.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackApi.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackApi.java
index a873643..d333246 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackApi.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackApi.java
@@ -37,6 +37,7 @@ import org.jclouds.cloudstack.features.SSHKeyPairApi;
 import org.jclouds.cloudstack.features.SecurityGroupApi;
 import org.jclouds.cloudstack.features.SessionApi;
 import org.jclouds.cloudstack.features.SnapshotApi;
+import org.jclouds.cloudstack.features.TagApi;
 import org.jclouds.cloudstack.features.TemplateApi;
 import org.jclouds.cloudstack.features.VMGroupApi;
 import org.jclouds.cloudstack.features.VirtualMachineApi;
@@ -195,4 +196,10 @@ public interface CloudStackApi extends Closeable {
     */
    @Delegate
    ProjectApi getProjectApi();
+
+   /**
+    * Provides synchronous access to Tags
+    */
+   @Delegate
+   TagApi getTagApi();
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/FirewallRule.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/FirewallRule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/FirewallRule.java
index 37e79e2..8c604b8 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/FirewallRule.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/FirewallRule.java
@@ -100,6 +100,7 @@ public class FirewallRule implements Comparable<FirewallRule> {
       protected String ipAddressId;
       protected FirewallRule.Protocol protocol;
       protected FirewallRule.State state;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see FirewallRule#getId()
@@ -185,8 +186,20 @@ public class FirewallRule implements Comparable<FirewallRule> {
          return self();
       }
 
+      /**
+       * @see FirewallRule#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 FirewallRule build() {
-         return new FirewallRule(id, CIDRs, startPort, endPort, icmpCode, icmpType, ipAddress, ipAddressId, protocol, state);
+         return new FirewallRule(id, CIDRs, startPort, endPort, icmpCode, icmpType, ipAddress, ipAddressId, protocol, state, tags);
       }
 
       public T fromFirewallRule(FirewallRule in) {
@@ -200,7 +213,8 @@ public class FirewallRule implements Comparable<FirewallRule> {
                .ipAddress(in.getIpAddress())
                .ipAddressId(in.getIpAddressId())
                .protocol(in.getProtocol())
-               .state(in.getState());
+               .state(in.getState())
+               .tags(in.getTags());
       }
    }
 
@@ -221,14 +235,15 @@ public class FirewallRule implements Comparable<FirewallRule> {
    private final String ipAddressId;
    private final FirewallRule.Protocol protocol;
    private final FirewallRule.State state;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
-         "id", "cidrlist", "startport", "endport", "icmpcode", "icmptype", "ipaddress", "ipaddressid", "protocol", "state"
+         "id", "cidrlist", "startport", "endport", "icmpcode", "icmptype", "ipaddress", "ipaddressid", "protocol", "state", "tags"
    })
    private FirewallRule(String id, @Nullable String CIDRs, int startPort, int endPort, @Nullable String icmpCode,
                         @Nullable String icmpType, @Nullable String ipAddress, @Nullable String ipAddressId,
-                        @Nullable Protocol protocol, @Nullable State state) {
-      this(id, splitStringOnCommas(CIDRs), startPort, endPort, icmpCode, icmpType, ipAddress, ipAddressId, protocol, state);
+                        @Nullable Protocol protocol, @Nullable State state, @Nullable Set<Tag> tags) {
+      this(id, splitStringOnCommas(CIDRs), startPort, endPort, icmpCode, icmpType, ipAddress, ipAddressId, protocol, state, tags);
    }
 
    private static Set<String> splitStringOnCommas(String in) {
@@ -238,7 +253,7 @@ public class FirewallRule implements Comparable<FirewallRule> {
 
    protected FirewallRule(String id, @Nullable Iterable<String> CIDRs, int startPort, int endPort, @Nullable String icmpCode,
                           @Nullable String icmpType, @Nullable String ipAddress, @Nullable String ipAddressId,
-                          @Nullable FirewallRule.Protocol protocol, @Nullable FirewallRule.State state) {
+                          @Nullable FirewallRule.Protocol protocol, @Nullable FirewallRule.State state, @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.CIDRs = CIDRs == null ? ImmutableSet.<String>of() : ImmutableSet.copyOf(CIDRs);
       this.startPort = startPort;
@@ -249,6 +264,7 @@ public class FirewallRule implements Comparable<FirewallRule> {
       this.ipAddressId = ipAddressId;
       this.protocol = protocol;
       this.state = state;
+      this.tags = tags == null ? ImmutableSet.<Tag>of() : ImmutableSet.copyOf(tags);
    }
 
    public String getId() {
@@ -297,9 +313,14 @@ public class FirewallRule implements Comparable<FirewallRule> {
       return this.state;
    }
 
+   @Nullable
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(id, CIDRs, startPort, endPort, icmpCode, icmpType, ipAddress, ipAddressId, protocol, state);
+      return Objects.hashCode(id, CIDRs, startPort, endPort, icmpCode, icmpType, ipAddress, ipAddressId, protocol, state, tags);
    }
 
    @Override
@@ -316,13 +337,15 @@ public class FirewallRule implements Comparable<FirewallRule> {
             && Objects.equal(this.ipAddress, that.ipAddress)
             && Objects.equal(this.ipAddressId, that.ipAddressId)
             && Objects.equal(this.protocol, that.protocol)
-            && Objects.equal(this.state, that.state);
+            && Objects.equal(this.state, that.state)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
       return MoreObjects.toStringHelper(this)
             .add("id", id).add("CIDRs", CIDRs).add("startPort", startPort).add("endPort", endPort).add("icmpCode", icmpCode)
-            .add("icmpType", icmpType).add("ipAddress", ipAddress).add("ipAddressId", ipAddressId).add("protocol", protocol).add("state", state);
+            .add("icmpType", icmpType).add("ipAddress", ipAddress).add("ipAddressId", ipAddressId).add("protocol", protocol).add("state", state)
+            .add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/IPForwardingRule.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/IPForwardingRule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/IPForwardingRule.java
index 6703c80..e06888b 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/IPForwardingRule.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/IPForwardingRule.java
@@ -58,6 +58,7 @@ public class IPForwardingRule implements Comparable<IPForwardingRule> {
       protected Set<String> CIDRs = ImmutableSet.of();
       protected int privateEndPort;
       protected int publicEndPort;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see IPForwardingRule#getId()
@@ -175,9 +176,21 @@ public class IPForwardingRule implements Comparable<IPForwardingRule> {
          return self();
       }
 
+      /**
+       * @see IPForwardingRule#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 IPForwardingRule build() {
          return new IPForwardingRule(id, IPAddress, IPAddressId, startPort, protocol, endPort, state, virtualMachineDisplayName,
-               virtualMachineId, virtualMachineName, publicPort, CIDRs, privateEndPort, publicEndPort);
+               virtualMachineId, virtualMachineName, publicPort, CIDRs, privateEndPort, publicEndPort, tags);
       }
 
       public T fromIPForwardingRule(IPForwardingRule in) {
@@ -195,7 +208,8 @@ public class IPForwardingRule implements Comparable<IPForwardingRule> {
                .publicPort(in.getPublicPort())
                .CIDRs(in.getCIDRs())
                .privateEndPort(in.getPrivateEndPort())
-               .publicEndPort(in.getPublicEndPort());
+               .publicEndPort(in.getPublicEndPort())
+               .tags(in.getTags());
       }
    }
 
@@ -220,15 +234,17 @@ public class IPForwardingRule implements Comparable<IPForwardingRule> {
    private final Set<String> CIDRs;
    private final int privateEndPort;
    private final int publicEndPort;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
          "id", "ipaddress", "ipaddressid", "startport", "protocol", "endport", "state", "virtualmachinedisplayname",
-         "virtualmachineid", "virtualmachinename", "publicport", "cidrlist", "privateendport", "publicendport"
+         "virtualmachineid", "virtualmachinename", "publicport", "cidrlist", "privateendport", "publicendport", "tags"
    })
    protected IPForwardingRule(String id, String IPAddress, String IPAddressId, int startPort, @Nullable String protocol,
                               int endPort, @Nullable String state, @Nullable String virtualMachineDisplayName,
                               @Nullable String virtualMachineId, @Nullable String virtualMachineName, int publicPort,
-                              @Nullable Set<String> CIDRs, int privateEndPort, int publicEndPort) {
+                              @Nullable Set<String> CIDRs, int privateEndPort, int publicEndPort,
+                              @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.IPAddress = IPAddress;
       this.IPAddressId = IPAddressId;
@@ -243,6 +259,7 @@ public class IPForwardingRule implements Comparable<IPForwardingRule> {
       this.CIDRs = CIDRs == null ? ImmutableSet.<String>of() : ImmutableSet.copyOf(CIDRs);
       this.privateEndPort = privateEndPort;
       this.publicEndPort = publicEndPort;
+      this.tags = tags == null ? ImmutableSet.<Tag>of() : ImmutableSet.copyOf(tags);
    }
 
    /**
@@ -350,9 +367,17 @@ public class IPForwardingRule implements Comparable<IPForwardingRule> {
       return this.publicEndPort;
    }
 
+   /**
+    * @return Tags on this rule
+    */
+   @Nullable
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(id, IPAddress, IPAddressId, startPort, protocol, endPort, state, virtualMachineDisplayName, virtualMachineId, virtualMachineName, publicPort, CIDRs, privateEndPort, publicEndPort);
+      return Objects.hashCode(id, IPAddress, IPAddressId, startPort, protocol, endPort, state, virtualMachineDisplayName, virtualMachineId, virtualMachineName, publicPort, CIDRs, privateEndPort, publicEndPort, tags);
    }
 
    @Override
@@ -373,7 +398,8 @@ public class IPForwardingRule implements Comparable<IPForwardingRule> {
             && Objects.equal(this.publicPort, that.publicPort)
             && Objects.equal(this.CIDRs, that.CIDRs)
             && Objects.equal(this.privateEndPort, that.privateEndPort)
-            && Objects.equal(this.publicEndPort, that.publicEndPort);
+            && Objects.equal(this.publicEndPort, that.publicEndPort)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
@@ -381,7 +407,8 @@ public class IPForwardingRule implements Comparable<IPForwardingRule> {
             .add("id", id).add("IPAddress", IPAddress).add("IPAddressId", IPAddressId).add("startPort", startPort)
             .add("protocol", protocol).add("endPort", endPort).add("state", state).add("virtualMachineDisplayName", virtualMachineDisplayName)
             .add("virtualMachineId", virtualMachineId).add("virtualMachineName", virtualMachineName).add("publicPort", publicPort)
-            .add("CIDRs", CIDRs).add("privateEndPort", privateEndPort).add("publicEndPort", publicEndPort);
+            .add("CIDRs", CIDRs).add("privateEndPort", privateEndPort).add("publicEndPort", publicEndPort)
+            .add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/ISO.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/ISO.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/ISO.java
index 3e79b04..a93304a 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/ISO.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/ISO.java
@@ -20,7 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.beans.ConstructorProperties;
 import java.util.Date;
+import java.util.Set;
 
+import com.google.common.collect.ImmutableSet;
 import org.jclouds.javax.annotation.Nullable;
 
 import com.google.common.base.MoreObjects;
@@ -90,6 +92,7 @@ public class ISO {
       protected String templateType;
       protected String zoneId;
       protected String zoneName;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see ISO#getId()
@@ -347,11 +350,23 @@ public class ISO {
          return self();
       }
 
+      /**
+       * @see ISO#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 ISO build() {
          return new ISO(id, account, accountId, bootable, checksum, created, crossZones, displayText, domain, domainid,
                format, hostId, hostName, hypervisor, isExtractable, isFeatured, isPublic, isReady, jobId, jobStatus, name,
                osTypeId, osTypeName, passwordEnabled, removed, size, sourceTemplateId, status, templateTag, templateType,
-               zoneId, zoneName);
+               zoneId, zoneName, tags);
       }
 
       public T fromISO(ISO in) {
@@ -387,7 +402,8 @@ public class ISO {
                .templateTag(in.getTemplateTag())
                .templateType(in.getTemplateType())
                .zoneId(in.getZoneId())
-               .zoneName(in.getZoneName());
+               .zoneName(in.getZoneName())
+               .tags(in.getTags());
       }
    }
 
@@ -430,9 +446,10 @@ public class ISO {
    private final String templateType;
    private final String zoneId;
    private final String zoneName;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
-         "id", "account", "accountid", "bootable", "checksum", "created", "crossZones", "displaytext", "domain", "domainid", "format", "hostid", "hostname", "hypervisor", "isextractable", "isfeatured", "ispublic", "isready", "jobid", "jobstatus", "name", "ostypeid", "ostypename", "passwordenabled", "removed", "size", "sourcetemplateid", "status", "templatetag", "templatetype", "zoneid", "zonename"
+         "id", "account", "accountid", "bootable", "checksum", "created", "crossZones", "displaytext", "domain", "domainid", "format", "hostid", "hostname", "hypervisor", "isextractable", "isfeatured", "ispublic", "isready", "jobid", "jobstatus", "name", "ostypeid", "ostypename", "passwordenabled", "removed", "size", "sourcetemplateid", "status", "templatetag", "templatetype", "zoneid", "zonename", "tags"
    })
    protected ISO(String id, @Nullable String account, @Nullable String accountId, boolean bootable, @Nullable String checksum,
                  @Nullable Date created, boolean crossZones, @Nullable String displayText, @Nullable String domain,
@@ -440,7 +457,8 @@ public class ISO {
                  @Nullable String hypervisor, boolean isExtractable, boolean isFeatured, boolean isPublic, boolean isReady,
                  @Nullable String jobId, @Nullable String jobStatus, @Nullable String name, @Nullable String osTypeId,
                  @Nullable String osTypeName, boolean passwordEnabled, @Nullable Date removed, long size, @Nullable String sourceTemplateId,
-                 @Nullable String status, @Nullable String templateTag, @Nullable String templateType, @Nullable String zoneId, @Nullable String zoneName) {
+                 @Nullable String status, @Nullable String templateTag, @Nullable String templateType, @Nullable String zoneId, @Nullable String zoneName,
+                 @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.account = account;
       this.accountId = accountId;
@@ -473,6 +491,7 @@ public class ISO {
       this.templateType = templateType;
       this.zoneId = zoneId;
       this.zoneName = zoneName;
+      this.tags = tags == null ? ImmutableSet.<Tag>of() : ImmutableSet.copyOf(tags);
    }
 
    /**
@@ -701,11 +720,20 @@ public class ISO {
       return this.zoneName;
    }
 
+   /**
+    * @return Tags on this ISO
+    */
+   @Nullable
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
       return Objects.hashCode(id, account, accountId, bootable, checksum, created, crossZones, displayText, domain,
             domainid, format, hostId, hostName, hypervisor, isExtractable, isFeatured, isPublic, isReady, jobId, jobStatus,
-            name, osTypeId, osTypeName, passwordEnabled, removed, size, sourceTemplateId, status, templateTag, templateType, zoneId, zoneName);
+            name, osTypeId, osTypeName, passwordEnabled, removed, size, sourceTemplateId, status, templateTag, templateType, zoneId, zoneName,
+            tags);
    }
 
    @Override
@@ -744,7 +772,8 @@ public class ISO {
             && Objects.equal(this.templateTag, that.templateTag)
             && Objects.equal(this.templateType, that.templateType)
             && 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() {
@@ -756,7 +785,7 @@ public class ISO {
             .add("isReady", isReady).add("jobId", jobId).add("jobStatus", jobStatus).add("name", name).add("osTypeId", osTypeId)
             .add("osTypeName", osTypeName).add("passwordEnabled", passwordEnabled).add("removed", removed).add("size", size)
             .add("sourceTemplateId", sourceTemplateId).add("status", status).add("templateTag", templateTag).add("templateType", templateType)
-            .add("zoneId", zoneId).add("zoneName", zoneName);
+            .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/IngressRule.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/IngressRule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/IngressRule.java
index efb5ff9..df3a388 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/IngressRule.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/IngressRule.java
@@ -19,12 +19,13 @@ package org.jclouds.cloudstack.domain;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.beans.ConstructorProperties;
-
-import org.jclouds.javax.annotation.Nullable;
+import java.util.Set;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.javax.annotation.Nullable;
 
 public class IngressRule implements Comparable<IngressRule> {
 
@@ -48,6 +49,7 @@ public class IngressRule implements Comparable<IngressRule> {
       protected String id;
       protected String securityGroupName;
       protected int startPort;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see IngressRule#getAccount()
@@ -121,8 +123,20 @@ public class IngressRule implements Comparable<IngressRule> {
          return self();
       }
 
+      /**
+       * @see IngressRule#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 IngressRule build() {
-         return new IngressRule(account, CIDR, endPort, ICMPCode, ICMPType, protocol, id, securityGroupName, startPort);
+         return new IngressRule(account, CIDR, endPort, ICMPCode, ICMPType, protocol, id, securityGroupName, startPort, tags);
       }
 
       public T fromIngressRule(IngressRule in) {
@@ -135,7 +149,8 @@ public class IngressRule implements Comparable<IngressRule> {
                .protocol(in.getProtocol())
                .id(in.getId())
                .securityGroupName(in.getSecurityGroupName())
-               .startPort(in.getStartPort());
+               .startPort(in.getStartPort())
+               .tags(in.getTags());
       }
    }
 
@@ -155,12 +170,14 @@ public class IngressRule implements Comparable<IngressRule> {
    private final String id;
    private final String securityGroupName;
    private final int startPort;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
-         "account", "cidr", "endport", "icmpcode", "icmptype", "protocol", "ruleid", "securitygroupname", "startport"
+         "account", "cidr", "endport", "icmpcode", "icmptype", "protocol", "ruleid", "securitygroupname", "startport", "tags"
    })
    protected IngressRule(@Nullable String account, @Nullable String CIDR, int endPort, int ICMPCode, int ICMPType,
-                         @Nullable String protocol, String id, @Nullable String securityGroupName, int startPort) {
+                         @Nullable String protocol, String id, @Nullable String securityGroupName, int startPort,
+                         @Nullable Set<Tag> tags) {
       this.account = account;
       this.CIDR = CIDR;
       this.endPort = endPort;
@@ -170,6 +187,7 @@ public class IngressRule implements Comparable<IngressRule> {
       this.id = checkNotNull(id, "id");
       this.securityGroupName = securityGroupName;
       this.startPort = startPort;
+      this.tags = tags == null ? ImmutableSet.<Tag>of() : ImmutableSet.copyOf(tags);
    }
 
    /**
@@ -239,9 +257,17 @@ public class IngressRule implements Comparable<IngressRule> {
       return this.startPort;
    }
 
+   /**
+    * @return Tags on this rule
+    */
+   @Nullable
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(account, CIDR, endPort, ICMPCode, ICMPType, protocol, id, securityGroupName, startPort);
+      return Objects.hashCode(account, CIDR, endPort, ICMPCode, ICMPType, protocol, id, securityGroupName, startPort, tags);
    }
 
    @Override
@@ -257,13 +283,15 @@ public class IngressRule implements Comparable<IngressRule> {
             && Objects.equal(this.protocol, that.protocol)
             && Objects.equal(this.id, that.id)
             && Objects.equal(this.securityGroupName, that.securityGroupName)
-            && Objects.equal(this.startPort, that.startPort);
+            && Objects.equal(this.startPort, that.startPort)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
       return MoreObjects.toStringHelper(this)
             .add("account", account).add("CIDR", CIDR).add("endPort", endPort).add("ICMPCode", ICMPCode)
-            .add("ICMPType", ICMPType).add("protocol", protocol).add("id", id).add("securityGroupName", securityGroupName).add("startPort", startPort);
+            .add("ICMPType", ICMPType).add("protocol", protocol).add("id", id).add("securityGroupName", securityGroupName).add("startPort", startPort)
+            .add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Network.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Network.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Network.java
index a6ec5a4..bcfd411 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Network.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Network.java
@@ -76,9 +76,9 @@ public class Network {
       protected String VLAN;
       protected TrafficType trafficType;
       protected String zoneId;
-      protected ImmutableSet.Builder<String> tags = ImmutableSet.<String>builder();
       protected boolean securityGroupEnabled;
       protected Set<? extends NetworkService> services = ImmutableSortedSet.of();
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see Network#getId()
@@ -298,23 +298,6 @@ public class Network {
       }
 
       /**
-       * @see Network#getTags()
-       */
-      public T tags(Iterable<String> tags) {
-         this.tags = ImmutableSet.<String>builder().addAll(tags);
-         return self();
-      }
-      
-      /**
-       * @see Network#getTags()
-       */
-      public T tag(String tag) {
-         this.tags.add(tag);
-         return self();
-      }
-      
-
-      /**
        * @see Network#isSecurityGroupEnabled()
        */
       public T securityGroupEnabled(boolean securityGroupEnabled) {
@@ -330,8 +313,20 @@ public class Network {
          return self();
       }
 
+      /**
+       * @see Network#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 Network build() {
-         return new Network(id, account, broadcastDomainType, broadcastURI, displayText, DNS1, DNS2, domain, domainId, endIP, gateway, isDefault, isShared, isSystem, netmask, networkDomain, networkOfferingAvailability, networkOfferingDisplayText, networkOfferingId, networkOfferingName, related, startIP, name, state, guestIPType, VLAN, trafficType, zoneId, tags.build(), securityGroupEnabled, services);
+         return new Network(id, account, broadcastDomainType, broadcastURI, displayText, DNS1, DNS2, domain, domainId, endIP, gateway, isDefault, isShared, isSystem, netmask, networkDomain, networkOfferingAvailability, networkOfferingDisplayText, networkOfferingId, networkOfferingName, related, startIP, name, state, guestIPType, VLAN, trafficType, zoneId, tags, securityGroupEnabled, services);
       }
 
       public T fromNetwork(Network in) {
@@ -363,9 +358,9 @@ public class Network {
                .VLAN(in.getVLAN())
                .trafficType(in.getTrafficType())
                .zoneId(in.getZoneId())
-               .tags(in.getTags())
                .securityGroupEnabled(in.isSecurityGroupEnabled())
-               .services(in.getServices());
+               .services(in.getServices())
+               .tags(in.getTags());
       }
    }
 
@@ -404,7 +399,7 @@ public class Network {
    private final String VLAN;
    private final TrafficType trafficType;
    private final String zoneId;
-   private final Set<String> tags;
+   private final Set<Tag> tags;
    private final boolean securityGroupEnabled;
    private final Set<? extends NetworkService> services;
 
@@ -418,7 +413,7 @@ public class Network {
                      @Nullable String networkOfferingDisplayText, @Nullable String networkOfferingId, @Nullable String networkOfferingName,
                      @Nullable String related, @Nullable String startIP, @Nullable String name, @Nullable String state,
                      @Nullable GuestIPType guestIPType, @Nullable String VLAN, @Nullable TrafficType trafficType,
-                     @Nullable String zoneId, @Nullable Iterable<String> tags, boolean securityGroupEnabled, Set<? extends NetworkService> services) {
+                     @Nullable String zoneId, @Nullable Set<Tag> tags, boolean securityGroupEnabled, Set<? extends NetworkService> services) {
       this.id = checkNotNull(id, "id");
       this.account = account;
       this.broadcastDomainType = broadcastDomainType;
@@ -447,7 +442,7 @@ public class Network {
       this.VLAN = VLAN;
       this.trafficType = trafficType;
       this.zoneId = zoneId;
-      this.tags = tags != null ? ImmutableSet.copyOf(tags) : ImmutableSet.<String> of();
+      this.tags = tags != null ? ImmutableSet.copyOf(tags) : ImmutableSet.<Tag> of();
       this.securityGroupEnabled = securityGroupEnabled;
       this.services = ImmutableSortedSet.copyOf(services);
    }
@@ -667,7 +662,7 @@ public class Network {
    /**
     * @return the tags for the Network
     */
-   public Set<String> getTags() {
+   public Set<Tag> getTags() {
       return this.tags;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PortForwardingRule.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PortForwardingRule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PortForwardingRule.java
index 2b3fcdf..b98123f 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PortForwardingRule.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PortForwardingRule.java
@@ -101,6 +101,7 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
       protected Set<String> CIDRs = ImmutableSet.of();
       protected int privateEndPort;
       protected int publicEndPort;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see PortForwardingRule#getId()
@@ -210,9 +211,21 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
          return self();
       }
 
+      /**
+       * @see PortForwardingRule#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 PortForwardingRule build() {
          return new PortForwardingRule(id, IPAddress, IPAddressId, privatePort, protocol, publicPort, state, virtualMachineDisplayName,
-               virtualMachineId, virtualMachineName, CIDRs, privateEndPort, publicEndPort);
+               virtualMachineId, virtualMachineName, CIDRs, privateEndPort, publicEndPort, tags);
       }
 
       public T fromPortForwardingRule(PortForwardingRule in) {
@@ -229,7 +242,8 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
                .virtualMachineName(in.getVirtualMachineName())
                .CIDRs(in.getCIDRs())
                .privateEndPort(in.getPrivateEndPort())
-               .publicEndPort(in.getPublicEndPort());
+               .publicEndPort(in.getPublicEndPort())
+               .tags(in.getTags());
       }
    }
 
@@ -253,17 +267,18 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
    private final Set<String> CIDRs;
    private final int privateEndPort;
    private final int publicEndPort;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
          "id", "ipaddress", "ipaddressid", "privateport", "protocol", "publicport", "state", "virtualmachinedisplayname",
-         "virtualmachineid", "virtualmachinename", "cidrlist", "privateendport", "publicendport"
+         "virtualmachineid", "virtualmachinename", "cidrlist", "privateendport", "publicendport", "tags"
    })
    private PortForwardingRule(String id, @Nullable String IPAddress, @Nullable String IPAddressId, int privatePort,
                               @Nullable Protocol protocol, int publicPort, @Nullable State state, @Nullable String virtualMachineDisplayName,
                               @Nullable String virtualMachineId, @Nullable String virtualMachineName, @Nullable String CIDRs,
-                              int privateEndPort, int publicEndPort) {
+                              int privateEndPort, int publicEndPort, @Nullable Set<Tag> tags) {
       this(id, IPAddress, IPAddressId, privatePort, protocol, publicPort, state, virtualMachineDisplayName, virtualMachineId,
-            virtualMachineName, splitStringOnCommas(CIDRs), privateEndPort, publicEndPort);
+            virtualMachineName, splitStringOnCommas(CIDRs), privateEndPort, publicEndPort, tags);
    }
 
    private static Set<String> splitStringOnCommas(String in) {
@@ -273,7 +288,8 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
    protected PortForwardingRule(String id, @Nullable String IPAddress, @Nullable String IPAddressId, int privatePort,
                                 @Nullable Protocol protocol, int publicPort, @Nullable State state,
                                 @Nullable String virtualMachineDisplayName, @Nullable String virtualMachineId,
-                                @Nullable String virtualMachineName, @Nullable Set<String> CIDRs, int privateEndPort, int publicEndPort) {
+                                @Nullable String virtualMachineName, @Nullable Set<String> CIDRs, int privateEndPort,
+                                int publicEndPort, @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.IPAddress = IPAddress;
       this.IPAddressId = IPAddressId;
@@ -287,6 +303,7 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
       this.CIDRs = CIDRs == null ? ImmutableSet.<String>of() : ImmutableSet.copyOf(CIDRs);
       this.privateEndPort = privateEndPort;
       this.publicEndPort = publicEndPort;
+      this.tags = tags != null ? ImmutableSet.copyOf(tags) : ImmutableSet.<Tag> of();
    }
 
    /**
@@ -387,9 +404,16 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
       return this.publicEndPort;
    }
 
+   /**
+    * @return the tags for the rule
+    */
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(id, IPAddress, IPAddressId, privatePort, protocol, publicPort, state, virtualMachineDisplayName, virtualMachineId, virtualMachineName, CIDRs, privateEndPort, publicEndPort);
+      return Objects.hashCode(id, IPAddress, IPAddressId, privatePort, protocol, publicPort, state, virtualMachineDisplayName, virtualMachineId, virtualMachineName, CIDRs, privateEndPort, publicEndPort, tags);
    }
 
    @Override
@@ -409,7 +433,8 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
             && Objects.equal(this.virtualMachineName, that.virtualMachineName)
             && Objects.equal(this.CIDRs, that.CIDRs)
             && Objects.equal(this.privateEndPort, that.privateEndPort)
-            && Objects.equal(this.publicEndPort, that.publicEndPort);
+            && Objects.equal(this.publicEndPort, that.publicEndPort)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
@@ -417,7 +442,7 @@ public class PortForwardingRule implements Comparable<PortForwardingRule> {
             .add("id", id).add("IPAddress", IPAddress).add("IPAddressId", IPAddressId).add("privatePort", privatePort)
             .add("protocol", protocol).add("publicPort", publicPort).add("state", state).add("virtualMachineDisplayName", virtualMachineDisplayName)
             .add("virtualMachineId", virtualMachineId).add("virtualMachineName", virtualMachineName).add("CIDRs", CIDRs)
-            .add("privateEndPort", privateEndPort).add("publicEndPort", publicEndPort);
+            .add("privateEndPort", privateEndPort).add("publicEndPort", publicEndPort).add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Project.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Project.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Project.java
index 29323a4..cecc372 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Project.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Project.java
@@ -19,7 +19,9 @@ package org.jclouds.cloudstack.domain;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.beans.ConstructorProperties;
+import java.util.Set;
 
+import com.google.common.collect.ImmutableSet;
 import org.jclouds.javax.annotation.Nullable;
 
 import com.google.common.base.CaseFormat;
@@ -68,6 +70,7 @@ public class Project implements Comparable<Project> {
       protected String domainId;
       protected String name;
       protected State state;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see org.jclouds.cloudstack.domain.Project#getId()
@@ -125,20 +128,32 @@ public class Project implements Comparable<Project> {
          return self();
       }
 
+      /**
+       * @see Project#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 Project build() {
-         return new Project(id, account, displayText, domain, domainId, name, state);
+         return new Project(id, account, displayText, domain, domainId, name, state, tags);
       }
 
       public T fromDomain(Project in) {
          return this
-                 .id(in.getId())
-                 .account(in.getAccount())
-                 .displayText(in.getDisplayText())
-                 .domain(in.getDomain())
-                 .domainId(in.getDomainId())
-                 .name(in.getName())
-                 .state(in.getState());
+               .id(in.getId())
+               .account(in.getAccount())
+               .displayText(in.getDisplayText())
+               .domain(in.getDomain())
+               .domainId(in.getDomainId())
+               .name(in.getName())
+               .state(in.getState())
+               .tags(in.getTags());
       }
    }
 
@@ -156,12 +171,13 @@ public class Project implements Comparable<Project> {
    private final String domainId;
    private final String name;
    private final State state;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
-         "id", "account", "displaytext", "domain", "domainid", "name", "state"
+         "id", "account", "displaytext", "domain", "domainid", "name", "state", "tags"
    })
    protected Project(String id, String account, String displayText, String domain, String domainId,
-                     String name, State state) {
+                     String name, State state, @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.account = account;
       this.displayText = displayText;
@@ -169,6 +185,7 @@ public class Project implements Comparable<Project> {
       this.domainId = domainId;
       this.name = name;
       this.state = checkNotNull(state, "state");
+      this.tags = tags != null ? ImmutableSet.copyOf(tags) : ImmutableSet.<Tag> of();
    }
 
    public String getId() {
@@ -204,9 +221,16 @@ public class Project implements Comparable<Project> {
       return this.state;
    }
 
+   /**
+    * @return the tags for the project
+    */
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(id, account, displayText, domain, domainId, name, state);
+      return Objects.hashCode(id, account, displayText, domain, domainId, name, state, tags);
    }
 
    @Override
@@ -220,13 +244,15 @@ public class Project implements Comparable<Project> {
             && Objects.equal(this.domain, that.domain)
             && Objects.equal(this.domainId, that.domainId)
             && Objects.equal(this.name, that.name)
-            && Objects.equal(this.state, that.state);
+            && Objects.equal(this.state, that.state)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
       return MoreObjects.toStringHelper(this).omitNullValues()
             .add("id", id).add("account", account).add("displayText", displayText)
-              .add("domain", domain).add("domainId", domainId).add("name", name).add("state", state);
+            .add("domain", domain).add("domainId", domainId).add("name", name).add("state", state)
+            .add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PublicIPAddress.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PublicIPAddress.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PublicIPAddress.java
index 1d6cff3..d6211df 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PublicIPAddress.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PublicIPAddress.java
@@ -20,7 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.beans.ConstructorProperties;
 import java.util.Date;
+import java.util.Set;
 
+import com.google.common.collect.ImmutableSet;
 import org.jclouds.javax.annotation.Nullable;
 
 import com.google.common.base.CaseFormat;
@@ -85,6 +87,7 @@ public class PublicIPAddress {
       protected String zoneName;
       protected String jobId;
       protected Integer jobStatus;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see PublicIPAddress#getId()
@@ -254,8 +257,20 @@ public class PublicIPAddress {
          return self();
       }
 
+      /**
+       * @see PublicIPAddress#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 PublicIPAddress build() {
-         return new PublicIPAddress(id, account, allocated, associatedNetworkId, domain, domainId, usesVirtualNetwork, IPAddress, isSourceNAT, isStaticNAT, networkId, state, virtualMachineDisplayName, virtualMachineId, virtualMachineName, VLANId, VLANName, zoneId, zoneName, jobId, jobStatus);
+         return new PublicIPAddress(id, account, allocated, associatedNetworkId, domain, domainId, usesVirtualNetwork, IPAddress, isSourceNAT, isStaticNAT, networkId, state, virtualMachineDisplayName, virtualMachineId, virtualMachineName, VLANId, VLANName, zoneId, zoneName, jobId, jobStatus, tags);
       }
 
       public T fromPublicIPAddress(PublicIPAddress in) {
@@ -280,7 +295,8 @@ public class PublicIPAddress {
                .zoneId(in.getZoneId())
                .zoneName(in.getZoneName())
                .jobId(in.getJobId())
-               .jobStatus(in.getJobStatus());
+               .jobStatus(in.getJobStatus())
+               .tags(in.getTags());
       }
    }
 
@@ -312,18 +328,19 @@ public class PublicIPAddress {
    private final String zoneName;
    private final String jobId;
    private final Integer jobStatus;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
          "id", "account", "allocated", "associatednetworkid", "domain", "domainid", "forvirtualnetwork", "ipaddress", "issourcenat",
          "isstaticnat", "networkid", "state", "virtualmachinedisplayname", "virtualmachineid", "virtualmachinename", "VLANid",
-         "VLANname", "zoneid", "zonename", "jobid", "jobstatus"
+         "VLANname", "zoneid", "zonename", "jobid", "jobstatus", "tags"
    })
    protected PublicIPAddress(String id, @Nullable String account, @Nullable Date allocated, @Nullable String associatedNetworkId,
                              @Nullable String domain, @Nullable String domainId, boolean usesVirtualNetwork, @Nullable String IPAddress,
                              boolean isSourceNAT, boolean isStaticNAT, @Nullable String networkId, @Nullable PublicIPAddress.State state,
                              @Nullable String virtualMachineDisplayName, @Nullable String virtualMachineId, @Nullable String virtualMachineName,
                              @Nullable String VLANId, @Nullable String VLANName, @Nullable String zoneId, @Nullable String zoneName,
-                             @Nullable String jobId, @Nullable Integer jobStatus) {
+                             @Nullable String jobId, @Nullable Integer jobStatus, @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.account = account;
       this.allocated = allocated;
@@ -345,6 +362,7 @@ public class PublicIPAddress {
       this.zoneName = zoneName;
       this.jobId = jobId;
       this.jobStatus = jobStatus;
+      this.tags = tags != null ? ImmutableSet.copyOf(tags) : ImmutableSet.<Tag> of();
    }
 
    /**
@@ -517,9 +535,16 @@ public class PublicIPAddress {
       return this.jobStatus;
    }
 
+   /**
+    * @return the tags for the public IP address
+    */
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(id, account, allocated, associatedNetworkId, domain, domainId, usesVirtualNetwork, IPAddress, isSourceNAT, isStaticNAT, networkId, state, virtualMachineDisplayName, virtualMachineId, virtualMachineName, VLANId, VLANName, zoneId, zoneName, jobId, jobStatus);
+      return Objects.hashCode(id, account, allocated, associatedNetworkId, domain, domainId, usesVirtualNetwork, IPAddress, isSourceNAT, isStaticNAT, networkId, state, virtualMachineDisplayName, virtualMachineId, virtualMachineName, VLANId, VLANName, zoneId, zoneName, jobId, jobStatus, tags);
    }
 
    @Override
@@ -547,7 +572,8 @@ public class PublicIPAddress {
             && Objects.equal(this.zoneId, that.zoneId)
             && Objects.equal(this.zoneName, that.zoneName)
             && Objects.equal(this.jobId, that.jobId)
-            && Objects.equal(this.jobStatus, that.jobStatus);
+            && Objects.equal(this.jobStatus, that.jobStatus)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
@@ -557,7 +583,7 @@ public class PublicIPAddress {
             .add("isSourceNAT", isSourceNAT).add("isStaticNAT", isStaticNAT).add("networkId", networkId).add("state", state)
             .add("virtualMachineDisplayName", virtualMachineDisplayName).add("virtualMachineId", virtualMachineId)
             .add("virtualMachineName", virtualMachineName).add("VLANId", VLANId).add("VLANName", VLANName).add("zoneId", zoneId)
-            .add("zoneName", zoneName).add("jobId", jobId).add("jobStatus", jobStatus);
+            .add("zoneName", zoneName).add("jobId", jobId).add("jobStatus", jobStatus).add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SecurityGroup.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SecurityGroup.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SecurityGroup.java
index 356fb00..b261965 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SecurityGroup.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SecurityGroup.java
@@ -54,6 +54,7 @@ public class SecurityGroup implements Comparable<SecurityGroup> {
       protected String jobId;
       protected Integer jobStatus;
       protected Set<IngressRule> ingressRules;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see SecurityGroup#getId()
@@ -127,8 +128,20 @@ public class SecurityGroup implements Comparable<SecurityGroup> {
          return self();
       }
 
+      /**
+       * @see SecurityGroup#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 SecurityGroup build() {
-         return new SecurityGroup(id, account, name, description, domain, domainId, jobId, jobStatus, ingressRules);
+         return new SecurityGroup(id, account, name, description, domain, domainId, jobId, jobStatus, ingressRules, tags);
       }
 
       public T fromSecurityGroup(SecurityGroup in) {
@@ -141,7 +154,8 @@ public class SecurityGroup implements Comparable<SecurityGroup> {
                .domainId(in.getDomainId())
                .jobId(in.getJobId())
                .jobStatus(in.getJobStatus())
-               .ingressRules(in.getIngressRules());
+               .ingressRules(in.getIngressRules())
+               .tags(in.getTags());
       }
    }
 
@@ -161,13 +175,14 @@ public class SecurityGroup implements Comparable<SecurityGroup> {
    private final String jobId;
    private final Integer jobStatus;
    private final Set<IngressRule> ingressRules;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
-         "id", "account", "name", "description", "domain", "domainid", "jobid", "jobstatus", "ingressrule"
+         "id", "account", "name", "description", "domain", "domainid", "jobid", "jobstatus", "ingressrule", "tags"
    })
    protected SecurityGroup(String id, @Nullable String account, @Nullable String name, @Nullable String description,
                            @Nullable String domain, @Nullable String domainId, @Nullable String jobId, @Nullable Integer jobStatus,
-                           @Nullable Set<IngressRule> ingressRules) {
+                           @Nullable Set<IngressRule> ingressRules, @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.account = account;
       this.name = name;
@@ -177,6 +192,7 @@ public class SecurityGroup implements Comparable<SecurityGroup> {
       this.jobId = jobId;
       this.jobStatus = jobStatus;
       this.ingressRules = ingressRules == null ? ImmutableSet.<IngressRule>of() : ImmutableSortedSet.copyOf(ingressRules);
+      this.tags = tags != null ? ImmutableSet.copyOf(tags) : ImmutableSet.<Tag> of();
    }
 
    /**
@@ -251,9 +267,16 @@ public class SecurityGroup implements Comparable<SecurityGroup> {
       return this.ingressRules;
    }
 
+   /**
+    * @return the tags for the security group
+    */
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(id, account, name, description, domain, domainId, jobId, jobStatus, ingressRules);
+      return Objects.hashCode(id, account, name, description, domain, domainId, jobId, jobStatus, ingressRules, tags);
    }
 
    @Override
@@ -269,12 +292,14 @@ public class SecurityGroup implements Comparable<SecurityGroup> {
             && Objects.equal(this.domainId, that.domainId)
             && Objects.equal(this.jobId, that.jobId)
             && Objects.equal(this.jobStatus, that.jobStatus)
-            && Objects.equal(this.ingressRules, that.ingressRules);
+            && Objects.equal(this.ingressRules, that.ingressRules)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
       return MoreObjects.toStringHelper(this).add("id", id).add("account", account).add("name", name).add("description", description)
-            .add("domain", domain).add("domainId", domainId).add("jobId", jobId).add("jobStatus", jobStatus).add("ingressRules", ingressRules);
+            .add("domain", domain).add("domainId", domainId).add("jobId", jobId).add("jobStatus", jobStatus).add("ingressRules", ingressRules)
+            .add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java
index d832a2a..86636d0 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java
@@ -20,7 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.beans.ConstructorProperties;
 import java.util.Date;
+import java.util.Set;
 
+import com.google.common.collect.ImmutableSet;
 import org.jclouds.javax.annotation.Nullable;
 
 import com.google.common.base.CaseFormat;
@@ -108,6 +110,7 @@ public class Snapshot {
       protected String volumeId;
       protected String volumeName;
       protected Volume.Type volumeType;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see Snapshot#getId()
@@ -221,9 +224,21 @@ public class Snapshot {
          return self();
       }
 
+      /**
+       * @see Snapshot#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 Snapshot build() {
          return new Snapshot(id, account, created, domain, domainId, interval, jobId, jobStatus, name, snapshotType, state,
-               volumeId, volumeName, volumeType);
+               volumeId, volumeName, volumeType, tags);
       }
 
       public T fromSnapshot(Snapshot in) {
@@ -241,7 +256,8 @@ public class Snapshot {
                .state(in.getState())
                .volumeId(in.getVolumeId())
                .volumeName(in.getVolumeName())
-               .volumeType(in.getVolumeType());
+               .volumeType(in.getVolumeType())
+               .tags(in.getTags());
       }
    }
 
@@ -266,14 +282,15 @@ public class Snapshot {
    private final String volumeId;
    private final String volumeName;
    private final Volume.Type volumeType;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
-         "id", "account", "created", "domain", "domainid", "intervaltype", "jobid", "jobstatus", "name", "snapshottype", "state", "volumeid", "volumename", "volumetype"
+         "id", "account", "created", "domain", "domainid", "intervaltype", "jobid", "jobstatus", "name", "snapshottype", "state", "volumeid", "volumename", "volumetype", "tags"
    })
    protected Snapshot(String id, @Nullable String account, @Nullable Date created, @Nullable String domain, @Nullable String domainId,
                       @Nullable Snapshot.Interval interval, @Nullable String jobId, @Nullable String jobStatus, @Nullable String name,
                       @Nullable Snapshot.Type snapshotType, @Nullable Snapshot.State state, @Nullable String volumeId, @Nullable String volumeName,
-                      @Nullable Volume.Type volumeType) {
+                      @Nullable Volume.Type volumeType, @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.account = account;
       this.created = created;
@@ -288,6 +305,7 @@ public class Snapshot {
       this.volumeId = volumeId;
       this.volumeName = volumeName;
       this.volumeType = volumeType;
+      this.tags = tags != null ? ImmutableSet.copyOf(tags) : ImmutableSet.<Tag> of();
    }
 
    /**
@@ -401,9 +419,16 @@ public class Snapshot {
       return this.volumeType;
    }
 
+   /**
+    * @return the tags for the snapshot
+    */
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(id, account, created, domain, domainId, interval, jobId, jobStatus, name, snapshotType, state, volumeId, volumeName, volumeType);
+      return Objects.hashCode(id, account, created, domain, domainId, interval, jobId, jobStatus, name, snapshotType, state, volumeId, volumeName, volumeType, tags);
    }
 
    @Override
@@ -424,14 +449,16 @@ public class Snapshot {
             && Objects.equal(this.state, that.state)
             && Objects.equal(this.volumeId, that.volumeId)
             && Objects.equal(this.volumeName, that.volumeName)
-            && Objects.equal(this.volumeType, that.volumeType);
+            && Objects.equal(this.volumeType, that.volumeType)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
       return MoreObjects.toStringHelper(this)
             .add("id", id).add("account", account).add("created", created).add("domain", domain).add("domainId", domainId)
             .add("interval", interval).add("jobId", jobId).add("jobStatus", jobStatus).add("name", name).add("snapshotType", snapshotType)
-            .add("state", state).add("volumeId", volumeId).add("volumeName", volumeName).add("volumeType", volumeType);
+            .add("state", state).add("volumeId", volumeId).add("volumeName", volumeName).add("volumeType", volumeType)
+            .add("tags", tags);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Tag.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Tag.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Tag.java
new file mode 100644
index 0000000..1868c51
--- /dev/null
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Tag.java
@@ -0,0 +1,352 @@
+/*
+ * 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.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.util.Map;
+
+import com.google.common.base.Function;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import org.jclouds.javax.annotation.Nullable;
+
+/**
+ * Class Tag
+ */
+public class Tag {
+
+   /**
+    * Type of resource to update.
+    */
+   public enum ResourceType {
+      USER_VM("UserVm"),
+      TEMPLATE("Template"),
+      ISO("ISO"),
+      VOLUME("Volume"),
+      SNAPSHOT("Snapshot"),
+      NETWORK("Network"),
+      NIC("Nic"),
+      LOAD_BALANCER("LoadBalancer"),
+      PORT_FORWARDING_RULE("PortForwardingRule"),
+      FIREWALL_RULE("FirewallRule"),
+      SECURITY_GROUP("SecurityGroup"),
+      PUBLIC_IP_ADDRESS("PublicIpAddress"),
+      PROJECT("Project"),
+      VPC("Vpc"),
+      NETWORK_ACL("NetworkACL"),
+      STATIC_ROUTE("StaticRoute"),
+      VM_SNAPSHOT("VMSnapshot"),
+      REMOTE_ACCESS_VPN("RemoteAccessVpn"),
+      ZONE("Zone"),
+      SERVICE_OFFERING("ServiceOffering"),
+      STORAGE("Storage"),
+      PRIVATE_GATEWAY("PrivateGateway"),
+      NETWORK_ACL_LIST("NetworkACLList"),
+      VPN_GATEWAY("VpnGateway"),
+      CUSTOMER_GATEWAY("CustomerGateway"),
+      VPN_CONNECTION("VpnConnection"),
+      UNRECOGNIZED("");
+
+      private String code;
+
+      private static final Map<String, ResourceType> INDEX = Maps.uniqueIndex(ImmutableSet.copyOf(ResourceType.values()),
+              new Function<ResourceType, String>() {
+
+                 @Override
+                 public String apply(ResourceType input) {
+                    return input.code;
+                 }
+
+              });
+
+      ResourceType(String code) {
+         this.code = code;
+      }
+
+      public String getCode() {
+         return code;
+      }
+
+      @Override
+      public String toString() {
+         return code;
+      }
+
+      public static ResourceType fromValue(String resourceType) {
+         String code = checkNotNull(resourceType, "resourcetype");
+         return INDEX.containsKey(code) ? INDEX.get(code) : UNRECOGNIZED;
+      }
+   }
+
+   public static Builder<?> builder() {
+      return new ConcreteBuilder();
+   }
+
+   public Builder<?> toBuilder() {
+      return new ConcreteBuilder().fromTag(this);
+   }
+
+   public abstract static class Builder<T extends Builder<T>> {
+      protected abstract T self();
+
+      protected String account;
+      protected String customer;
+      protected String domain;
+      protected String domainId;
+      protected String key;
+      protected String project;
+      protected String projectId;
+      protected String resourceId;
+      protected ResourceType resourceType;
+      protected String value;
+
+      /**
+       * @see Tag#getAccount()
+       */
+      public T account(String account) {
+         this.account = account;
+         return self();
+      }
+
+      /**
+       * @see Tag#getCustomer()
+       */
+      public T customer(String customer) {
+         this.customer = customer;
+         return self();
+      }
+
+      /**
+       * @see Tag#getDomain()
+       */
+      public T domain(String domain) {
+         this.domain = domain;
+         return self();
+      }
+
+      /**
+       * @see Tag#getDomainId()
+       */
+      public T domainId(String domainId) {
+         this.domainId = domainId;
+         return self();
+      }
+
+      /**
+       * @see Tag#getKey()
+       */
+      public T key(String key) {
+         this.key = key;
+         return self();
+      }
+
+      /**
+       * @see Tag#getProject()
+       */
+      public T project(String project) {
+         this.project = project;
+         return self();
+      }
+
+      /**
+       * @see Tag#getProjectId()
+       */
+      public T projectId(String projectId) {
+         this.projectId = projectId;
+         return self();
+      }
+
+      /**
+       * @see Tag#getResourceId()
+       */
+      public T resourceId(String resourceId) {
+         this.resourceId = resourceId;
+         return self();
+      }
+
+      /**
+       * @see Tag#getResourceType()
+       */
+      public T resourceType(ResourceType resourceType) {
+         this.resourceType = resourceType;
+         return self();
+      }
+
+      /**
+       * @see Tag#getValue()
+       */
+      public T value(String value) {
+         this.value = value;
+         return self();
+      }
+
+      public Tag build() {
+         return new Tag(account, customer, domain, domainId, key, project,
+                 projectId, resourceId, resourceType, value);
+      }
+
+      public T fromTag(Tag in) {
+         return this
+                 .account(in.getAccount())
+                 .customer(in.getCustomer())
+                 .domain(in.getDomain())
+                 .domainId(in.getDomainId())
+                 .key(in.getKey())
+                 .project(in.getProject())
+                 .projectId(in.getProjectId())
+                 .resourceId(in.getResourceId())
+                 .resourceType(in.getResourceType())
+                 .value(in.getValue());
+      }
+   }
+
+   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+
+   private final String account;
+   private final String customer;
+   private final String domain;
+   private final String domainId;
+   private final String key;
+   private final String project;
+   private final String projectId;
+   private final String resourceId;
+   private final ResourceType resourceType;
+   private final String value;
+
+   @ConstructorProperties({
+           "account", "customer", "domain", "domainid", "key", "project", "projectid", "resourceid",
+            "resourcetype", "value"
+   })
+   protected Tag(@Nullable String account, @Nullable String customer, @Nullable String domain,
+                 @Nullable String domainId, @Nullable String key, @Nullable String project,
+                 @Nullable String projectId, @Nullable String resourceId,
+                 @Nullable ResourceType resourceType, @Nullable String value) {
+      this.account = account;
+      this.customer = customer;
+      this.domain = domain;
+      this.domainId = domainId;
+      this.key = key;
+      this.project = project;
+      this.projectId = projectId;
+      this.resourceId = resourceId;
+      this.resourceType = resourceType;
+      this.value = value;
+   }
+
+   @Nullable
+   public String getAccount() {
+      return this.account;
+   }
+
+   @Nullable
+   public String getCustomer() {
+      return this.customer;
+   }
+
+   @Nullable
+   public String getDomain() {
+      return this.domain;
+   }
+
+   @Nullable
+   public String getDomainId() {
+      return this.domainId;
+   }
+
+   @Nullable
+   public String getKey() {
+      return this.key;
+   }
+
+   @Nullable
+   public String getProject() {
+      return this.project;
+   }
+
+   @Nullable
+   public String getProjectId() {
+      return this.projectId;
+   }
+
+   @Nullable
+   public String getResourceId() {
+      return this.resourceId;
+   }
+
+   @Nullable
+   public ResourceType getResourceType() {
+      return this.resourceType;
+   }
+
+   @Nullable
+   public String getValue() {
+      return this.value;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(account, customer, domain, domainId, key, project, projectId,
+              resourceId, resourceType, value);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      Tag that = Tag.class.cast(obj);
+      return Objects.equal(this.account, that.account)
+              && Objects.equal(this.customer, that.customer)
+              && Objects.equal(this.domain, that.domain)
+              && Objects.equal(this.domainId, that.domainId)
+              && Objects.equal(this.key, that.key)
+              && Objects.equal(this.project, that.project)
+              && Objects.equal(this.projectId, that.projectId)
+              && Objects.equal(this.resourceId, that.resourceId)
+              && Objects.equal(this.resourceType, that.resourceType)
+              && Objects.equal(this.value, that.value);
+   }
+
+   protected ToStringHelper string() {
+      return MoreObjects.toStringHelper(this)
+              .add("account", account)
+              .add("customer", customer)
+              .add("domain", domain)
+              .add("domainId", domainId)
+              .add("key", key)
+              .add("project", project)
+              .add("projectId", projectId)
+              .add("resourceId", resourceId)
+              .add("resourceType", resourceType)
+              .add("value", value);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/43bb86f0/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Template.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Template.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Template.java
index 8019579..76dce48 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Template.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Template.java
@@ -20,13 +20,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.beans.ConstructorProperties;
 import java.util.Date;
-
-import com.google.common.base.Strings;
-import org.jclouds.javax.annotation.Nullable;
+import java.util.Set;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.javax.annotation.Nullable;
 
 public class Template implements Comparable<Template> {
    public enum Status {
@@ -166,6 +167,7 @@ public class Template implements Comparable<Template> {
       protected String hostName;
       protected String sourceTemplateId;
       protected String templateTag;
+      protected Set<Tag> tags = ImmutableSet.of();
 
       /**
        * @see Template#getId()
@@ -423,8 +425,20 @@ public class Template implements Comparable<Template> {
          return self();
       }
 
+      /**
+       * @see Template#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 Template build() {
-         return new Template(id, displayText, domain, domainId, account, accountId, zone, zoneId, OSType, OSTypeId, name, type, status, format, hypervisor, size, created, removed, crossZones, bootable, extractable, featured, isPublic, ready, passwordEnabled, jobId, jobStatus, checksum, hostId, hostName, sourceTemplateId, templateTag);
+         return new Template(id, displayText, domain, domainId, account, accountId, zone, zoneId, OSType, OSTypeId, name, type, status, format, hypervisor, size, created, removed, crossZones, bootable, extractable, featured, isPublic, ready, passwordEnabled, jobId, jobStatus, checksum, hostId, hostName, sourceTemplateId, templateTag, tags);
       }
 
       public T fromTemplate(Template in) {
@@ -460,7 +474,8 @@ public class Template implements Comparable<Template> {
                .hostId(in.getHostId())
                .hostName(in.getHostName())
                .sourceTemplateId(in.getSourceTemplateId())
-               .templateTag(in.getTemplateTag());
+               .templateTag(in.getTemplateTag())
+               .tags(in.getTags());
       }
    }
 
@@ -503,12 +518,13 @@ public class Template implements Comparable<Template> {
    private final String hostName;
    private final String sourceTemplateId;
    private final String templateTag;
+   private final Set<Tag> tags;
 
    @ConstructorProperties({
          "id", "displaytext", "domain", "domainid", "account", "accountid", "zonename", "zoneid", "ostypename", "ostypeid",
          "name", "templatetype", "status", "format", "hypervisor", "size", "created", "removed", "crossZones", "bootable",
          "isextractable", "isfeatured", "ispublic", "isready", "passwordenabled", "jobid", "jobstatus", "checksum", "hostId",
-         "hostname", "sourcetemplateid", "templatetag"
+         "hostname", "sourcetemplateid", "templatetag", "tags"
    })
    protected Template(String id, @Nullable String displayText, @Nullable String domain, @Nullable String domainId,
                       @Nullable String account, @Nullable String accountId, @Nullable String zone, @Nullable String zoneId,
@@ -517,7 +533,8 @@ public class Template implements Comparable<Template> {
                       @Nullable Long size, @Nullable Date created, @Nullable Date removed, boolean crossZones,
                       boolean bootable, boolean extractable, boolean featured, boolean ispublic, boolean ready, boolean passwordEnabled,
                       @Nullable String jobId, @Nullable String jobStatus, @Nullable String checksum, @Nullable String hostId,
-                      @Nullable String hostName, @Nullable String sourceTemplateId, @Nullable String templateTag) {
+                      @Nullable String hostName, @Nullable String sourceTemplateId, @Nullable String templateTag,
+                      @Nullable Set<Tag> tags) {
       this.id = checkNotNull(id, "id");
       this.displayText = displayText;
       this.domain = domain;
@@ -550,6 +567,7 @@ public class Template implements Comparable<Template> {
       this.hostName = hostName;
       this.sourceTemplateId = sourceTemplateId;
       this.templateTag = templateTag;
+      this.tags = tags == null ? ImmutableSet.<Tag>of() : ImmutableSet.copyOf(tags);
    }
 
    /**
@@ -806,9 +824,17 @@ public class Template implements Comparable<Template> {
       return this.templateTag;
    }
 
+   /**
+    * @return the tags on this template
+    */
+   @Nullable
+   public Set<Tag> getTags() {
+      return this.tags;
+   }
+
    @Override
    public int hashCode() {
-      return Objects.hashCode(id, displayText, domain, domainId, account, accountId, zone, zoneId, OSType, OSTypeId, name, type, status, format, hypervisor, size, created, removed, crossZones, bootable, extractable, featured, ispublic, ready, passwordEnabled, jobId, jobStatus, checksum, hostId, hostName, sourceTemplateId, templateTag);
+      return Objects.hashCode(id, displayText, domain, domainId, account, accountId, zone, zoneId, OSType, OSTypeId, name, type, status, format, hypervisor, size, created, removed, crossZones, bootable, extractable, featured, ispublic, ready, passwordEnabled, jobId, jobStatus, checksum, hostId, hostName, sourceTemplateId, templateTag, tags);
    }
 
    @Override
@@ -847,12 +873,13 @@ public class Template implements Comparable<Template> {
             && Objects.equal(this.hostId, that.hostId)
             && Objects.equal(this.hostName, that.hostName)
             && Objects.equal(this.sourceTemplateId, that.sourceTemplateId)
-            && Objects.equal(this.templateTag, that.templateTag);
+            && Objects.equal(this.templateTag, that.templateTag)
+            && Objects.equal(this.tags, that.tags);
    }
 
    protected ToStringHelper string() {
       return MoreObjects.toStringHelper(this)
-            .add("id", id).add("displayText", displayText).add("domain", domain).add("domainId", domainId).add("account", account).add("accountId", accountId).add("zone", zone).add("zoneId", zoneId).add("OSType", OSType).add("OSTypeId", OSTypeId).add("name", name).add("type", type).add("status", status).add("format", format).add("hypervisor", hypervisor).add("size", size).add("created", created).add("removed", removed).add("crossZones", crossZones).add("bootable", bootable).add("extractable", extractable).add("featured", featured).add("ispublic", ispublic).add("ready", ready).add("passwordEnabled", passwordEnabled).add("jobId", jobId).add("jobStatus", jobStatus).add("checksum", checksum).add("hostId", hostId).add("hostName", hostName).add("sourceTemplateId", sourceTemplateId).add("templateTag", templateTag);
+            .add("id", id).add("displayText", displayText).add("domain", domain).add("domainId", domainId).add("account", account).add("accountId", accountId).add("zone", zone).add("zoneId", zoneId).add("OSType", OSType).add("OSTypeId", OSTypeId).add("name", name).add("type", type).add("status", status).add("format", format).add("hypervisor", hypervisor).add("size", size).add("created", created).add("removed", removed).add("crossZones", crossZones).add("bootable", bootable).add("extractable", extractable).add("featured", featured).add("ispublic", ispublic).add("ready", ready).add("passwordEnabled", passwordEnabled).add("jobId", jobId).add("jobStatus", jobStatus).add("checksum", checksum).add("hostId", hostId).add("hostName", hostName).add("sourceTemplateId", sourceTemplateId).add("templateTag", templateTag).add("tags", tags);
    }
 
    @Override