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

[10/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/event/ListEventTypesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/event/ListEventTypesCmd.java b/api/src/org/apache/cloudstack/api/command/user/event/ListEventTypesCmd.java
new file mode 100644
index 0000000..4c432f3
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/event/ListEventTypesCmd.java
@@ -0,0 +1,60 @@
+// 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.event;
+
+import java.util.ArrayList;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.response.EventTypeResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import com.cloud.user.Account;
+
+@APICommand(name = "listEventTypes", description = "List Event Types", responseObject = EventTypeResponse.class)
+public class ListEventTypesCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(ListEventTypesCmd.class.getName());
+    private static final String s_name = "listeventtypesresponse";
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public void execute() {
+        String[] result = _mgr.listEventTypes();
+        ListResponse<EventTypeResponse> response = new ListResponse<EventTypeResponse>();
+        ArrayList<EventTypeResponse> responses = new ArrayList<EventTypeResponse>();
+        if (result != null) {
+            for (String eventType : result) {
+                EventTypeResponse eventTypeResponse = new EventTypeResponse();
+                eventTypeResponse.setName(eventType);
+                eventTypeResponse.setObjectName("eventtype");
+                responses.add(eventTypeResponse);
+            }
+        }
+        response.setResponses(responses);
+        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/event/ListEventsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java b/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java
new file mode 100644
index 0000000..94205d1
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.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.event;
+
+import java.util.Date;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.EventResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+
+@APICommand(name = "listEvents", description="A command to list events.", responseObject=EventResponse.class)
+public class ListEventsCmd extends BaseListProjectAndAccountResourcesCmd {
+    public static final Logger s_logger = Logger.getLogger(ListEventsCmd.class.getName());
+
+    private static final String s_name = "listeventsresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = EventResponse.class,
+            description="the ID of the event")
+    private Long id;
+
+    @Parameter(name=ApiConstants.DURATION, type=CommandType.INTEGER, description="the duration of the event")
+    private Integer duration;
+
+    @Parameter(name=ApiConstants.END_DATE, type=CommandType.DATE, description="the end date range of the list you want to retrieve (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\")")
+    private Date endDate;
+
+    @Parameter(name=ApiConstants.ENTRY_TIME, type=CommandType.INTEGER, description="the time the event was entered")
+    private Integer entryTime;
+
+    @Parameter(name=ApiConstants.LEVEL, type=CommandType.STRING, description="the event level (INFO, WARN, ERROR)")
+    private String level;
+
+    @Parameter(name=ApiConstants.START_DATE, type=CommandType.DATE, description="the start date range of the list you want to retrieve (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\")")
+    private Date startDate;
+
+    @Parameter(name=ApiConstants.TYPE, type=CommandType.STRING, description="the event type (see event types)")
+    private String type;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public Integer getDuration() {
+        return duration;
+    }
+
+    public Date getEndDate() {
+        return endDate;
+    }
+
+    public Integer getEntryTime() {
+        return entryTime;
+    }
+
+    public String getLevel() {
+        return level;
+    }
+
+    public Date getStartDate() {
+        return startDate;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute(){
+
+        ListResponse<EventResponse> response = _queryService.searchForEvents(this);
+        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/firewall/CreateFirewallRuleCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java
new file mode 100644
index 0000000..803301f
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java
@@ -0,0 +1,332 @@
+// 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.firewall;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cloudstack.api.response.IPAddressResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseAsyncCreateCmd;
+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.FirewallResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.IpAddress;
+import com.cloud.network.rules.FirewallRule;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+import com.cloud.utils.net.NetUtils;
+
+@APICommand(name = "createFirewallRule", description = "Creates a firewall rule for a given ip address", responseObject = FirewallResponse.class)
+public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements FirewallRule {
+    public static final Logger s_logger = Logger.getLogger(CreateFirewallRuleCmd.class.getName());
+
+    private static final String s_name = "createfirewallruleresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.IP_ADDRESS_ID, type = CommandType.UUID, entityType = IPAddressResponse.class,
+            required=true, description = "the IP address id of the port forwarding rule")
+    private Long ipAddressId;
+
+    @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, required = true, description = "the protocol for the firewall rule. Valid values are TCP/UDP/ICMP.")
+    private String protocol;
+
+    @Parameter(name = ApiConstants.START_PORT, type = CommandType.INTEGER, description = "the starting port of firewall rule")
+    private Integer publicStartPort;
+
+    @Parameter(name = ApiConstants.END_PORT, type = CommandType.INTEGER, description = "the ending port of firewall rule")
+    private Integer publicEndPort;
+
+    @Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
+    private List<String> cidrlist;
+
+    @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.TYPE, type = CommandType.STRING, description = "type of firewallrule: system/user")
+    private String type;
+
+    // ///////////////////////////////////////////////////
+    // ///////////////// Accessors ///////////////////////
+    // ///////////////////////////////////////////////////
+
+    public String getEntityTable() {
+        return "firewall_rules";
+    }
+
+    public Long getIpAddressId() {
+        return ipAddressId;
+    }
+
+    @Override
+    public String getProtocol() {
+        return protocol.trim();
+    }
+
+    public List<String> getSourceCidrList() {
+        if (cidrlist != null) {
+            return cidrlist;
+        } else {
+            List<String> oneCidrList = new ArrayList<String>();
+            oneCidrList.add(NetUtils.ALL_CIDRS);
+            return oneCidrList;
+        }
+
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public void setSourceCidrList(List<String> cidrs){
+        cidrlist = cidrs;
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException {
+        UserContext callerContext = UserContext.current();
+        boolean success = false;
+        FirewallRule rule = _entityMgr.findById(FirewallRule.class, getEntityId());
+        try {
+            UserContext.current().setEventDetails("Rule Id: " + getEntityId());
+            success = _firewallService.applyFirewallRules(rule.getSourceIpAddressId(), callerContext.getCaller());
+
+            // State is different after the rule is applied, so get new object here
+            rule = _entityMgr.findById(FirewallRule.class, getEntityId());
+            FirewallResponse fwResponse = new FirewallResponse();
+            if (rule != null) {
+                fwResponse = _responseGenerator.createFirewallResponse(rule);
+                setResponseObject(fwResponse);
+            }
+            fwResponse.setResponseName(getCommandName());
+        } finally {
+            if (!success || rule == null) {
+                _firewallService.revokeFirewallRule(getEntityId(), true);
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create firewall rule");
+            }
+        }
+    }
+
+    @Override
+    public long getId() {
+        throw new UnsupportedOperationException("database id can only provided by VO objects");
+    }
+
+    @Override
+    public String getXid() {
+        // FIXME: We should allow for end user to specify Xid.
+        return null;
+    }
+
+
+    @Override
+    public String getUuid() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Long getSourceIpAddressId() {
+        return ipAddressId;
+    }
+
+    @Override
+    public Integer getSourcePortStart() {
+        if (publicStartPort != null) {
+            return publicStartPort.intValue();
+        }
+        return null;
+    }
+
+    @Override
+    public Integer getSourcePortEnd() {
+        if (publicEndPort == null) {
+            if (publicStartPort != null) {
+                return publicStartPort.intValue();
+            }
+        } else {
+            return publicEndPort.intValue();
+        }
+
+        return null;
+    }
+
+    @Override
+    public Purpose getPurpose() {
+        return Purpose.Firewall;
+    }
+
+    @Override
+    public State getState() {
+        throw new UnsupportedOperationException("Should never call me to find the state");
+    }
+
+    @Override
+    public long getNetworkId() {
+        IpAddress ip = _entityMgr.findById(IpAddress.class, getIpAddressId());
+        Long ntwkId = null;
+
+        if (ip.getAssociatedWithNetworkId() != null) {
+            ntwkId = ip.getAssociatedWithNetworkId();
+        }
+
+        if (ntwkId == null) {
+            throw new InvalidParameterValueException("Unable to create firewall rule for the ipAddress id=" + ipAddressId +
+                    " as ip is not associated with any network and no networkId is passed in");
+        }
+        return ntwkId;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Account account = UserContext.current().getCaller();
+
+        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 long getDomainId() {
+        IpAddress ip = _networkService.getIp(ipAddressId);
+        return ip.getDomainId();
+    }
+
+    @Override
+    public void create() {
+        if (getSourceCidrList() != null) {
+            for (String cidr: getSourceCidrList()){
+                if (!NetUtils.isValidCIDR(cidr)){
+                    throw new ServerApiException(BaseCmd.PARAM_ERROR, "Source cidrs formatting error " + cidr);
+                }
+            }
+        }
+
+        try {
+            FirewallRule result = _firewallService.createFirewallRule(this);
+            setEntityId(result.getId());
+        } catch (NetworkRuleConflictException ex) {
+            s_logger.info("Network rule conflict: " + ex.getMessage());
+            s_logger.trace("Network Rule Conflict: ", ex);
+            throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage());
+        }
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_FIREWALL_OPEN;
+    }
+
+    @Override
+    public String getEventDescription() {
+        IpAddress ip = _networkService.getIp(ipAddressId);
+        return ("Createing firewall rule for Ip: " + ip.getAddress() + " for protocol:" + this.getProtocol());
+    }
+
+    @Override
+    public long getAccountId() {
+        IpAddress ip = _networkService.getIp(ipAddressId);
+        return ip.getAccountId();
+    }
+
+    @Override
+    public String getSyncObjType() {
+        return BaseAsyncCmd.networkSyncObject;
+    }
+
+    @Override
+    public Long getSyncObjId() {
+        return getIp().getAssociatedWithNetworkId();
+    }
+
+    private IpAddress getIp() {
+        IpAddress ip = _networkService.getIp(ipAddressId);
+        if (ip == null) {
+            throw new InvalidParameterValueException("Unable to find ip address by id " + ipAddressId);
+        }
+        return ip;
+    }
+
+    @Override
+    public Integer getIcmpCode() {
+        if (icmpCode != null) {
+            return icmpCode;
+        } else if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO)) {
+            return -1;
+        }
+        return null;
+    }
+
+    @Override
+    public Integer getIcmpType() {
+        if (icmpType != null) {
+            return icmpType;
+        } else if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO)) {
+                return -1;
+
+        }
+        return null;
+    }
+
+    @Override
+    public Long getRelated() {
+        return null;
+    }
+
+    @Override
+    public FirewallRuleType getType() {
+        if (type != null && type.equalsIgnoreCase("system")) {
+            return FirewallRuleType.System;
+        } else {
+            return FirewallRuleType.User;
+        }
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.FirewallRule;
+    }
+
+    @Override
+    public TrafficType getTrafficType() {
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java
new file mode 100644
index 0000000..ecccf03
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java
@@ -0,0 +1,376 @@
+// 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.firewall;
+
+import java.util.List;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.IPAddressResponse;
+import org.apache.cloudstack.api.response.NetworkResponse;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.FirewallRuleResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.IpAddress;
+import com.cloud.network.rules.PortForwardingRule;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+import com.cloud.utils.net.Ip;
+
+@APICommand(name = "createPortForwardingRule", description = "Creates a port forwarding rule", responseObject = FirewallRuleResponse.class)
+public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements PortForwardingRule {
+    public static final Logger s_logger = Logger.getLogger(CreatePortForwardingRuleCmd.class.getName());
+
+    private static final String s_name = "createportforwardingruleresponse";
+
+    // ///////////////////////////////////////////////////
+    // ////////////// API parameters /////////////////////
+    // ///////////////////////////////////////////////////
+
+    @Parameter(name = ApiConstants.IP_ADDRESS_ID, type = CommandType.UUID, entityType = IPAddressResponse.class,
+            required = true,
+    description = "the IP address id of the port forwarding rule")
+    private Long ipAddressId;
+
+    @Parameter(name = ApiConstants.PRIVATE_START_PORT, type = CommandType.INTEGER, required = true,
+            description = "the starting port of port forwarding rule's private port range")
+    private Integer privateStartPort;
+
+    @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, required = true,
+            description = "the protocol for the port fowarding rule. Valid values are TCP or UDP.")
+    private String protocol;
+
+    @Parameter(name = ApiConstants.PRIVATE_END_PORT, type = CommandType.INTEGER, required = false, description = "the ending port of port forwarding rule's private port range")
+    private Integer privateEndPort;
+
+    @Parameter(name = ApiConstants.PUBLIC_START_PORT, type = CommandType.INTEGER, required = true,
+            description = "the starting port of port forwarding rule's public port range")
+    private Integer publicStartPort;
+
+    @Parameter(name = ApiConstants.PUBLIC_END_PORT, type = CommandType.INTEGER, required = false, description = "the ending port of port forwarding rule's private port range")
+    private Integer publicEndPort;
+
+    @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class,
+            required = true,
+                description = "the ID of the virtual machine for the port forwarding rule")
+    private Long virtualMachineId;
+
+    @Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING,
+            description = "the cidr list to forward traffic from")
+    private List<String> cidrlist;
+
+    @Parameter(name = ApiConstants.OPEN_FIREWALL, type = CommandType.BOOLEAN,
+            description = "if true, firewall rule for source/end pubic port is automatically created; " +
+                    "if false - firewall rule has to be created explicitely. If not specified 1) defaulted to false when PF" +
+                    " rule is being created for VPC guest network 2) in all other cases defaulted to true")
+    private Boolean openFirewall;
+
+    @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.UUID, entityType = NetworkResponse.class,
+            description="The network of the vm the Port Forwarding rule will be created for. " +
+                "Required when public Ip address is not associated with any Guest network yet (VPC case)")
+    private Long networkId;
+
+    // ///////////////////////////////////////////////////
+    // ///////////////// Accessors ///////////////////////
+    // ///////////////////////////////////////////////////
+
+    public String getEntityTable() {
+        return "firewall_rules";
+    }
+
+    public Long getIpAddressId() {
+        return ipAddressId;
+    }
+
+    @Override
+    public String getProtocol() {
+        return protocol.trim();
+    }
+
+    @Override
+    public long getVirtualMachineId() {
+        return virtualMachineId;
+    }
+
+    public List<String> getSourceCidrList() {
+        if (cidrlist != null) {
+            throw new InvalidParameterValueException("Parameter cidrList is deprecated; if you need to open firewall " +
+                    "rule for the specific cidr, please refer to createFirewallRule command");
+        }
+        return null;
+    }
+
+    public Boolean getOpenFirewall() {
+        boolean isVpc = getVpcId() == null ? false : true;
+        if (openFirewall != null) {
+            if (isVpc && openFirewall) {
+                throw new InvalidParameterValueException("Can't have openFirewall=true when IP address belongs to VPC");
+            }
+            return openFirewall;
+        } else {
+            if (isVpc) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private Long getVpcId() {
+        if (ipAddressId != null) {
+            IpAddress ipAddr = _networkService.getIp(ipAddressId);
+            if (ipAddr == null || !ipAddr.readyToUse()) {
+                throw new InvalidParameterValueException("Unable to create PF rule, invalid IP address id " + ipAddr.getId());
+            } else {
+                return ipAddr.getVpcId();
+            }
+        }
+        return null;
+    }
+
+    // ///////////////////////////////////////////////////
+    // ///////////// API Implementation///////////////////
+    // ///////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+
+    @Override
+    public void execute() throws ResourceUnavailableException {
+        UserContext callerContext = UserContext.current();
+        boolean success = true;
+        PortForwardingRule rule = null;
+        try {
+            UserContext.current().setEventDetails("Rule Id: " + getEntityId());
+
+            if (getOpenFirewall()) {
+                success = success && _firewallService.applyFirewallRules(ipAddressId, callerContext.getCaller());
+            }
+
+            success = success && _rulesService.applyPortForwardingRules(ipAddressId, callerContext.getCaller());
+
+            // State is different after the rule is applied, so get new object here
+            rule = _entityMgr.findById(PortForwardingRule.class, getEntityId());
+            FirewallRuleResponse fwResponse = new FirewallRuleResponse();
+            if (rule != null) {
+                fwResponse = _responseGenerator.createPortForwardingRuleResponse(rule);
+                setResponseObject(fwResponse);
+            }
+            fwResponse.setResponseName(getCommandName());
+        } finally {
+            if (!success || rule == null) {
+
+                if (getOpenFirewall()) {
+                    _firewallService.revokeRelatedFirewallRule(getEntityId(), true);
+                }
+
+                _rulesService.revokePortForwardingRule(getEntityId(), true);
+
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to apply port forwarding rule");
+            }
+        }
+    }
+
+    @Override
+    public long getId() {
+        throw new UnsupportedOperationException("database id can only provided by VO objects");
+    }
+
+    @Override
+    public String getXid() {
+        // FIXME: We should allow for end user to specify Xid.
+        return null;
+    }
+
+
+    @Override
+    public String getUuid() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Long getSourceIpAddressId() {
+        return ipAddressId;
+    }
+
+    @Override
+    public Integer getSourcePortStart() {
+        return publicStartPort.intValue();
+    }
+
+    @Override
+    public Integer getSourcePortEnd() {
+        return (publicEndPort == null)? publicStartPort.intValue() : publicEndPort.intValue();
+    }
+
+    @Override
+    public Purpose getPurpose() {
+        return Purpose.PortForwarding;
+    }
+
+    @Override
+    public State getState() {
+        throw new UnsupportedOperationException("Should never call me to find the state");
+    }
+
+    @Override
+    public long getNetworkId() {
+        IpAddress ip = _entityMgr.findById(IpAddress.class, getIpAddressId());
+        Long ntwkId = null;
+
+        if (ip.getAssociatedWithNetworkId() != null) {
+            ntwkId = ip.getAssociatedWithNetworkId();
+        } else {
+            ntwkId = networkId;
+        }
+        if (ntwkId == null) {
+            throw new InvalidParameterValueException("Unable to create port forwarding rule for the ipAddress id=" + ipAddressId +
+                    " as ip is not associated with any network and no networkId is passed in");
+        }
+        return ntwkId;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Account account = UserContext.current().getCaller();
+
+        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 long getDomainId() {
+        IpAddress ip = _networkService.getIp(ipAddressId);
+        return ip.getDomainId();
+    }
+
+    @Override
+    public Ip getDestinationIpAddress() {
+        return null;
+    }
+
+    @Override
+    public void setDestinationIpAddress(Ip destinationIpAddress) {
+        return;
+    }
+
+    @Override
+    public int getDestinationPortStart() {
+        return privateStartPort.intValue();
+    }
+
+    @Override
+    public int getDestinationPortEnd() {
+        return (privateEndPort == null)? privateStartPort.intValue() : privateEndPort.intValue();
+    }
+
+    @Override
+    public void create() {
+        // cidr list parameter is deprecated
+        if (cidrlist != null) {
+            throw new InvalidParameterValueException("Parameter cidrList is deprecated; if you need to open firewall rule for the specific cidr, please refer to createFirewallRule command");
+        }
+
+        try {
+            PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId, getOpenFirewall());
+            setEntityId(result.getId());
+        } catch (NetworkRuleConflictException ex) {
+            s_logger.info("Network rule conflict: " , ex);
+            s_logger.trace("Network Rule Conflict: ", ex);
+            throw new ServerApiException(BaseCmd.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage());
+        }
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_NET_RULE_ADD;
+    }
+
+    @Override
+    public String getEventDescription() {
+        IpAddress ip = _networkService.getIp(ipAddressId);
+        return ("Applying port forwarding  rule for Ip: " + ip.getAddress() + " with virtual machine:" + virtualMachineId);
+    }
+
+    @Override
+    public long getAccountId() {
+        IpAddress ip = _networkService.getIp(ipAddressId);
+        return ip.getAccountId();
+    }
+
+    @Override
+    public String getSyncObjType() {
+        return BaseAsyncCmd.networkSyncObject;
+    }
+
+    @Override
+    public Long getSyncObjId() {
+        return getIp().getAssociatedWithNetworkId();
+    }
+
+    private IpAddress getIp() {
+        IpAddress ip = _networkService.getIp(ipAddressId);
+        if (ip == null) {
+            throw new InvalidParameterValueException("Unable to find ip address by id " + ipAddressId);
+        }
+        return ip;
+    }
+
+    @Override
+    public Integer getIcmpCode() {
+        return null;
+    }
+
+    @Override
+    public Integer getIcmpType() {
+        return null;
+    }
+
+    @Override
+    public Long getRelated() {
+        return null;
+    }
+
+    @Override
+    public FirewallRuleType getType() {
+        return FirewallRuleType.User;
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.FirewallRule;
+    }
+
+    @Override
+    public TrafficType getTrafficType() {
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java
new file mode 100644
index 0000000..5655b5e
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java
@@ -0,0 +1,117 @@
+// 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.firewall;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.FirewallRuleResponse;
+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.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.rules.FirewallRule;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "deleteFirewallRule", description="Deletes a firewall rule", responseObject=SuccessResponse.class)
+public class DeleteFirewallRuleCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(DeleteFirewallRuleCmd.class.getName());
+    private static final String s_name = "deletefirewallruleresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = FirewallRuleResponse.class,
+            required=true, description="the ID of the firewall rule")
+    private Long id;
+
+    // unexposed parameter needed for events logging
+    @Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.UUID, entityType = AccountResponse.class,
+            expose=false)
+    private Long ownerId;
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_FIREWALL_CLOSE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  ("Deleting firewall rule id=" + id);
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        if (ownerId == null) {
+            FirewallRule rule = _entityMgr.findById(FirewallRule.class, id);
+            if (rule == null) {
+                throw new InvalidParameterValueException("Unable to find firewall rule by id=" + id);
+            } else {
+                ownerId = _entityMgr.findById(FirewallRule.class, id).getAccountId();
+            }
+        }
+        return ownerId;
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException {
+        UserContext.current().setEventDetails("Rule Id: " + id);
+        boolean result = _firewallService.revokeFirewallRule(id, true);
+
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete firewall rule");
+        }
+    }
+
+
+    @Override
+    public String getSyncObjType() {
+        return BaseAsyncCmd.networkSyncObject;
+    }
+
+    @Override
+    public Long getSyncObjId() {
+        return _firewallService.getFirewallRule(id).getNetworkId();
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.FirewallRule;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java
new file mode 100644
index 0000000..8f4d599
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java
@@ -0,0 +1,119 @@
+// 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.firewall;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.FirewallRuleResponse;
+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.exception.InvalidParameterValueException;
+import com.cloud.network.rules.PortForwardingRule;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "deletePortForwardingRule", description="Deletes a port forwarding rule", responseObject=SuccessResponse.class)
+public class DeletePortForwardingRuleCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(DeletePortForwardingRuleCmd.class.getName());
+    private static final String s_name = "deleteportforwardingruleresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = FirewallRuleResponse.class,
+            required=true, description="the ID of the port forwarding rule")
+    private Long id;
+
+    // unexposed parameter needed for events logging
+    @Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.UUID, entityType = AccountResponse.class,
+            expose=false)
+    private Long ownerId;
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_NET_RULE_DELETE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  ("Deleting port forwarding rule for id=" + id);
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        if (ownerId == null) {
+            PortForwardingRule rule = _entityMgr.findById(PortForwardingRule.class, id);
+            if (rule == null) {
+                throw new InvalidParameterValueException("Unable to find port forwarding rule by id=" + id);
+            } else {
+                ownerId = _entityMgr.findById(PortForwardingRule.class, id).getAccountId();
+            }
+
+        }
+        return ownerId;
+    }
+
+    @Override
+    public void execute(){
+        UserContext.current().setEventDetails("Rule Id: "+id);
+        //revoke corresponding firewall rule first
+        boolean result  = _firewallService.revokeRelatedFirewallRule(id, true);
+        result = result &&  _rulesService.revokePortForwardingRule(id, true);
+
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete port forwarding rule");
+        }
+    }
+
+
+    @Override
+    public String getSyncObjType() {
+        return BaseAsyncCmd.networkSyncObject;
+    }
+
+    @Override
+    public Long getSyncObjId() {
+        return _rulesService.getPortForwardigRule(id).getNetworkId();
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.FirewallRule;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java
new file mode 100644
index 0000000..80581fb
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java
@@ -0,0 +1,87 @@
+// 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.firewall;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cloudstack.api.response.FirewallRuleResponse;
+import org.apache.cloudstack.api.response.IPAddressResponse;
+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.FirewallResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import com.cloud.network.rules.FirewallRule;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listFirewallRules", description="Lists all firewall rules for an IP address.", responseObject=FirewallResponse.class)
+public class ListFirewallRulesCmd extends BaseListTaggedResourcesCmd {
+    public static final Logger s_logger = Logger.getLogger(ListFirewallRulesCmd.class.getName());
+    private static final String s_name = "listfirewallrulesresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = FirewallRuleResponse.class,
+            description="Lists rule with the specified ID.")
+    private Long id;
+
+    @Parameter(name=ApiConstants.IP_ADDRESS_ID, type=CommandType.UUID, entityType = IPAddressResponse.class,
+            description="the id of IP address of the firwall services")
+    private Long ipAddressId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getIpAddressId() {
+        return ipAddressId;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute(){
+        Pair<List<? extends FirewallRule>, Integer> result = _firewallService.listFirewallRules(this);
+        ListResponse<FirewallResponse> response = new ListResponse<FirewallResponse>();
+        List<FirewallResponse> fwResponses = new ArrayList<FirewallResponse>();
+
+        for (FirewallRule fwRule : result.first()) {
+            FirewallResponse ruleData = _responseGenerator.createFirewallResponse(fwRule);
+            ruleData.setObjectName("firewallrule");
+            fwResponses.add(ruleData);
+        }
+        response.setResponses(fwResponses, 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/firewall/ListPortForwardingRulesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java
new file mode 100644
index 0000000..665af44
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.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.firewall;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cloudstack.api.response.IPAddressResponse;
+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.FirewallRuleResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import com.cloud.network.rules.PortForwardingRule;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listPortForwardingRules", description="Lists all port forwarding rules for an IP address.", responseObject=FirewallRuleResponse.class)
+public class ListPortForwardingRulesCmd extends BaseListTaggedResourcesCmd {
+    public static final Logger s_logger = Logger.getLogger(ListPortForwardingRulesCmd.class.getName());
+
+    private static final String s_name = "listportforwardingrulesresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = FirewallRuleResponse.class,
+            description="Lists rule with the specified ID.")
+    private Long id;
+
+    @Parameter(name=ApiConstants.IP_ADDRESS_ID, type=CommandType.UUID, entityType = IPAddressResponse.class,
+            description="the id of IP address of the port forwarding services")
+    private Long ipAddressId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getIpAddressId() {
+        return ipAddressId;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute(){
+        Pair<List<? extends PortForwardingRule>, Integer> result = _rulesService.listPortForwardingRules(this);
+        ListResponse<FirewallRuleResponse> response = new ListResponse<FirewallRuleResponse>();
+        List<FirewallRuleResponse> fwResponses = new ArrayList<FirewallRuleResponse>();
+
+        for (PortForwardingRule fwRule : result.first()) {
+            FirewallRuleResponse ruleData = _responseGenerator.createPortForwardingRuleResponse(fwRule);
+            ruleData.setObjectName("portforwardingrule");
+            fwResponses.add(ruleData);
+        }
+        response.setResponses(fwResponses, 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/firewall/UpdatePortForwardingRuleCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java
new file mode 100644
index 0000000..a52ebb7
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.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.firewall;
+
+import org.apache.cloudstack.api.response.IPAddressResponse;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.FirewallRuleResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.network.IpAddress;
+import com.cloud.user.Account;
+
+@APICommand(name = "updatePortForwardingRule", responseObject=FirewallRuleResponse.class, description="Updates a port forwarding rule.  Only the private port and the virtual machine can be updated.")
+public class UpdatePortForwardingRuleCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(UpdatePortForwardingRuleCmd.class.getName());
+    private static final String s_name = "updateportforwardingruleresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.PRIVATE_IP, type=CommandType.STRING, description="the private IP address of the port forwarding rule")
+    private String privateIp;
+
+    @Parameter(name=ApiConstants.PRIVATE_PORT, type=CommandType.STRING, required=true, description="the private port of the port forwarding rule")
+    private String privatePort;
+
+    @Parameter(name=ApiConstants.PROTOCOL, type=CommandType.STRING, required=true, description="the protocol for the port fowarding rule. Valid values are TCP or UDP.")
+    private String protocol;
+
+    @Parameter(name=ApiConstants.IP_ADDRESS_ID, type=CommandType.UUID, entityType = IPAddressResponse.class,
+            required=true, description="the IP address id of the port forwarding rule")
+    private Long publicIpId;
+
+    @Parameter(name=ApiConstants.PUBLIC_PORT, type=CommandType.STRING, required=true, description="the public port of the port forwarding rule")
+    private String publicPort;
+
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType = UserVmResponse.class,
+            description="the ID of the virtual machine for the port forwarding rule")
+    private Long virtualMachineId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getPrivateIp() {
+        return privateIp;
+    }
+
+    public String getPrivatePort() {
+        return privatePort;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public Long getPublicIpId() {
+        return publicIpId;
+    }
+
+    public String getPublicPort() {
+        return publicPort;
+    }
+
+    public Long getVirtualMachineId() {
+        return virtualMachineId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        IpAddress addr = _entityMgr.findById(IpAddress.class, getPublicIpId());
+        if (addr != null) {
+            return addr.getAccountId();
+        }
+
+        // bad address given, parent this command to SYSTEM so ERROR events are tracked
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_NET_RULE_MODIFY;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "updating port forwarding rule";
+    }
+
+    @Override
+    public void execute(){
+//FIXME:        PortForwardingRule result = _mgr.updatePortForwardingRule(this);
+//        if (result != null) {
+//            FirewallRuleResponse response = _responseGenerator.createFirewallRuleResponse(result);
+//            response.setResponseName(getName());
+//            this.setResponseObject(response);
+//        } else {
+//            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update port forwarding rule");
+//        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/guest/ListGuestOsCategoriesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/guest/ListGuestOsCategoriesCmd.java b/api/src/org/apache/cloudstack/api/command/user/guest/ListGuestOsCategoriesCmd.java
new file mode 100644
index 0000000..3b4c4cd
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/guest/ListGuestOsCategoriesCmd.java
@@ -0,0 +1,92 @@
+// 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.guest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import com.cloud.storage.GuestOsCategory;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listOsCategories", description="Lists all supported OS categories for this cloud.", responseObject=GuestOSCategoryResponse.class)
+public class ListGuestOsCategoriesCmd extends BaseListCmd {
+    public static final Logger s_logger = Logger.getLogger(ListIsosCmd.class.getName());
+
+    private static final String s_name = "listoscategoriesresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = GuestOSCategoryResponse.class,
+            description="list Os category by id")
+    private Long id;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="list os category by name", since="3.0.1")
+    private String name;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute(){
+        Pair<List<? extends GuestOsCategory>, Integer> result = _mgr.listGuestOSCategoriesByCriteria(this);
+        ListResponse<GuestOSCategoryResponse> response = new ListResponse<GuestOSCategoryResponse>();
+        List<GuestOSCategoryResponse> osCatResponses = new ArrayList<GuestOSCategoryResponse>();
+        for (GuestOsCategory osCategory : result.first()) {
+            GuestOSCategoryResponse categoryResponse = new GuestOSCategoryResponse();
+            categoryResponse.setId(osCategory.getUuid());
+            categoryResponse.setName(osCategory.getName());
+
+            categoryResponse.setObjectName("oscategory");
+            osCatResponses.add(categoryResponse);
+        }
+
+        response.setResponses(osCatResponses, 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/guest/ListGuestOsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java b/api/src/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java
new file mode 100644
index 0000000..3c145e9
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java
@@ -0,0 +1,96 @@
+// 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.guest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.command.user.iso.ListIsosCmd;
+import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
+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.GuestOSResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import com.cloud.storage.GuestOS;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listOsTypes", description="Lists all supported OS types for this cloud.", responseObject=GuestOSResponse.class)
+public class ListGuestOsCmd extends BaseListCmd {
+    public static final Logger s_logger = Logger.getLogger(ListIsosCmd.class.getName());
+
+    private static final String s_name = "listostypesresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = GuestOSResponse.class,
+            description="list by Os type Id")
+    private Long id;
+
+    @Parameter(name=ApiConstants.OS_CATEGORY_ID, type=CommandType.UUID, entityType = GuestOSCategoryResponse.class,
+            description="list by Os Category id")
+    private Long osCategoryId;
+
+    @Parameter(name=ApiConstants.DESCRIPTION, type=CommandType.STRING, description="list os by description", since="3.0.1")
+    private String description;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public Long getOsCategoryId() {
+        return osCategoryId;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute(){
+        Pair<List<? extends GuestOS>, Integer> result = _mgr.listGuestOSByCriteria(this);
+        ListResponse<GuestOSResponse> response = new ListResponse<GuestOSResponse>();
+        List<GuestOSResponse> osResponses = new ArrayList<GuestOSResponse>();
+        for (GuestOS guestOS : result.first()) {
+            GuestOSResponse guestOSResponse = _responseGenerator.createGuestOSResponse(guestOS);
+            osResponses.add(guestOSResponse);
+        }
+
+        response.setResponses(osResponses, 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/iso/AttachIsoCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java
new file mode 100644
index 0000000..1e154e2
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java
@@ -0,0 +1,113 @@
+// 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.iso;
+
+import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
+import org.apache.cloudstack.api.response.TemplateResponse;
+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.UserVmResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.user.UserContext;
+import com.cloud.uservm.UserVm;
+
+@APICommand(name = "attachIso", description="Attaches an ISO to a virtual machine.", responseObject=UserVmResponse.class)
+public class AttachIsoCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(AttachIsoCmd.class.getName());
+
+    private static final String s_name = "attachisoresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = TemplateResponse.class,
+            required=true, description="the ID of the ISO file")
+    private Long id;
+
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType = TemplateResponse.class,
+            required=true, description="the ID of the virtual machine")
+    private Long virtualMachineId;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public Long getVirtualMachineId() {
+        return virtualMachineId;
+    }
+
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        UserVm vm = _entityMgr.findById(UserVm.class, getVirtualMachineId());
+        if (vm == null) {
+            throw new InvalidParameterValueException("Unable to find virtual machine by id " + getVirtualMachineId());
+        }
+
+        return vm.getAccountId();
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_ISO_ATTACH;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "attaching ISO: " + getId() + " to vm: " + getVirtualMachineId();
+    }
+
+    @Override
+    public void execute(){
+        UserContext.current().setEventDetails("Vm Id: " +getVirtualMachineId()+ " ISO Id: "+getId());
+        boolean result = _templateService.attachIso(id, virtualMachineId);
+        if (result) {
+            UserVm userVm = _responseGenerator.findUserVmById(virtualMachineId);
+            if (userVm != null) {
+                UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", userVm).get(0);
+                response.setResponseName(DeployVMCmd.getResultObjectName());
+                this.setResponseObject(response);
+            } else {
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to attach iso");
+            }
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to attach iso");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java
new file mode 100644
index 0000000..b449ff5
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java
@@ -0,0 +1,30 @@
+// 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.iso;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.TemplateResponse;
+import org.apache.cloudstack.api.command.user.template.CopyTemplateCmd;
+
+@APICommand(name = "copyIso", description="Copies an iso from one zone to another.", responseObject=TemplateResponse.class)
+public class CopyIsoCmd extends CopyTemplateCmd {
+    public static final Logger s_logger = Logger.getLogger(CopyIsoCmd.class.getName());
+    private static final String s_name = "copyisoresponse";
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/iso/DeleteIsoCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/DeleteIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/DeleteIsoCmd.java
new file mode 100644
index 0000000..44efbf8
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/iso/DeleteIsoCmd.java
@@ -0,0 +1,118 @@
+// 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.iso;
+
+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 org.apache.cloudstack.api.response.TemplateResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+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 = "deleteIso", description="Deletes an ISO file.", responseObject=SuccessResponse.class)
+public class DeleteIsoCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(DeleteIsoCmd.class.getName());
+    private static final String s_name = "deleteisosresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = TemplateResponse.class,
+            required=true, description="the ID of the ISO file")
+    private Long id;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
+            description="the ID of the zone of the ISO file. If not specified, the ISO will be deleted from all the zones")
+    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 iso = _entityMgr.findById(VirtualMachineTemplate.class, getId());
+        if (iso != null) {
+            return iso.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_ISO_DELETE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "Deleting iso " + getId();
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Iso;
+    }
+
+    public Long getInstanceId() {
+        return getId();
+    }
+
+    @Override
+    public void execute(){
+        UserContext.current().setEventDetails("ISO Id: "+getId());
+        boolean result = _templateService.deleteIso(this);
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete iso");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java
new file mode 100644
index 0000000..eb1c6ee
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java
@@ -0,0 +1,97 @@
+// 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.iso;
+
+import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
+import org.apache.cloudstack.api.response.TemplateResponse;
+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.UserVmResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.uservm.UserVm;
+
+@APICommand(name = "detachIso", description="Detaches any ISO file (if any) currently attached to a virtual machine.", responseObject=UserVmResponse.class)
+public class DetachIsoCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(DetachIsoCmd.class.getName());
+
+    private static final String s_name = "detachisoresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType = TemplateResponse.class,
+            required=true, description="The ID of the virtual machine")
+    private Long virtualMachineId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getVirtualMachineId() {
+        return virtualMachineId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        UserVm vm = _entityMgr.findById(UserVm.class, getVirtualMachineId());
+        if (vm != null) {
+            return vm.getAccountId();
+        } else {
+            throw new InvalidParameterValueException("Unable to find vm by id " + getVirtualMachineId());
+        }
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_ISO_DETACH;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "detaching ISO from vm: " + getVirtualMachineId();
+    }
+
+    @Override
+    public void execute(){
+        boolean result = _templateService.detachIso(virtualMachineId);
+        if (result) {
+            UserVm userVm = _entityMgr.findById(UserVm.class, virtualMachineId);
+            UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", userVm).get(0);
+            response.setResponseName(DeployVMCmd.getResultObjectName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to detach iso");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java
new file mode 100644
index 0000000..5f8303e
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.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.iso;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.TemplateResponse;
+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 = "extractIso", description="Extracts an ISO", responseObject=ExtractResponse.class)
+public class ExtractIsoCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(ExtractIsoCmd.class.getName());
+
+    private static final String s_name = "extractisoresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = TemplateResponse.class,
+            required=true, description="the ID of the ISO file")
+    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;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_ISO_EXTRACT;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        VirtualMachineTemplate iso = _entityMgr.findById(VirtualMachineTemplate.class, getId());
+        if (iso != null) {
+            return iso.getAccountId();
+        }
+
+        // invalid id, parent this command to SYSTEM so ERROR events are tracked
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "extracting iso: " + getId() + " from zone: " + getZoneId();
+    }
+
+    public static String getStaticName() {
+        return s_name;
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Iso;
+    }
+
+    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());
+                response.setObjectName("iso");
+                this.setResponseObject(response);
+            } else {
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to extract iso");
+            }
+        } catch (InternalErrorException ex) {
+            s_logger.warn("Exception: ", ex);
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage());
+        }
+    }
+}