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

[6/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/securitygroup/AuthorizeSecurityGroupEgressCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java
new file mode 100644
index 0000000..acafcbe
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java
@@ -0,0 +1,223 @@
+// 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.securitygroup;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+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.DomainResponse;
+import org.apache.cloudstack.api.response.ProjectAccountResponse;
+import org.apache.cloudstack.api.response.SecurityGroupRuleResponse;
+import org.apache.cloudstack.api.response.SecurityGroupResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.network.security.SecurityRule;
+import com.cloud.user.UserContext;
+import com.cloud.utils.StringUtils;
+
+@APICommand(name = "authorizeSecurityGroupEgress", responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular egress rule for this security group", since="3.0.0")
+@SuppressWarnings("rawtypes")
+public class AuthorizeSecurityGroupEgressCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(AuthorizeSecurityGroupIngressCmd.class.getName());
+
+    private static final String s_name = "authorizesecuritygroupegressresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, description = "TCP is default. UDP is the other supported protocol")
+    private String protocol;
+
+    @Parameter(name = ApiConstants.START_PORT, type = CommandType.INTEGER, description = "start port for this egress rule")
+    private Integer startPort;
+
+    @Parameter(name = ApiConstants.END_PORT, type = CommandType.INTEGER, description = "end port for this egress rule")
+    private Integer endPort;
+
+    @Parameter(name = ApiConstants.ICMP_TYPE, type = CommandType.INTEGER, description = "type of the icmp message being sent")
+    private Integer icmpType;
+
+    @Parameter(name = ApiConstants.ICMP_CODE, type = CommandType.INTEGER, description = "error code for this icmp message")
+    private Integer icmpCode;
+
+    @Parameter(name=ApiConstants.CIDR_LIST, type=CommandType.LIST, collectionType=CommandType.STRING, description="the cidr list associated")
+    private List<String> cidrList;
+
+    @Parameter(name = ApiConstants.USER_SECURITY_GROUP_LIST, type = CommandType.MAP, description = "user to security group mapping")
+    private Map userSecurityGroupList;
+
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, description="an optional domainId for the security group. If the account parameter is used, domainId must also be used.", entityType = DomainResponse.class)
+    private Long domainId;
+
+    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="an optional account for the security group. Must be used with domainId.")
+    private String accountName;
+
+    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, description="an optional project of the security group", entityType=ProjectAccountResponse.class)
+    private Long projectId;
+
+    @Parameter(name=ApiConstants.SECURITY_GROUP_ID, type=CommandType.UUID, description="The ID of the security group. Mutually exclusive with securityGroupName parameter", entityType=SecurityGroupResponse.class)
+    private Long securityGroupId;
+
+    @Parameter(name=ApiConstants.SECURITY_GROUP_NAME, type=CommandType.STRING, description="The name of the security group. Mutually exclusive with securityGroupName parameter")
+    private String securityGroupName;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public List<String> getCidrList() {
+        return cidrList;
+    }
+
+    public Integer getEndPort() {
+        return endPort;
+    }
+
+    public Integer getIcmpCode() {
+        return icmpCode;
+    }
+
+    public Integer getIcmpType() {
+        return icmpType;
+    }
+
+    public Long getSecurityGroupId() {
+        if (securityGroupId != null && securityGroupName != null) {
+            throw new InvalidParameterValueException("securityGroupId and securityGroupName parameters are mutually exclusive");
+        }
+
+        if (securityGroupName != null) {
+            securityGroupId = _responseGenerator.getSecurityGroupId(securityGroupName, getEntityOwnerId());
+            if (securityGroupId == null) {
+                throw new InvalidParameterValueException("Unable to find security group " + securityGroupName + " for account id=" + getEntityOwnerId());
+            }
+            securityGroupName = null;
+        }
+
+        if (securityGroupId == null) {
+            throw new InvalidParameterValueException("Either securityGroupId or securityGroupName is required by authorizeSecurityGroupIngress command");
+        }
+
+        return securityGroupId;
+    }
+
+    public String getProtocol() {
+        if (protocol == null) {
+            return "all";
+        }
+        return protocol;
+    }
+
+    public Integer getStartPort() {
+        return startPort;
+    }
+
+    public Map getUserSecurityGroupList() {
+        return userSecurityGroupList;
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "securitygroup";
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
+        if (accountId == null) {
+            return UserContext.current().getCaller().getId();
+        }
+
+        return accountId;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_SECURITY_GROUP_AUTHORIZE_EGRESS;
+    }
+
+    @Override
+    public String getEventDescription() {
+        StringBuilder sb = new StringBuilder();
+        if (getUserSecurityGroupList() != null) {
+            sb.append("group list(group/account): ");
+            Collection userGroupCollection = getUserSecurityGroupList().values();
+            Iterator iter = userGroupCollection.iterator();
+
+            HashMap userGroup = (HashMap) iter.next();
+            String group = (String) userGroup.get("group");
+            String authorizedAccountName = (String) userGroup.get("account");
+            sb.append(group + "/" + authorizedAccountName);
+
+            while (iter.hasNext()) {
+                userGroup = (HashMap) iter.next();
+                group = (String) userGroup.get("group");
+                authorizedAccountName = (String) userGroup.get("account");
+                sb.append(", " + group + "/" + authorizedAccountName);
+            }
+        } else if (getCidrList() != null) {
+            sb.append("cidr list: ");
+            sb.append(StringUtils.join(getCidrList(), ", "));
+        } else {
+            sb.append("<error:  no egress parameters>");
+        }
+
+        return "authorizing egress to group: " + getSecurityGroupId() + " to " + sb.toString();
+    }
+
+    @Override
+    public void execute() {
+        List<? extends SecurityRule> egressRules = _securityGroupService.authorizeSecurityGroupEgress(this);
+        if (egressRules != null && !egressRules.isEmpty()) {
+            SecurityGroupResponse response = _responseGenerator.createSecurityGroupResponseFromSecurityGroupRule(egressRules);
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to authorize security group egress rule(s)");
+        }
+
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.SecurityGroup;
+    }
+
+    @Override
+    public Long getInstanceId() {
+        return getSecurityGroupId();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java
new file mode 100644
index 0000000..abd20fc
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java
@@ -0,0 +1,235 @@
+// 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.securitygroup;
+
+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.DomainResponse;
+import org.apache.cloudstack.api.response.ProjectAccountResponse;
+import org.apache.cloudstack.api.response.SecurityGroupResponse;
+import org.apache.cloudstack.api.response.SecurityGroupRuleResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.network.security.SecurityRule;
+import com.cloud.user.UserContext;
+import com.cloud.utils.StringUtils;
+import com.cloud.utils.net.NetUtils;
+
+@APICommand(name = "authorizeSecurityGroupIngress", responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular ingress rule for this security group")
+@SuppressWarnings("rawtypes")
+public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(AuthorizeSecurityGroupIngressCmd.class.getName());
+
+    private static final String s_name = "authorizesecuritygroupingressresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, description = "TCP is default. UDP is the other supported protocol")
+    private String protocol;
+
+    @Parameter(name = ApiConstants.START_PORT, type = CommandType.INTEGER, description = "start port for this ingress rule")
+    private Integer startPort;
+
+    @Parameter(name = ApiConstants.END_PORT, type = CommandType.INTEGER, description = "end port for this ingress rule")
+    private Integer endPort;
+
+    @Parameter(name = ApiConstants.ICMP_TYPE, type = CommandType.INTEGER, description = "type of the icmp message being sent")
+    private Integer icmpType;
+
+    @Parameter(name = ApiConstants.ICMP_CODE, type = CommandType.INTEGER, description = "error code for this icmp message")
+    private Integer icmpCode;
+
+    @Parameter(name=ApiConstants.CIDR_LIST, type=CommandType.LIST, collectionType=CommandType.STRING, description="the cidr list associated")
+    private List<String> cidrList;
+
+    @Parameter(name = ApiConstants.USER_SECURITY_GROUP_LIST, type = CommandType.MAP, description = "user to security group mapping")
+    private Map userSecurityGroupList;
+
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, description="an optional domainId for the security group. If the account parameter is used, domainId must also be used.", entityType = DomainResponse.class)
+    private Long domainId;
+
+    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="an optional account for the security group. Must be used with domainId.")
+    private String accountName;
+
+    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, description="an optional project of the security group", entityType=ProjectAccountResponse.class)
+    private Long projectId;
+
+    @Parameter(name=ApiConstants.SECURITY_GROUP_ID, type=CommandType.UUID, description="The ID of the security group. Mutually exclusive with securityGroupName parameter", entityType=SecurityGroupResponse.class)
+    private Long securityGroupId;
+
+    @Parameter(name=ApiConstants.SECURITY_GROUP_NAME, type=CommandType.STRING, description="The name of the security group. Mutually exclusive with securityGroupName parameter")
+    private String securityGroupName;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public List<String> getCidrList() {
+        return cidrList;
+    }
+
+    public Integer getEndPort() {
+        return endPort;
+    }
+
+    public Integer getIcmpCode() {
+        return icmpCode;
+    }
+
+    public Integer getIcmpType() {
+        return icmpType;
+    }
+
+    public Long getSecurityGroupId() {
+        if (securityGroupId != null && securityGroupName != null) {
+            throw new InvalidParameterValueException("securityGroupId and securityGroupName parameters are mutually exclusive");
+        }
+
+        if (securityGroupName != null) {
+            securityGroupId = _responseGenerator.getSecurityGroupId(securityGroupName, getEntityOwnerId());
+            if (securityGroupId == null) {
+                throw new InvalidParameterValueException("Unable to find security group " + securityGroupName + " for account id=" + getEntityOwnerId());
+            }
+            securityGroupName = null;
+        }
+
+        if (securityGroupId == null) {
+            throw new InvalidParameterValueException("Either securityGroupId or securityGroupName is required by authorizeSecurityGroupIngress command");
+        }
+
+        return securityGroupId;
+    }
+
+    public String getProtocol() {
+        if (protocol == null) {
+            return "all";
+        }
+        return protocol;
+    }
+
+    public Integer getStartPort() {
+        return startPort;
+    }
+
+    public Map getUserSecurityGroupList() {
+        return userSecurityGroupList;
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "securitygroup";
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Long accountId = finalyzeAccountId(accountName, domainId, projectId, true);
+        if (accountId == null) {
+            return UserContext.current().getCaller().getId();
+        }
+
+        return accountId;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_SECURITY_GROUP_AUTHORIZE_INGRESS;
+    }
+
+    @Override
+    public String getEventDescription() {
+        StringBuilder sb = new StringBuilder();
+        if (getUserSecurityGroupList() != null) {
+            sb.append("group list(group/account): ");
+            Collection userGroupCollection = getUserSecurityGroupList().values();
+            Iterator iter = userGroupCollection.iterator();
+
+            HashMap userGroup = (HashMap) iter.next();
+            String group = (String) userGroup.get("group");
+            String authorizedAccountName = (String) userGroup.get("account");
+            sb.append(group + "/" + authorizedAccountName);
+
+            while (iter.hasNext()) {
+                userGroup = (HashMap) iter.next();
+                group = (String) userGroup.get("group");
+                authorizedAccountName = (String) userGroup.get("account");
+                sb.append(", " + group + "/" + authorizedAccountName);
+            }
+        } else if (getCidrList() != null) {
+            sb.append("cidr list: ");
+            sb.append(StringUtils.join(getCidrList(), ", "));
+        } else {
+            sb.append("<error:  no ingress parameters>");
+        }
+
+        return "authorizing ingress to group: " + getSecurityGroupId() + " to " + sb.toString();
+    }
+
+    @Override
+    public void execute() {
+        if(cidrList != null){
+            for(String cidr : cidrList ){
+                if (!NetUtils.isValidCIDR(cidr)){
+                    throw new ServerApiException(BaseCmd.PARAM_ERROR,  cidr + " is an Invalid CIDR ");
+                }
+            }
+        }
+        List<? extends SecurityRule> ingressRules = _securityGroupService.authorizeSecurityGroupIngress(this);
+        if (ingressRules != null && !ingressRules.isEmpty()) {
+            SecurityGroupResponse response = _responseGenerator.createSecurityGroupResponseFromSecurityGroupRule(ingressRules);
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to authorize security group ingress rule(s)");
+        }
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.SecurityGroup;
+    }
+
+    @Override
+    public Long getInstanceId() {
+        return getSecurityGroupId();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java
new file mode 100644
index 0000000..c494355
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.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.securitygroup;
+
+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.ProjectAccountResponse;
+import org.apache.cloudstack.api.response.SecurityGroupResponse;
+import com.cloud.network.security.SecurityGroup;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "createSecurityGroup", responseObject = SecurityGroupResponse.class, description = "Creates a security group")
+public class CreateSecurityGroupCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(CreateSecurityGroupCmd.class.getName());
+
+    private static final String s_name = "createsecuritygroupresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional account for the security group. Must be used with domainId.")
+    private String accountName;
+
+    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "an optional domainId for the security group. If the account parameter is used, domainId must also be used.", entityType = DomainResponse.class)
+    private Long domainId;
+
+    @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "the description of the security group")
+    private String description;
+
+    @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the security group")
+    private String securityGroupName;
+
+    @Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, description = "Deploy vm for the project", entityType=ProjectAccountResponse.class)
+    private Long projectId;
+
+    // ///////////////////////////////////////////////////
+    // ///////////////// Accessors ///////////////////////
+    // ///////////////////////////////////////////////////
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public String getSecurityGroupName() {
+        return securityGroupName;
+    }
+
+    public Long getProjectId() {
+        return projectId;
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Account account = UserContext.current().getCaller();
+        if ((account == null) || isAdmin(account.getType())) {
+            if ((domainId != null) && (accountName != null)) {
+                Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
+                if (userAccount != null) {
+                    return userAccount.getId();
+                }
+            }
+        }
+
+        if (account != null) {
+            return account.getId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are
+// tracked
+    }
+
+    @Override
+    public void execute() {
+        SecurityGroup group = _securityGroupService.createSecurityGroup(this);
+        if (group != null) {
+            SecurityGroupResponse response = _responseGenerator.createSecurityGroupResponse(group);
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create security group");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java
new file mode 100644
index 0000000..15a0025
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java
@@ -0,0 +1,130 @@
+// 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.securitygroup;
+
+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.ProjectAccountResponse;
+import org.apache.cloudstack.api.response.SecurityGroupResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceInUseException;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "deleteSecurityGroup", description="Deletes security group", responseObject=SuccessResponse.class)
+public class DeleteSecurityGroupCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(DeleteSecurityGroupCmd.class.getName());
+    private static final String s_name = "deletesecuritygroupresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="the account of the security group. Must be specified with domain ID")
+    private String accountName;
+
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, description="the domain ID of account owning the security group", entityType=DomainResponse.class)
+    private Long domainId;
+
+    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, description="the project of the security group", entityType=ProjectAccountResponse.class)
+    private Long projectId;
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, description="The ID of the security group. Mutually exclusive with name parameter", entityType=SecurityGroupResponse.class)
+    private Long id;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="The ID of the security group. Mutually exclusive with id parameter")
+    private String name;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public Long getProjectId() {
+        return projectId;
+    }
+
+    public Long getId() {
+        if (id != null && name != null) {
+            throw new InvalidParameterValueException("name and id parameters are mutually exclusive");
+        }
+
+        if (name != null) {
+            id = _responseGenerator.getSecurityGroupId(name, getEntityOwnerId());
+            if (id == null) {
+                throw new InvalidParameterValueException("Unable to find security group by name " + name + " for the account id=" + getEntityOwnerId());
+            }
+        }
+
+        if (id == null) {
+            throw new InvalidParameterValueException("Either id or name parameter is requred by deleteSecurityGroup command");
+        }
+
+        return id;
+    }
+
+
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @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(){
+        try{
+            boolean result = _securityGroupService.deleteSecurityGroup(this);
+            if (result) {
+                SuccessResponse response = new SuccessResponse(getCommandName());
+                this.setResponseObject(response);
+            } else {
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete security group");
+            }
+        } catch (ResourceInUseException ex) {
+            s_logger.warn("Exception: ", ex);
+            throw new ServerApiException(BaseCmd.RESOURCE_IN_USE_ERROR, ex.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java
new file mode 100644
index 0000000..cf1ab84
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java
@@ -0,0 +1,85 @@
+// 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.securitygroup;
+
+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.SecurityGroupResponse;
+import org.apache.cloudstack.api.response.UserVmResponse;
+
+import com.cloud.async.AsyncJob;
+
+@APICommand(name = "listSecurityGroups", description="Lists security groups", responseObject=SecurityGroupResponse.class)
+public class ListSecurityGroupsCmd extends BaseListTaggedResourcesCmd {
+    public static final Logger s_logger = Logger.getLogger(ListSecurityGroupsCmd.class.getName());
+
+    private static final String s_name = "listsecuritygroupsresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.SECURITY_GROUP_NAME, type=CommandType.STRING, description="lists security groups by name")
+    private String securityGroupName;
+
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, description="lists security groups by virtual machine id", entityType=UserVmResponse.class)
+    private Long virtualMachineId;
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, description="list the security group by the id provided", entityType=SecurityGroupResponse.class)
+    private Long id;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+    public String getSecurityGroupName() {
+        return securityGroupName;
+    }
+
+    public Long getVirtualMachineId() {
+        return virtualMachineId;
+    }
+
+    public Long getId(){
+        return id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute(){
+        ListResponse<SecurityGroupResponse> response = _queryService.searchForSecurityGroups(this);
+        response.setResponseName(getCommandName());
+        this.setResponseObject(response);
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.SecurityGroup;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java
new file mode 100644
index 0000000..53d8fcf
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java
@@ -0,0 +1,104 @@
+// 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.securitygroup;
+
+import org.apache.cloudstack.api.*;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.SecurityGroupRuleResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.network.security.SecurityGroup;
+import com.cloud.user.Account;
+
+@APICommand(name = "revokeSecurityGroupEgress", responseObject = SuccessResponse.class, description = "Deletes a particular egress rule from this security group", since="3.0.0")
+public class RevokeSecurityGroupEgressCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(RevokeSecurityGroupEgressCmd.class.getName());
+
+    private static final String s_name = "revokesecuritygroupegress";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, required = true, description = "The ID of the egress rule", entityType=SecurityGroupRuleResponse.class)
+    private Long id;
+
+    // ///////////////////////////////////////////////////
+    // ///////////////// Accessors ///////////////////////
+    // ///////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "revokesecuritygroupegress";
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        SecurityGroup group = _entityMgr.findById(SecurityGroup.class, getId());
+        if (group != null) {
+            return group.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_SECURITY_GROUP_REVOKE_EGRESS;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "revoking egress rule id: " + getId();
+    }
+
+    @Override
+    public void execute() {
+        boolean result = _securityGroupService.revokeSecurityGroupEgress(this);
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to revoke security group egress rule");
+        }
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.SecurityGroup;
+    }
+
+    @Override
+    public Long getInstanceId() {
+        return getId();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java
new file mode 100644
index 0000000..1f56dee
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java
@@ -0,0 +1,108 @@
+// 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.securitygroup;
+
+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.SecurityGroupRuleResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.network.security.SecurityGroup;
+import com.cloud.user.Account;
+
+@APICommand(name = "revokeSecurityGroupIngress", responseObject = SuccessResponse.class, description = "Deletes a particular ingress rule from this security group")
+public class RevokeSecurityGroupIngressCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(RevokeSecurityGroupIngressCmd.class.getName());
+
+    private static final String s_name = "revokesecuritygroupingress";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, required = true, description = "The ID of the ingress rule", entityType=SecurityGroupRuleResponse.class)
+    private Long id;
+
+    // ///////////////////////////////////////////////////
+    // ///////////////// Accessors ///////////////////////
+    // ///////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "revokesecuritygroupingress";
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        SecurityGroup group = _entityMgr.findById(SecurityGroup.class, getId());
+        if (group != null) {
+            return group.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_SECURITY_GROUP_REVOKE_INGRESS;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "revoking ingress rule id: " + getId();
+    }
+
+    @Override
+    public void execute() {
+        boolean result = _securityGroupService.revokeSecurityGroupIngress(this);
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to revoke security group ingress rule");
+        }
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.SecurityGroup;
+    }
+
+    @Override
+    public Long getInstanceId() {
+        return getId();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
new file mode 100644
index 0000000..33469ac
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
@@ -0,0 +1,190 @@
+// 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.snapshot;
+
+import org.apache.cloudstack.api.*;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.SnapshotResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.SnapshotPolicyResponse;
+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.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "createSnapshot", description = "Creates an instant snapshot of a volume.", responseObject = SnapshotResponse.class)
+public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
+    public static final Logger s_logger = Logger.getLogger(CreateSnapshotCmd.class.getName());
+    private static final String s_name = "createsnapshotresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "The account of the snapshot. The account parameter must be used with the domainId parameter.")
+    private String accountName;
+
+    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class,
+            description = "The domain ID of the snapshot. If used with the account parameter, specifies a domain for the account associated with the disk volume.")
+    private Long domainId;
+
+    @Parameter(name = ApiConstants.VOLUME_ID, type = CommandType.UUID, entityType = VolumeResponse.class,
+            required = true, description = "The ID of the disk volume")
+    private Long volumeId;
+
+    @Parameter(name = ApiConstants.POLICY_ID, type = CommandType.UUID, entityType = SnapshotPolicyResponse.class,
+            description = "policy id of the snapshot, if this is null, then use MANUAL_POLICY.")
+    private Long policyId;
+
+    private String syncObjectType = BaseAsyncCmd.snapshotHostSyncObject;
+
+    // ///////////////////////////////////////////////////
+    // ///////////////// Accessors ///////////////////////
+    // ///////////////////////////////////////////////////
+
+    public String getEntityTable() {
+        return "snapshots";
+    }
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public Long getVolumeId() {
+        return volumeId;
+    }
+
+    public Long getPolicyId() {
+        if (policyId != null) {
+            return policyId;
+        } else {
+            return Snapshot.MANUAL_POLICY_ID;
+        }
+    }
+
+    private Long getHostId() {
+        Volume volume = _entityMgr.findById(Volume.class, getVolumeId());
+        if (volume == null) {
+            throw new InvalidParameterValueException("Unable to find volume by id");
+        }
+        return _snapshotService.getHostIdForSnapshotOperation(volume);
+    }
+
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "snapshot";
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+
+        Volume volume = _entityMgr.findById(Volume.class, getVolumeId());
+        if (volume == null) {
+            throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId);
+        }
+
+        Account account = _accountService.getAccount(volume.getAccountId());
+        //Can create templates for enabled projects/accounts only
+        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
+            Project project = _projectService.findByProjectAccountId(volume.getAccountId());
+            if (project.getState() != Project.State.Active) {
+                throw new PermissionDeniedException("Can't add resources to the project id=" + project.getId() + " in state=" + project.getState() + " as it's no longer active");
+            }
+        } else if (account.getState() == Account.State.disabled) {
+            throw new PermissionDeniedException("The owner of template is disabled: " + account);
+        }
+
+        return volume.getAccountId();
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_SNAPSHOT_CREATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "creating snapshot for volume: " + getVolumeId();
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Snapshot;
+    }
+
+    @Override
+    public void create() throws ResourceAllocationException {
+        Snapshot snapshot = _snapshotService.allocSnapshot(getVolumeId(), getPolicyId());
+        if (snapshot != null) {
+            this.setEntityId(snapshot.getId());
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create snapshot");
+        }
+    }
+
+    @Override
+    public void execute() {
+        UserContext.current().setEventDetails("Volume Id: "+getVolumeId());
+        Snapshot snapshot = _snapshotService.createSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()));
+        if (snapshot != null) {
+            SnapshotResponse response = _responseGenerator.createSnapshotResponse(snapshot);
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create snapshot due to an internal error creating snapshot for volume " + volumeId);
+        }
+    }
+
+
+    @Override
+    public String getSyncObjType() {
+        if (getSyncObjId() != null) {
+            return syncObjectType;
+        }
+        return null;
+    }
+
+    @Override
+    public Long getSyncObjId() {
+        if (getHostId() != null) {
+            return getHostId();
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java
new file mode 100644
index 0000000..cafb79e
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java
@@ -0,0 +1,132 @@
+// 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.snapshot;
+
+import org.apache.cloudstack.api.*;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.SnapshotPolicyResponse;
+import org.apache.cloudstack.api.response.VolumeResponse;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.projects.Project;
+import com.cloud.storage.Volume;
+import com.cloud.storage.snapshot.SnapshotPolicy;
+import com.cloud.user.Account;
+
+@APICommand(name = "createSnapshotPolicy", description="Creates a snapshot policy for the account.", responseObject=SnapshotPolicyResponse.class)
+public class CreateSnapshotPolicyCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(CreateSnapshotPolicyCmd.class.getName());
+
+    private static final String s_name = "createsnapshotpolicyresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.INTERVAL_TYPE, type=CommandType.STRING, required=true, description="valid values are HOURLY, DAILY, WEEKLY, and MONTHLY")
+    private String intervalType;
+
+    @Parameter(name=ApiConstants.MAX_SNAPS, type=CommandType.INTEGER, required=true, description="maximum number of snapshots to retain")
+    private Integer maxSnaps;
+
+    @Parameter(name=ApiConstants.SCHEDULE, type=CommandType.STRING, required=true, description="time the snapshot is scheduled to be taken. " +
+                                                                                    "Format is:" +
+                                                                                    "* if HOURLY, MM" +
+                                                                                    "* if DAILY, MM:HH" +
+                                                                                    "* if WEEKLY, MM:HH:DD (1-7)" +
+                                                                                    "* if MONTHLY, MM:HH:DD (1-28)")
+    private String schedule;
+
+    @Parameter(name=ApiConstants.TIMEZONE, type=CommandType.STRING, required=true, description="Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
+    private String timezone;
+
+    @Parameter(name=ApiConstants.VOLUME_ID, type=CommandType.UUID, entityType = VolumeResponse.class,
+            required=true, description="the ID of the disk volume")
+    private Long volumeId;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getIntervalType() {
+        return intervalType;
+    }
+
+    public Integer getMaxSnaps() {
+        return maxSnaps;
+    }
+
+    public String getSchedule() {
+        return schedule;
+    }
+
+    public String getTimezone() {
+        return timezone;
+    }
+
+    public Long getVolumeId() {
+        return volumeId;
+    }
+
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Volume volume = _entityMgr.findById(Volume.class, getVolumeId());
+        if (volume == null) {
+            throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId);
+        }
+
+        Account account = _accountService.getAccount(volume.getAccountId());
+        //Can create templates for enabled projects/accounts only
+        if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
+            Project project = _projectService.findByProjectAccountId(volume.getAccountId());
+            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");
+                throw ex;
+            }
+        } else if (account.getState() == Account.State.disabled) {
+            throw new PermissionDeniedException("The owner of template is disabled: " + account);
+        }
+
+        return volume.getAccountId();
+    }
+
+    @Override
+    public void execute(){
+        SnapshotPolicy result = _snapshotService.createPolicy(this, _accountService.getAccount(getEntityOwnerId()));
+        if (result != null) {
+            SnapshotPolicyResponse response = _responseGenerator.createSnapshotPolicyResponse(result);
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create snapshot policy");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java
new file mode 100644
index 0000000..6def873
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java
@@ -0,0 +1,100 @@
+// 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.snapshot;
+
+import org.apache.cloudstack.api.*;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.SnapshotResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.storage.Snapshot;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "deleteSnapshot", description="Deletes a snapshot of a disk volume.", responseObject=SuccessResponse.class)
+public class DeleteSnapshotCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(DeleteSnapshotCmd.class.getName());
+    private static final String s_name = "deletesnapshotresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = SnapshotResponse.class,
+            required=true, description="The ID of the snapshot")
+    private Long id;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Snapshot snapshot = _entityMgr.findById(Snapshot.class, getId());
+        if (snapshot != null) {
+            return snapshot.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_SNAPSHOT_DELETE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "deleting snapshot: " + getId();
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Snapshot;
+    }
+
+    public Long getInstanceId() {
+        return getId();
+    }
+
+    @Override
+    public void execute(){
+        UserContext.current().setEventDetails("Snapshot Id: "+getId());
+        boolean result = _snapshotService.deleteSnapshot(getId());
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete snapshot");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotPoliciesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotPoliciesCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotPoliciesCmd.java
new file mode 100644
index 0000000..17f28d9
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotPoliciesCmd.java
@@ -0,0 +1,86 @@
+// 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.snapshot;
+
+import java.util.List;
+
+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.SnapshotPolicyResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.user.Account;
+
+@APICommand(name = "deleteSnapshotPolicies", description="Deletes snapshot policies for the account.", responseObject=SuccessResponse.class)
+public class DeleteSnapshotPoliciesCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(DeleteSnapshotPoliciesCmd.class.getName());
+
+    private static final String s_name = "deletesnapshotpoliciesresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = SnapshotPolicyResponse.class,
+            description="the Id of the snapshot policy")
+    private Long id;
+
+    @Parameter(name=ApiConstants.IDS, type=CommandType.LIST, collectionType=CommandType.UUID, entityType = SnapshotPolicyResponse.class,
+            description="list of snapshots policy IDs separated by comma")
+    private List<Long> ids;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public List<Long> getIds() {
+        return ids;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public void execute(){
+        boolean result = _snapshotService.deleteSnapshotPolicies(this);
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete snapshot policy");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotPoliciesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotPoliciesCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotPoliciesCmd.java
new file mode 100644
index 0000000..647c503
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotPoliciesCmd.java
@@ -0,0 +1,78 @@
+// 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.snapshot;
+
+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.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.SnapshotPolicyResponse;
+import org.apache.cloudstack.api.response.VolumeResponse;
+import com.cloud.storage.snapshot.SnapshotPolicy;
+
+@APICommand(name = "listSnapshotPolicies", description="Lists snapshot policies.", responseObject=SnapshotPolicyResponse.class)
+public class ListSnapshotPoliciesCmd extends BaseListCmd {
+    public static final Logger s_logger = Logger.getLogger(ListSnapshotPoliciesCmd.class.getName());
+
+    private static final String s_name = "listsnapshotpoliciesresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.VOLUME_ID, type=CommandType.UUID, entityType = VolumeResponse.class,
+            required=true, description="the ID of the disk volume")
+    private Long volumeId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getVolumeId() {
+        return volumeId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute(){
+        List<? extends SnapshotPolicy> result = _snapshotService.listPoliciesforVolume(this);
+        ListResponse<SnapshotPolicyResponse> response = new ListResponse<SnapshotPolicyResponse>();
+        List<SnapshotPolicyResponse> policyResponses = new ArrayList<SnapshotPolicyResponse>();
+        for (SnapshotPolicy policy : result) {
+            SnapshotPolicyResponse policyResponse = _responseGenerator.createSnapshotPolicyResponse(policy);
+            policyResponse.setObjectName("snapshotpolicy");
+            policyResponses.add(policyResponse);
+        }
+        response.setResponses(policyResponses);
+        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/snapshot/ListSnapshotsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java
new file mode 100644
index 0000000..5c6e79c
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java
@@ -0,0 +1,114 @@
+// 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.snapshot;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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.SnapshotResponse;
+import org.apache.cloudstack.api.response.VolumeResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.storage.Snapshot;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listSnapshots", description="Lists all available snapshots for the account.", responseObject=SnapshotResponse.class)
+public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd {
+    public static final Logger s_logger = Logger.getLogger(ListSnapshotsCmd.class.getName());
+
+    private static final String s_name = "listsnapshotsresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = SnapshotResponse.class,
+            description="lists snapshot by snapshot ID")
+    private Long id;
+
+    @Parameter(name=ApiConstants.INTERVAL_TYPE, type=CommandType.STRING, description="valid values are HOURLY, DAILY, WEEKLY, and MONTHLY.")
+    private String intervalType;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="lists snapshot by snapshot name")
+    private String snapshotName;
+
+    @Parameter(name=ApiConstants.SNAPSHOT_TYPE, type=CommandType.STRING, description="valid values are MANUAL or RECURRING.")
+    private String snapshotType;
+
+    @Parameter(name=ApiConstants.VOLUME_ID, type=CommandType.UUID, entityType = VolumeResponse.class,
+            description="the ID of the disk volume")
+    private Long volumeId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getIntervalType() {
+        return intervalType;
+    }
+
+    public String getSnapshotName() {
+        return snapshotName;
+    }
+
+    public String getSnapshotType() {
+        return snapshotType;
+    }
+
+    public Long getVolumeId() {
+        return volumeId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Snapshot;
+    }
+
+    @Override
+    public void execute(){
+        Pair<List<? extends Snapshot>, Integer> result = _snapshotService.listSnapshots(this);
+        ListResponse<SnapshotResponse> response = new ListResponse<SnapshotResponse>();
+        List<SnapshotResponse> snapshotResponses = new ArrayList<SnapshotResponse>();
+        for (Snapshot snapshot : result.first()) {
+            SnapshotResponse snapshotResponse = _responseGenerator.createSnapshotResponse(snapshot);
+            snapshotResponse.setObjectName("snapshot");
+            snapshotResponses.add(snapshotResponse);
+        }
+        response.setResponses(snapshotResponses, result.second());
+        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/ssh/CreateSSHKeyPairCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java
new file mode 100644
index 0000000..bade857
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java
@@ -0,0 +1,103 @@
+// 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.cloudstack.api.APICommand;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+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 = "createSSHKeyPair", description="Create a new keypair and returns the private key", responseObject=SSHKeyPairResponse.class)
+public class CreateSSHKeyPairCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(CreateSSHKeyPairCmd.class.getName());
+    private static final String s_name = "createsshkeypairresponse";
+
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="Name of the keypair")
+    private String name;
+
+    //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 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 r = _mgr.createSSHKeyPair(this);
+        SSHKeyPairResponse response = new SSHKeyPairResponse(r.getName(), r.getFingerprint(), r.getPrivateKey());
+        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/ssh/DeleteSSHKeyPairCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java
new file mode 100644
index 0000000..9b6d403
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java
@@ -0,0 +1,109 @@
+// 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.SuccessResponse;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "deleteSSHKeyPair", description="Deletes a keypair by name", responseObject=SuccessResponse.class)
+public class DeleteSSHKeyPairCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(CreateSSHKeyPairCmd.class.getName());
+    private static final String s_name = "deletesshkeypairresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="Name of the keypair")
+    private String name;
+
+    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="the account associated with the keypair. Must be used with the domainId parameter.")
+    private String accountName;
+
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType = DomainResponse.class,
+            description="the domain ID associated with the keypair")
+    private Long domainId;
+
+    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class,
+            description="the project associated with keypair")
+    private Long projectId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getName() {
+        return name;
+    }
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public Long getProjectId() {
+        return projectId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public void execute() {
+        boolean result = _mgr.deleteSSHKeyPair(this);
+        SuccessResponse response = new SuccessResponse(getCommandName());
+        response.setSuccess(result);
+        this.setResponseObject(response);
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Account account = UserContext.current().getCaller();
+        if ((account == null) || isAdmin(account.getType())) {
+            if ((domainId != null) && (accountName != null)) {
+                Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
+                if (userAccount != null) {
+                    return userAccount.getId();
+                }
+            }
+        }
+
+        if (account != null) {
+            return account.getId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+}