You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ml...@apache.org on 2013/01/10 01:48:37 UTC

[5/52] [partial] Summary: Fixes for api_refactoring

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java
new file mode 100644
index 0000000..27013df
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java
@@ -0,0 +1,88 @@
+// 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.apache.cloudstack.api.command.user.ssh;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.SSHKeyPairResponse;
+import com.cloud.user.SSHKeyPair;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listSSHKeyPairs", description="List registered keypairs", responseObject=SSHKeyPairResponse.class)
+public class ListSSHKeyPairsCmd extends BaseListProjectAndAccountResourcesCmd {
+    public static final Logger s_logger = Logger.getLogger(ListSSHKeyPairsCmd.class.getName());
+    private static final String s_name = "listsshkeypairsresponse";
+
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="A key pair name to look for")
+    private String name;
+
+    @Parameter(name="fingerprint", type=CommandType.STRING, description="A public key fingerprint to look for")
+    private String fingerprint;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getName() {
+        return name;
+    }
+
+    public String getFingerprint() {
+        return fingerprint;
+    }
+
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public void execute() {
+        Pair<List<? extends SSHKeyPair>, Integer> resultList = _mgr.listSSHKeyPairs(this);
+        List<SSHKeyPairResponse> responses = new ArrayList<SSHKeyPairResponse>();
+        for (SSHKeyPair result : resultList.first()) {
+            SSHKeyPairResponse r = new SSHKeyPairResponse(result.getName(), result.getFingerprint());
+            r.setObjectName("sshkeypair");
+            responses.add(r);
+        }
+
+        ListResponse<SSHKeyPairResponse> response = new ListResponse<SSHKeyPairResponse>();
+        response.setResponses(responses, resultList.second());
+        response.setResponseName(getCommandName());
+        this.setResponseObject(response);
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java
new file mode 100644
index 0000000..2f08692
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java
@@ -0,0 +1,110 @@
+// 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.apache.cloudstack.api.command.user.ssh;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ProjectResponse;
+import org.apache.cloudstack.api.response.SSHKeyPairResponse;
+import com.cloud.user.SSHKeyPair;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "registerSSHKeyPair", description="Register a public key in a keypair under a certain name", responseObject=SSHKeyPairResponse.class)
+public class RegisterSSHKeyPairCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(RegisterSSHKeyPairCmd.class.getName());
+    private static final String s_name = "registersshkeypairresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="Name of the keypair")
+    private String name;
+
+    @Parameter(name="publickey", type=CommandType.STRING, required=true, description="Public key material of the keypair", length=5120)
+    private String publicKey;
+
+    //Owner information
+    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="an optional account for the ssh key. Must be used with domainId.")
+    private String accountName;
+
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType = DomainResponse.class,
+            description="an optional domainId for the ssh key. If the account parameter is used, domainId must also be used.")
+    private Long domainId;
+
+    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class,
+            description="an optional project for the ssh key")
+    private Long projectId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getName() {
+        return name;
+    }
+
+    public String getPublicKey() {
+        return publicKey;
+    }
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public Long getProjectId() {
+        return projectId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public long getEntityOwnerId() {
+        Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
+        if (accountId == null) {
+            return UserContext.current().getCaller().getId();
+        }
+
+        return accountId;
+    }
+
+    @Override
+    public void execute() {
+        SSHKeyPair result = _mgr.registerSSHKeyPair(this);
+        SSHKeyPairResponse response = new SSHKeyPairResponse(result.getName(), result.getFingerprint());
+        response.setResponseName(getCommandName());
+        response.setObjectName("keypair");
+        this.setResponseObject(response);
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java
new file mode 100644
index 0000000..54338bd
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java
@@ -0,0 +1,131 @@
+// 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.apache.cloudstack.api.command.user.tag;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.server.ResourceTag;
+import com.cloud.server.ResourceTag.TaggedResourceType;
+@APICommand(name = "createTags", description = "Creates resource tag(s)", responseObject = SuccessResponse.class, since = "Burbank")
+public class CreateTagsCmd extends BaseAsyncCmd{
+    public static final Logger s_logger = Logger.getLogger(CreateTagsCmd.class.getName());
+
+    private static final String s_name = "createtagsresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.TAGS, type = CommandType.MAP, required=true, description = "Map of tags (key/value pairs)")
+    private Map tag;
+
+    @Parameter(name=ApiConstants.RESOURCE_TYPE, type=CommandType.STRING, required=true, description="type of the resource")
+    private String resourceType;
+
+    @Parameter(name=ApiConstants.RESOURCE_IDS, type=CommandType.LIST, required=true,
+            collectionType=CommandType.STRING, description="list of resources to create the tags for")
+    private List<String> resourceIds;
+
+    @Parameter(name=ApiConstants.CUSTOMER, type=CommandType.STRING, description="identifies client specific tag. " +
+            "When the value is not null, the tag can't be used by cloudStack code internally")
+    private String customer;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+
+    public TaggedResourceType getResourceType(){
+        return _taggedResourceService.getResourceType(resourceType);
+    }
+
+    public Map<String, String> getTags() {
+        Map<String, String> tagsMap = null;
+        if (!tag.isEmpty()) {
+            tagsMap = new HashMap<String, String>();
+            Collection<?> servicesCollection = tag.values();
+            Iterator<?> iter = servicesCollection.iterator();
+            while (iter.hasNext()) {
+                HashMap<String, String> services = (HashMap<String, String>) iter.next();
+                String key = services.get("key");
+                String value = services.get("value");
+                tagsMap.put(key, value);
+            }
+        }
+        return tagsMap;
+    }
+
+    public List<String> getResourceIds() {
+        return resourceIds;
+    }
+
+    public String getCustomer() {
+        return customer;
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        //FIXME - validate the owner here
+       return 1;
+    }
+
+    @Override
+    public void execute() {
+        List<ResourceTag> tags = _taggedResourceService.createTags(getResourceIds(), getResourceType(), getTags(), getCustomer());
+
+        if (tags != null && !tags.isEmpty()) {
+                SuccessResponse response = new SuccessResponse(getCommandName());
+                this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create tags");
+        }
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_TAGS_CREATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "creating tags";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java
new file mode 100644
index 0000000..cf2ea9e
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java
@@ -0,0 +1,122 @@
+// 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.apache.cloudstack.api.command.user.tag;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.server.ResourceTag.TaggedResourceType;
+@APICommand(name = "deleteTags", description = "Deleting resource tag(s)", responseObject = SuccessResponse.class, since = "Burbank")
+public class DeleteTagsCmd extends BaseAsyncCmd{
+    public static final Logger s_logger = Logger.getLogger(DeleteTagsCmd.class.getName());
+
+    private static final String s_name = "deletetagsresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.TAGS, type = CommandType.MAP, description = "Delete tags matching key/value pairs")
+    private Map tag;
+
+    @Parameter(name=ApiConstants.RESOURCE_TYPE, type=CommandType.STRING, required=true, description="Delete tag by resource type")
+    private String resourceType;
+
+    @Parameter(name=ApiConstants.RESOURCE_IDS, type=CommandType.LIST, required=true,
+            collectionType=CommandType.STRING, description="Delete tags for resource id(s)")
+    private List<String> resourceIds;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+
+    public TaggedResourceType getResourceType(){
+        return _taggedResourceService.getResourceType(resourceType);
+    }
+
+    public Map<String, String> getTags() {
+        Map<String, String> tagsMap = null;
+        if (tag != null && !tag.isEmpty()) {
+            tagsMap = new HashMap<String, String>();
+            Collection<?> servicesCollection = tag.values();
+            Iterator<?> iter = servicesCollection.iterator();
+            while (iter.hasNext()) {
+                HashMap<String, String> services = (HashMap<String, String>) iter.next();
+                String key = services.get("key");
+                String value = services.get("value");
+                tagsMap.put(key, value);
+            }
+        }
+        return tagsMap;
+    }
+
+    public List<String> getResourceIds() {
+        return resourceIds;
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        //FIXME - validate the owner here
+       return 1;
+    }
+
+    @Override
+    public void execute() {
+        boolean success = _taggedResourceService.deleteTags(getResourceIds(), getResourceType(), getTags());
+
+        if (success) {
+                SuccessResponse response = new SuccessResponse(getCommandName());
+                this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete tags");
+        }
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_TAGS_DELETE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "Deleting tags";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java
new file mode 100644
index 0000000..e3dc108
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java
@@ -0,0 +1,83 @@
+// 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.apache.cloudstack.api.command.user.tag;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.ResourceTagResponse;
+
+@APICommand(name = "listTags", description = "List resource tag(s)", responseObject = ResourceTagResponse.class, since = "Burbank")
+public class ListTagsCmd extends BaseListProjectAndAccountResourcesCmd{
+    private static final String s_name = "listtagsresponse";
+
+    @Parameter(name=ApiConstants.RESOURCE_TYPE, type=CommandType.STRING, description="list by resource type")
+    private String resourceType;
+
+    @Parameter(name=ApiConstants.RESOURCE_ID, type=CommandType.STRING, description="list by resource id")
+    private String resourceId;
+
+    @Parameter(name=ApiConstants.KEY, type=CommandType.STRING, description="list by key")
+    private String key;
+
+    @Parameter(name=ApiConstants.VALUE, type=CommandType.STRING, description="list by value")
+    private String value;
+
+    @Parameter(name=ApiConstants.CUSTOMER, type=CommandType.STRING, description="list by customer name")
+    private String customer;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public void execute() {
+
+      ListResponse<ResourceTagResponse> response = _queryService.listTags(this);
+      response.setResponseName(getCommandName());
+      this.setResponseObject(response);
+    }
+
+    public String getResourceType() {
+        return resourceType;
+    }
+
+    public String getResourceId() {
+        return resourceId;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public String getCustomer() {
+        return customer;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java
new file mode 100644
index 0000000..c6461a7
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java
@@ -0,0 +1,144 @@
+// 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.apache.cloudstack.api.command.user.template;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.TemplateResponse;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.StorageUnavailableException;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "copyTemplate", description="Copies a template from one zone to another.", responseObject=TemplateResponse.class)
+public class CopyTemplateCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(CopyTemplateCmd.class.getName());
+    private static final String s_name = "copytemplateresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.DESTINATION_ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
+            required=true, description="ID of the zone the template is being copied to.")
+    private Long destZoneId;
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = UserVmResponse.class,
+            required=true, description="Template ID.")
+    private Long id;
+
+    @Parameter(name=ApiConstants.SOURCE_ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
+            required=true, description="ID of the zone the template is currently hosted on.")
+    private Long sourceZoneId;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getDestinationZoneId() {
+        return destZoneId;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public Long getSourceZoneId() {
+        return sourceZoneId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getStaticName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, getId());
+        if (template != null) {
+            return template.getAccountId();
+        }
+
+        // bad id given, parent this command to SYSTEM so ERROR events are tracked
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_TEMPLATE_COPY;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "copying template: " + getId() + " from zone: " + getSourceZoneId() + " to zone: " + getDestinationZoneId();
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Template;
+    }
+
+    public Long getInstanceId() {
+        return getId();
+    }
+
+    @Override
+    public void execute() throws ResourceAllocationException{
+        try {
+            UserContext.current().setEventDetails(getEventDescription());
+            VirtualMachineTemplate template = _templateService.copyTemplate(this);
+
+            if (template != null){
+                List<TemplateResponse> listResponse = _responseGenerator.createTemplateResponses(template.getId(), getDestinationZoneId(), false);
+                TemplateResponse response = new TemplateResponse();
+                if (listResponse != null && !listResponse.isEmpty()) {
+                    response = listResponse.get(0);
+                }
+
+                response.setResponseName(getCommandName());
+                this.setResponseObject(response);
+            } else {
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to copy template");
+            }
+        } catch (StorageUnavailableException ex) {
+            s_logger.warn("Exception: ", ex);
+            throw new ServerApiException(BaseCmd.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java
new file mode 100644
index 0000000..65cc8b9
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java
@@ -0,0 +1,285 @@
+// 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.apache.cloudstack.api.command.user.template;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cloudstack.api.*;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.GuestOSResponse;
+import org.apache.cloudstack.api.response.SnapshotResponse;
+import org.apache.cloudstack.api.response.StoragePoolResponse;
+import org.apache.cloudstack.api.response.TemplateResponse;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.VolumeResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.projects.Project;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.Volume;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "createTemplate", responseObject = StoragePoolResponse.class, description = "Creates a template of a virtual machine. " + "The virtual machine must be in a STOPPED state. "
+        + "A template created from this command is automatically designated as a private template visible to the account that created it.")
+        public class CreateTemplateCmd extends BaseAsyncCreateCmd {
+    public static final Logger s_logger = Logger.getLogger(CreateTemplateCmd.class.getName());
+    private static final String s_name = "createtemplateresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.BITS, type = CommandType.INTEGER, description = "32 or 64 bit")
+    private Integer bits;
+
+    @Parameter(name = ApiConstants.DISPLAY_TEXT, type = CommandType.STRING, required = true, description = "the display text of the template. This is usually used for display purposes.", length=4096)
+    private String displayText;
+
+    @Parameter(name = ApiConstants.IS_FEATURED, type = CommandType.BOOLEAN, description = "true if this template is a featured template, false otherwise")
+    private Boolean featured;
+
+    @Parameter(name = ApiConstants.IS_PUBLIC, type = CommandType.BOOLEAN, description = "true if this template is a public template, false otherwise")
+    private Boolean publicTemplate;
+
+    @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name of the template")
+    private String templateName;
+
+    @Parameter(name = ApiConstants.OS_TYPE_ID, type = CommandType.UUID, entityType = GuestOSResponse.class,
+            required = true, description = "the ID of the OS Type that best represents the OS of this template.")
+    private Long osTypeId;
+
+    @Parameter(name = ApiConstants.PASSWORD_ENABLED, type = CommandType.BOOLEAN, description = "true if the template supports the password reset feature; default is false")
+    private Boolean passwordEnabled;
+
+    @Parameter(name = ApiConstants.REQUIRES_HVM, type = CommandType.BOOLEAN, description = "true if the template requres HVM, false otherwise")
+    private Boolean requiresHvm;
+
+    @Parameter(name = ApiConstants.SNAPSHOT_ID, type = CommandType.UUID, entityType = SnapshotResponse.class,
+            description = "the ID of the snapshot the template is being created from. Either this parameter, or volumeId has to be passed in")
+    private Long snapshotId;
+
+    @Parameter(name = ApiConstants.VOLUME_ID, type = CommandType.UUID, entityType = VolumeResponse.class,
+            description = "the ID of the disk volume the template is being created from. Either this parameter, or snapshotId has to be passed in")
+    private Long volumeId;
+
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType = UserVmResponse.class,
+            description="Optional, VM ID. If this presents, it is going to create a baremetal template for VM this ID refers to. This is only for VM whose hypervisor type is BareMetal")
+    private Long vmId;
+
+    @Parameter(name=ApiConstants.URL, type=CommandType.STRING, description="Optional, only for baremetal hypervisor. The directory name where template stored on CIFS server")
+    private String url;
+
+    @Parameter(name=ApiConstants.TEMPLATE_TAG, type=CommandType.STRING, description="the tag for this template.")
+    private String templateTag;
+
+    @Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="Template details in key/value pairs.")
+    protected Map details;
+
+    // ///////////////////////////////////////////////////
+    // ///////////////// Accessors ///////////////////////
+    // ///////////////////////////////////////////////////
+
+    public String getEntityTable() {
+        return "vm_template";
+    }
+
+    public Integer getBits() {
+        return bits;
+    }
+
+    public String getDisplayText() {
+        return displayText;
+    }
+
+    public Boolean isFeatured() {
+        return featured;
+    }
+
+    public Boolean isPublic() {
+        return publicTemplate;
+    }
+
+    public String getTemplateName() {
+        return templateName;
+    }
+
+    public Long getOsTypeId() {
+        return osTypeId;
+    }
+
+    public Boolean isPasswordEnabled() {
+        return passwordEnabled;
+    }
+
+    public Boolean getRequiresHvm() {
+        return requiresHvm;
+    }
+
+    public Long getSnapshotId() {
+        return snapshotId;
+    }
+
+    public Long getVolumeId() {
+        return volumeId;
+    }
+
+    public Long getVmId() {
+        return vmId;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public String getTemplateTag() {
+        return templateTag;
+    }
+
+    public Map getDetails() {
+        if (details == null || details.isEmpty()) {
+            return null;
+        }
+
+        Collection paramsCollection = details.values();
+        Map params = (Map) (paramsCollection.toArray())[0];
+        return params;
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "template";
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Long volumeId = getVolumeId();
+        Long snapshotId = getSnapshotId();
+        Long accountId = null;
+        if (volumeId != null) {
+            Volume volume = _entityMgr.findById(Volume.class, volumeId);
+            if (volume != null) {
+                accountId = volume.getAccountId();
+            } else {
+                throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId);
+            }
+        } else {
+            Snapshot snapshot = _entityMgr.findById(Snapshot.class, snapshotId);
+            if (snapshot != null) {
+                accountId = snapshot.getAccountId();
+            } else {
+                throw new InvalidParameterValueException("Unable to find snapshot by id=" + snapshotId);
+            }
+        }
+
+        Account account = _accountService.getAccount(accountId);
+        //Can create templates for enabled projects/accounts only
+        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
+            Project project = _projectService.findByProjectAccountId(accountId);
+            if (project.getState() != Project.State.Active) {
+                PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the specified project id in state=" + project.getState() + " as it's no longer active");
+                ex.addProxyObject(project, project.getId(), "projectId");
+            }
+        } else if (account.getState() == Account.State.disabled) {
+            throw new PermissionDeniedException("The owner of template is disabled: " + account);
+        }
+
+        return accountId;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_TEMPLATE_CREATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "creating template: " + getTemplateName();
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Template;
+    }
+
+    private boolean isBareMetal() {
+        return (this.getVmId() != null && this.getUrl() != null);
+    }
+
+    @Override
+    public void create() throws ResourceAllocationException {
+        if (isBareMetal()) {
+            _bareMetalVmService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId()));
+            /*Baremetal creates template record after taking image proceeded, use vmId as entity id here*/
+            this.setEntityId(vmId);
+        } else {
+            VirtualMachineTemplate template = null;
+            template = _userVmService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId()));
+            if (template != null) {
+                this.setEntityId(template.getId());
+            } else {
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR,
+                "Failed to create a template");
+            }
+        }
+    }
+
+    @Override
+    public void execute() {
+        UserContext.current().setEventDetails("Template Id: "+getEntityId()+((getSnapshotId() == null) ? " from volume Id: " + getVolumeId() : " from snapshot Id: " + getSnapshotId()));
+        VirtualMachineTemplate template = null;
+        if (isBareMetal()) {
+            template = _bareMetalVmService.createPrivateTemplate(this);
+        } else {
+            template = _userVmService.createPrivateTemplate(this);
+        }
+
+        if (template != null){
+            List<TemplateResponse> templateResponses;
+            if (isBareMetal()) {
+                templateResponses = _responseGenerator.createTemplateResponses(template.getId(), vmId);
+            } else {
+                templateResponses = _responseGenerator.createTemplateResponses(template.getId(), snapshotId, volumeId, false);
+            }
+            TemplateResponse response = new TemplateResponse();
+            if (templateResponses != null && !templateResponses.isEmpty()) {
+                response = templateResponses.get(0);
+            }
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create private template");
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/template/DeleteTemplateCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/DeleteTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/DeleteTemplateCmd.java
new file mode 100644
index 0000000..26f3e84
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/template/DeleteTemplateCmd.java
@@ -0,0 +1,115 @@
+// 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.apache.cloudstack.api.command.user.template;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "deleteTemplate", responseObject=SuccessResponse.class, description="Deletes a template from the system. All virtual machines using the deleted template will not be affected.")
+public class DeleteTemplateCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(DeleteTemplateCmd.class.getName());
+    private static final String s_name = "deletetemplateresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = UserVmResponse.class,
+            required=true, description="the ID of the template")
+    private Long id;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
+            description="the ID of zone of the template")
+    private Long zoneId;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getStaticName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, getId());
+        if (template != null) {
+            return template.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_TEMPLATE_DELETE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "Deleting template " + getId();
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Template;
+    }
+
+    public Long getInstanceId() {
+        return getId();
+    }
+
+    @Override
+    public void execute(){
+        UserContext.current().setEventDetails("Template Id: "+getId());
+        boolean result = _templateService.deleteTemplate(this);
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete template");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java
new file mode 100644
index 0000000..521293c
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java
@@ -0,0 +1,136 @@
+// 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.apache.cloudstack.api.command.user.template;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.ExtractResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InternalErrorException;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "extractTemplate", description="Extracts a template", responseObject=ExtractResponse.class)
+public class ExtractTemplateCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(ExtractTemplateCmd.class.getName());
+
+    private static final String s_name = "extracttemplateresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = UserVmResponse.class,
+            required=true, description="the ID of the template")
+    private Long id;
+
+    @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required=false, description="the url to which the ISO would be extracted")
+    private String url;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
+            required=false, description="the ID of the zone where the ISO is originally located" )
+    private Long zoneId;
+
+    @Parameter(name=ApiConstants.MODE, type=CommandType.STRING, required=true, description="the mode of extraction - HTTP_DOWNLOAD or FTP_UPLOAD")
+    private String mode;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+    public String getMode() {
+        return mode;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getStaticName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, getId());
+        if (template != null) {
+            return template.getAccountId();
+        }
+
+        // invalid id, parent this command to SYSTEM so ERROR events are tracked
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_TEMPLATE_EXTRACT;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "extracting template: " + getId() + " from zone: " + getZoneId();
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Template;
+    }
+
+    public Long getInstanceId() {
+        return getId();
+    }
+
+    @Override
+    public void execute(){
+        try {
+            UserContext.current().setEventDetails(getEventDescription());
+            Long uploadId = _templateService.extract(this);
+            if (uploadId != null){
+                ExtractResponse response = _responseGenerator.createExtractResponse(uploadId, id, zoneId, getEntityOwnerId(), mode);
+                response.setResponseName(getCommandName());
+                this.setResponseObject(response);
+            } else {
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to extract template");
+            }
+        } catch (InternalErrorException ex) {
+            s_logger.warn("Exception: ", ex);
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatePermissionsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatePermissionsCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatePermissionsCmd.java
new file mode 100644
index 0000000..7446195
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatePermissionsCmd.java
@@ -0,0 +1,46 @@
+// Licensedname = "listTemplatePermissions",  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.apache.cloudstack.api.command.user.template;
+
+import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.TemplatePermissionsResponse;
+import org.apache.log4j.Logger;
+
+import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.template.VirtualMachineTemplate;
+
+@APICommand(name = "listTemplatePermissions", description="List template visibility and all accounts that have permissions to view this template.", responseObject=TemplatePermissionsResponse.class)
+public class ListTemplatePermissionsCmd extends BaseListTemplateOrIsoPermissionsCmd {
+    protected String getResponseName() {
+        return "listtemplatepermissionsresponse";
+    }
+
+    @Override
+    public String getMediaType() {
+        return "template";
+    }
+
+    @Override
+    protected Logger getLogger() {
+        return Logger.getLogger(ListTemplatePermissionsCmd.class.getName());
+    }
+
+    protected boolean templateIsCorrectType(VirtualMachineTemplate template) {
+        return !template.getFormat().equals(ImageFormat.ISO);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java
new file mode 100644
index 0000000..a1464cc
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java
@@ -0,0 +1,136 @@
+// 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.apache.cloudstack.api.command.user.template;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import com.cloud.storage.template.TemplateInfo;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.TemplateResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listTemplates", description="List all public, private, and privileged templates.", responseObject=TemplateResponse.class)
+public class ListTemplatesCmd extends BaseListTaggedResourcesCmd {
+    public static final Logger s_logger = Logger.getLogger(ListTemplatesCmd.class.getName());
+
+    private static final String s_name = "listtemplatesresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, description="the hypervisor for which to restrict the search")
+    private String hypervisor;
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=TemplateResponse.class,
+            description="the template ID")
+    private Long id;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the template name")
+    private String templateName;
+
+    @Parameter(name=ApiConstants.TEMPLATE_FILTER, type=CommandType.STRING, required=true, description="possible values are \"featured\", \"self\", \"self-executable\", \"executable\", and \"community\"." +
+                                                                                        "* featured-templates that are featured and are public" +
+                                                                                        "* self-templates that have been registered/created by the owner" +
+                                                                                        "* selfexecutable-templates that have been registered/created by the owner that can be used to deploy a new VM" +
+                                                                                        "* executable-all templates that can be used to deploy a new VM* community-templates that are public.")
+    private String templateFilter;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
+            description="list templates by zoneId")
+    private Long zoneId;
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getHypervisor() {
+        return hypervisor;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getTemplateName() {
+        return templateName;
+    }
+
+    public String getTemplateFilter() {
+        return templateFilter;
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+    public boolean listInReadyState() {
+
+        Account account = UserContext.current().getCaller();
+        // It is account specific if account is admin type and domainId and accountName are not null
+        boolean isAccountSpecific = (account == null || isAdmin(account.getType())) && (getAccountName() != null) && (getDomainId() != null);
+        // Show only those that are downloaded.
+        TemplateFilter templateFilter = TemplateFilter.valueOf(getTemplateFilter());
+        boolean onlyReady = (templateFilter == TemplateFilter.featured) || (templateFilter == TemplateFilter.selfexecutable) || (templateFilter == TemplateFilter.sharedexecutable)
+        || (templateFilter == TemplateFilter.executable && isAccountSpecific) || (templateFilter == TemplateFilter.community);
+        return onlyReady;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Template;
+    }
+
+    @Override
+    public void execute(){
+        Set<Pair<Long, Long>> templateZonePairSet = _mgr.listTemplates(this);
+
+        ListResponse<TemplateResponse> response = new ListResponse<TemplateResponse>();
+        List<TemplateResponse> templateResponses = new ArrayList<TemplateResponse>();
+
+        for (Pair<Long, Long> template : templateZonePairSet) {
+            List<TemplateResponse> responses = new ArrayList<TemplateResponse>();
+            responses = _responseGenerator.createTemplateResponses(template.first().longValue(), template.second(), listInReadyState());
+            templateResponses.addAll(responses);
+        }
+
+        response.setResponses(templateResponses);
+        response.setResponseName(getCommandName());
+        this.setResponseObject(response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
new file mode 100644
index 0000000..b3677b9
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
@@ -0,0 +1,243 @@
+// 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.apache.cloudstack.api.command.user.template;
+
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.GuestOSResponse;
+import org.apache.cloudstack.api.response.ProjectResponse;
+import org.apache.cloudstack.api.response.TemplateResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "registerTemplate", description="Registers an existing template into the CloudStack cloud. ", responseObject=TemplateResponse.class)
+public class RegisterTemplateCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(RegisterTemplateCmd.class.getName());
+
+    private static final String s_name = "registertemplateresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.BITS, type=CommandType.INTEGER, description="32 or 64 bits support. 64 by default")
+    private Integer bits;
+
+    @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, required=true, description="the display text of the template. This is usually used for display purposes.", length=4096)
+    private String displayText;
+
+    @Parameter(name=ApiConstants.FORMAT, type=CommandType.STRING, required=true, description="the format for the template. Possible values include QCOW2, RAW, and VHD.")
+    private String format;
+
+    @Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, required=true, description="the target hypervisor for the template")
+    private String hypervisor;
+
+    @Parameter(name=ApiConstants.IS_FEATURED, type=CommandType.BOOLEAN, description="true if this template is a featured template, false otherwise")
+    private Boolean featured;
+
+    @Parameter(name=ApiConstants.IS_PUBLIC, type=CommandType.BOOLEAN, description="true if the template is available to all accounts; default is true")
+    private Boolean publicTemplate;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="the name of the template")
+    private String templateName;
+
+    @Parameter(name=ApiConstants.OS_TYPE_ID, type=CommandType.UUID, entityType = GuestOSResponse.class,
+            required=true, description="the ID of the OS Type that best represents the OS of this template.")
+    private Long osTypeId;
+
+    @Parameter(name=ApiConstants.PASSWORD_ENABLED, type=CommandType.BOOLEAN, description="true if the template supports the password reset feature; default is false")
+    private Boolean passwordEnabled;
+
+    @Parameter(name=ApiConstants.SSHKEY_ENABLED, type=CommandType.BOOLEAN, description="true if the template supports the sshkey upload feature; default is false")
+    private Boolean sshKeyEnabled;
+
+    @Parameter(name=ApiConstants.IS_EXTRACTABLE, type=CommandType.BOOLEAN, description="true if the template or its derivatives are extractable; default is false")
+    private Boolean extractable;
+
+    @Parameter(name=ApiConstants.REQUIRES_HVM, type=CommandType.BOOLEAN, description="true if this template requires HVM")
+    private Boolean requiresHvm;
+
+    @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required=true, description="the URL of where the template is hosted. Possible URL include http:// and https://")
+    private String url;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
+            required=true, description="the ID of the zone the template is to be hosted on")
+    private Long zoneId;
+
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType = DomainResponse.class,
+            description="an optional domainId. If the account parameter is used, domainId must also be used.")
+    private Long domainId;
+
+    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="an optional accountName. Must be used with domainId.")
+    private String accountName;
+
+    @Parameter(name=ApiConstants.CHECKSUM, type=CommandType.STRING, description="the MD5 checksum value of this template")
+    private String checksum;
+
+    @Parameter(name=ApiConstants.TEMPLATE_TAG, type=CommandType.STRING, description="the tag for this template.")
+    private String templateTag;
+
+    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class,
+            description="Register template for the project")
+    private Long projectId;
+
+    @Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="Template details in key/value pairs.")
+    protected Map details;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Integer getBits() {
+        return bits;
+    }
+
+    public String getDisplayText() {
+        return displayText;
+    }
+
+    public String getFormat() {
+        return format;
+    }
+
+    public String getHypervisor() {
+        return hypervisor;
+    }
+
+    public Boolean isFeatured() {
+        return featured;
+    }
+
+    public Boolean isPublic() {
+        return publicTemplate;
+    }
+
+    public String getTemplateName() {
+        return templateName;
+    }
+
+    public Long getOsTypeId() {
+        return osTypeId;
+    }
+
+    public Boolean isPasswordEnabled() {
+        return passwordEnabled;
+    }
+
+    public Boolean isSshKeyEnabled() {
+        return sshKeyEnabled;
+    }
+
+    public Boolean isExtractable() {
+        return extractable;
+    }
+
+    public Boolean getRequiresHvm() {
+        return requiresHvm;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public String getChecksum() {
+        return checksum;
+    }
+
+    public String getTemplateTag() {
+        return templateTag;
+    }
+
+    public Map getDetails() {
+        if (details == null || details.isEmpty()) {
+            return null;
+        }
+
+        Collection paramsCollection = details.values();
+        Map params = (Map) (paramsCollection.toArray())[0];
+        return params;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Template;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
+        if (accountId == null) {
+            return UserContext.current().getCaller().getId();
+        }
+
+        return accountId;
+    }
+
+    @Override
+    public void execute() throws ResourceAllocationException{
+        try {
+            VirtualMachineTemplate template = _templateService.registerTemplate(this);
+            if (template != null){
+                ListResponse<TemplateResponse> response = new ListResponse<TemplateResponse>();
+                List<TemplateResponse> templateResponses = _responseGenerator.createTemplateResponses(template.getId(), zoneId, false);
+                response.setResponses(templateResponses);
+                response.setResponseName(getCommandName());
+                this.setResponseObject(response);
+            } else {
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to register template");
+            }
+        } catch (URISyntaxException ex1) {
+            s_logger.info(ex1);
+            throw new ServerApiException(BaseCmd.PARAM_ERROR, ex1.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java
new file mode 100644
index 0000000..01ea200
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java
@@ -0,0 +1,79 @@
+// 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.apache.cloudstack.api.command.user.template;
+
+import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.TemplateResponse;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.user.Account;
+
+@APICommand(name = "updateTemplate", description="Updates attributes of a template.", responseObject=TemplateResponse.class)
+public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd {
+    public static final Logger s_logger = Logger.getLogger(UpdateTemplateCmd.class.getName());
+    private static final String s_name = "updatetemplateresponse";
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public Boolean isBootable() {
+        return null;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @SuppressWarnings("unchecked")
+    public TemplateResponse getResponse() {
+       return null;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, getId());
+        if (template != null) {
+            return template.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public void execute(){
+        VirtualMachineTemplate result = _mgr.updateTemplate(this);
+        if (result != null) {
+            TemplateResponse response = _responseGenerator.createIsoResponse(result);
+            response.setObjectName("template");
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update template");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java
new file mode 100644
index 0000000..8f3e660
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java
@@ -0,0 +1,51 @@
+// 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.apache.cloudstack.api.command.user.template;
+
+import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.user.Account;
+
+@APICommand(name = "updateTemplatePermissions", responseObject=SuccessResponse.class, description="Updates a template visibility permissions. " +
+                                                                                        "A public template is visible to all accounts within the same domain. " +
+                                                                                        "A private template is visible only to the owner of the template. " +
+                                                                                        "A priviledged template is a private template with account permissions added. " +
+                                                                                        "Only accounts specified under the template permissions are visible to them.")
+public class UpdateTemplatePermissionsCmd extends BaseUpdateTemplateOrIsoPermissionsCmd {
+    protected String getResponseName() {
+        return "updatetemplatepermissionsresponse";
+    }
+
+    protected Logger getLogger() {
+        return Logger.getLogger(UpdateTemplatePermissionsCmd.class.getName());
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, getId());
+        if (template != null) {
+            return template.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+}