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:38 UTC

[3/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/vmgroup/UpdateVMGroupCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java
new file mode 100644
index 0000000..09313c0
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.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.vmgroup;
+
+import org.apache.cloudstack.api.*;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.InstanceGroupResponse;
+import com.cloud.user.Account;
+import com.cloud.vm.InstanceGroup;
+
+@APICommand(name = "updateInstanceGroup", description="Updates a vm group", responseObject=InstanceGroupResponse.class)
+public class UpdateVMGroupCmd extends BaseCmd{
+
+    private static final String s_name = "updateinstancegroupresponse";
+    public static final Logger s_logger = Logger.getLogger(UpdateVMGroupCmd.class.getName());
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=InstanceGroupResponse.class,
+            required=true, description="Instance group ID")
+    private Long id;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="new instance group name")
+    private String groupName;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getGroupName() {
+        return groupName;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        InstanceGroup group = _entityMgr.findById(InstanceGroup.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 void execute(){
+        InstanceGroup result = _mgr.updateVmGroup(this);
+        if (result != null){
+            InstanceGroupResponse response = _responseGenerator.createInstanceGroupResponse(result);
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to update vm instance group");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java
new file mode 100644
index 0000000..e48e4e4
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java
@@ -0,0 +1,131 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.user.volume;
+
+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.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.VolumeResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.storage.Volume;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "attachVolume", description="Attaches a disk volume to a virtual machine.", responseObject=VolumeResponse.class)
+public class AttachVolumeCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(AttachVolumeCmd.class.getName());
+    private static final String s_name = "attachvolumeresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.DEVICE_ID, type=CommandType.LONG, description="the ID of the device to map the volume to within the guest OS. " +
+                                                                    "If no deviceId is passed in, the next available deviceId will be chosen. " +
+                                                                    "Possible values for a Linux OS are:" +
+                                                                    "* 1 - /dev/xvdb" +
+                                                                    "* 2 - /dev/xvdc" +
+                                                                    "* 4 - /dev/xvde" +
+                                                                    "* 5 - /dev/xvdf" +
+                                                                    "* 6 - /dev/xvdg" +
+                                                                    "* 7 - /dev/xvdh" +
+                                                                    "* 8 - /dev/xvdi" +
+                                                                    "* 9 - /dev/xvdj")
+    private Long deviceId;
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VolumeResponse.class,
+            required=true, description="the ID of the disk volume")
+    private Long id;
+
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType=UserVmResponse.class,
+            required=true, description="    the ID of the virtual machine")
+    private Long virtualMachineId;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getDeviceId() {
+        return deviceId;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public Long getVirtualMachineId() {
+        return virtualMachineId;
+    }
+
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Volume;
+    }
+
+    public Long getInstanceId() {
+        return getId();
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Volume volume = _responseGenerator.findVolumeById(getId());
+        if (volume == null) {
+            return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked
+        }
+        return volume.getAccountId();
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_VOLUME_ATTACH;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "attaching volume: " + getId() + " to vm: " + getVirtualMachineId();
+    }
+
+    @Override
+    public void execute(){
+        UserContext.current().setEventDetails("Volume Id: "+getId()+" VmId: "+getVirtualMachineId());
+        Volume result = _userVmService.attachVolumeToVM(this);
+        if (result != null) {
+            VolumeResponse response = _responseGenerator.createVolumeResponse(result);
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to attach volume");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java
new file mode 100644
index 0000000..512685f
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java
@@ -0,0 +1,187 @@
+// 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.volume;
+
+import org.apache.cloudstack.api.response.*;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+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 com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.Volume;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "createVolume", responseObject=VolumeResponse.class, description="Creates a disk volume from a disk offering. This disk volume must still be attached to a virtual machine to make use of it.")
+public class CreateVolumeCmd extends BaseAsyncCreateCmd {
+    public static final Logger s_logger = Logger.getLogger(CreateVolumeCmd.class.getName());
+    private static final String s_name = "createvolumeresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="the account associated with the disk volume. Must be used with the domainId parameter.")
+    private String accountName;
+
+    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType=ProjectResponse.class,
+            description="the project associated with the volume. Mutually exclusive with account parameter")
+    private Long projectId;
+
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
+            description="the domain ID associated with the disk offering. If used with the account parameter" +
+                    " returns the disk volume associated with the account for the specified domain.")
+    private Long domainId;
+
+    @Parameter(name=ApiConstants.DISK_OFFERING_ID,required = false, type=CommandType.UUID, entityType=DiskOfferingResponse.class,
+            description="the ID of the disk offering. Either diskOfferingId or snapshotId must be passed in.")
+    private Long diskOfferingId;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="the name of the disk volume")
+    private String volumeName;
+
+    @Parameter(name=ApiConstants.SIZE, type=CommandType.LONG, description="Arbitrary volume size")
+    private Long size;
+
+    @Parameter(name=ApiConstants.SNAPSHOT_ID, type=CommandType.UUID, entityType=SnapshotResponse.class,
+            description="the snapshot ID for the disk volume. Either diskOfferingId or snapshotId must be passed in.")
+    private Long snapshotId;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
+            description="the ID of the availability zone")
+    private Long zoneId;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getEntityTable() {
+        return "volumes";
+    }
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public Long getDiskOfferingId() {
+        return diskOfferingId;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public String getVolumeName() {
+        return volumeName;
+    }
+
+    public Long getSize() {
+        return size;
+    }
+
+    public Long getSnapshotId() {
+        return snapshotId;
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+    private Long getProjectId() {
+        return projectId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "volume";
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Volume;
+    }
+
+    @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_VOLUME_CREATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "creating volume: " + getVolumeName() + ((getSnapshotId() == null) ? "" : " from snapshot: " + getSnapshotId());
+    }
+
+    @Override
+    public void create() throws ResourceAllocationException{
+
+        Volume volume = _storageService.allocVolume(this);
+        if (volume != null) {
+            this.setEntityId(volume.getId());
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create volume");
+        }
+    }
+
+    @Override
+    public void execute(){
+        UserContext.current().setEventDetails("Volume Id: "+getEntityId()+((getSnapshotId() == null) ? "" : " from snapshot: " + getSnapshotId()));
+        Volume volume = _storageService.createVolume(this);
+        if (volume != null) {
+            VolumeResponse response = _responseGenerator.createVolumeResponse(volume);
+            //FIXME - have to be moved to ApiResponseHelper
+            if (getSnapshotId() != null) {
+                Snapshot snap = _entityMgr.findById(Snapshot.class, getSnapshotId());
+                if (snap != null) {
+                    response.setSnapshotId(snap.getUuid()); // if the volume was
+                                                            // created from a
+                                                            // snapshot,
+                                                            // snapshotId will
+                                                            // be set so we pass
+                                                            // it back in the
+                                                            // response
+                }
+            }
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create a volume");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java
new file mode 100644
index 0000000..2b2e94c
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java
@@ -0,0 +1,90 @@
+// 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.volume;
+
+import org.apache.cloudstack.api.response.VolumeResponse;
+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.SuccessResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.storage.Volume;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "deleteVolume", description="Deletes a detached disk volume.", responseObject=SuccessResponse.class)
+public class DeleteVolumeCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(DeleteVolumeCmd.class.getName());
+    private static final String s_name = "deletevolumeresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VolumeResponse.class,
+            required=true, description="The ID of the disk volume")
+    private Long id;
+
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "volume";
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Volume volume = _entityMgr.findById(Volume.class, getId());
+        if (volume != null) {
+            return volume.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+    @Override
+    public void execute() throws ConcurrentOperationException {
+        UserContext.current().setEventDetails("Volume Id: "+getId());
+        boolean result = _storageService.deleteVolume(id, UserContext.current().getCaller());
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete volume");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java
new file mode 100644
index 0000000..c8ecdde
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java
@@ -0,0 +1,138 @@
+// 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.volume;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.UserVmResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.VolumeResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.storage.Volume;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+import com.cloud.uservm.UserVm;
+
+@APICommand(name = "detachVolume", description="Detaches a disk volume from a virtual machine.", responseObject=VolumeResponse.class)
+public class DetachVolumeCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(DetachVolumeCmd.class.getName());
+    private static final String s_name = "detachvolumeresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VolumeResponse.class,
+            description="the ID of the disk volume")
+    private Long id;
+
+    @Parameter(name=ApiConstants.DEVICE_ID, type=CommandType.LONG, description="the device ID on the virtual machine where volume is detached from")
+    private Long deviceId;
+
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType=UserVmResponse.class,
+            description="the ID of the virtual machine where the volume is detached from")
+    private Long virtualMachineId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public Long getDeviceId() {
+        return deviceId;
+    }
+
+    public Long getVirtualMachineId() {
+        return virtualMachineId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "volume";
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Volume;
+    }
+
+    public Long getInstanceId() {
+        return getId();
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Long volumeId = getId();
+        if (volumeId != null) {
+            Volume volume = _responseGenerator.findVolumeById(volumeId);
+            if (volume != null) {
+                return volume.getAccountId();
+            }
+        } else if (getVirtualMachineId() != null) {
+            UserVm vm = _responseGenerator.findUserVmById(getVirtualMachineId());
+            if (vm != null) {
+                return vm.getAccountId();
+            }
+        }
+
+        // invalid id, parent this command to SYSTEM so ERROR events are tracked
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_VOLUME_DETACH;
+    }
+
+    @Override
+    public String getEventDescription() {
+        StringBuilder sb = new StringBuilder();
+        if (id != null) {
+            sb.append(": " + id);
+        } else if ((deviceId != null) && (virtualMachineId != null)) {
+            sb.append(" with device id: " + deviceId + " from vm: " + virtualMachineId);
+        } else {
+            sb.append(" <error:  either volume id or deviceId/vmId need to be specified>");
+        }
+        return  "detaching volume" + sb.toString();
+    }
+
+    @Override
+    public void execute(){
+        UserContext.current().setEventDetails("Volume Id: "+getId()+" VmId: "+getVirtualMachineId());
+        Volume result = _userVmService.detachVolumeFromVM(this);
+        if (result != null){
+            VolumeResponse response = _responseGenerator.createVolumeResponse(result);
+            response.setResponseName("volume");
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to detach volume");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java
new file mode 100644
index 0000000..7f6cd05
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java
@@ -0,0 +1,158 @@
+// 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.volume;
+
+import java.net.URISyntaxException;
+
+import org.apache.cloudstack.api.response.VolumeResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+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.ExtractResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.dc.DataCenter;
+import com.cloud.event.EventTypes;
+import com.cloud.storage.Upload;
+import com.cloud.storage.Volume;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "extractVolume", description="Extracts volume", responseObject=ExtractResponse.class)
+public class ExtractVolumeCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(ExtractVolumeCmd.class.getName());
+
+    private static final String s_name = "extractvolumeresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VolumeResponse.class,
+            required=true, description="the ID of the volume")
+    private Long id;
+
+
+    @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required=false, description="the url to which the volume would be extracted")
+    private String url;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
+            required=true, description="the ID of the zone where the volume is located")
+    private Long zoneId;
+
+    @Parameter(name=ApiConstants.MODE, type=CommandType.STRING, required=true, description="the mode of extraction - HTTP_DOWNLOAD or FTP_UPLOAD")
+    private String mode;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+    public String getMode() {
+        return mode;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getStaticName() {
+        return s_name;
+    }
+
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Volume;
+    }
+
+    public Long getInstanceId() {
+        return getId();
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Volume volume = _entityMgr.findById(Volume.class, getId());
+        if (volume != null) {
+            return volume.getAccountId();
+        }
+
+        // invalid id, parent this command to SYSTEM so ERROR events are tracked
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_VOLUME_EXTRACT;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "Extraction job";
+    }
+
+    @Override
+    public void execute(){
+        try {
+            UserContext.current().setEventDetails("Volume Id: "+getId());
+            Long uploadId = _mgr.extractVolume(this);
+            if (uploadId != null){
+                Upload uploadInfo = _entityMgr.findById(Upload.class, uploadId);
+                ExtractResponse response = new ExtractResponse();
+                response.setResponseName(getCommandName());
+                response.setObjectName("volume");
+                Volume vol = _entityMgr.findById(Volume.class, id);
+                response.setId(vol.getUuid());
+                response.setName(vol.getName());
+                DataCenter zone = _entityMgr.findById(DataCenter.class, id);
+                response.setZoneId(zone.getUuid());
+                response.setZoneName(zone.getName());
+                response.setMode(mode);
+                response.setUploadId(uploadInfo.getUuid());
+                response.setState(uploadInfo.getUploadState().toString());
+                Account account = _entityMgr.findById(Account.class, getEntityOwnerId());
+                response.setAccountId(account.getUuid());
+                response.setUrl(uploadInfo.getUploadUrl());
+                this.setResponseObject(response);
+            } else {
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to extract volume");
+            }
+        } catch (URISyntaxException ex) {
+            s_logger.info(ex);
+            throw new ServerApiException(BaseCmd.PARAM_ERROR, ex.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java
new file mode 100644
index 0000000..9ba4f34
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.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.volume;
+
+import org.apache.cloudstack.api.response.*;
+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 com.cloud.async.AsyncJob;
+
+
+@APICommand(name = "listVolumes", description="Lists all volumes.", responseObject=VolumeResponse.class)
+public class ListVolumesCmd extends BaseListTaggedResourcesCmd {
+    public static final Logger s_logger = Logger.getLogger(ListVolumesCmd.class.getName());
+
+    private static final String s_name = "listvolumesresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.HOST_ID, type=CommandType.UUID, entityType=HostResponse.class,
+            description="list volumes on specified host")
+    private Long hostId;
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VolumeResponse.class,
+            description="the ID of the disk volume")
+    private Long id;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the name of the disk volume")
+    private String volumeName;
+
+    @Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class,
+            description="the pod id the disk volume belongs to")
+    private Long podId;
+
+    @Parameter(name=ApiConstants.TYPE, type=CommandType.STRING, description="the type of disk volume")
+    private String type;
+
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType=UserVmResponse.class,
+            description="the ID of the virtual machine")
+    private Long virtualMachineId;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
+            description="the ID of the availability zone")
+    private Long zoneId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+
+    public Long getHostId() {
+        return hostId;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getVolumeName() {
+        return volumeName;
+    }
+
+    public Long getPodId() {
+        return podId;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public Long getVirtualMachineId() {
+        return virtualMachineId;
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.Volume;
+    }
+
+    @Override
+    public void execute(){
+        ListResponse<VolumeResponse> response = _queryService.searchForVolumes(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/volume/MigrateVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java
new file mode 100644
index 0000000..30e672a
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java
@@ -0,0 +1,106 @@
+// 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.volume;
+
+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.StoragePoolResponse;
+import org.apache.cloudstack.api.response.VolumeResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.storage.Volume;
+import com.cloud.user.Account;
+
+
+@APICommand(name = "migrateVolume", description="Migrate volume", responseObject=VolumeResponse.class, since="3.0.0")
+public class MigrateVolumeCmd extends BaseAsyncCmd {
+    private static final String s_name = "migratevolumeresponse";
+
+     /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.VOLUME_ID, type=CommandType.UUID, entityType=VolumeResponse.class,
+            required=true, description="the ID of the volume")
+    private Long volumeId;
+
+    @Parameter(name=ApiConstants.STORAGE_ID, type=CommandType.UUID, entityType=StoragePoolResponse.class,
+            required=true, description="destination storage pool ID to migrate the volume to")
+    private Long storageId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getVolumeId() {
+        return volumeId;
+    }
+
+    public Long getStoragePoolId() {
+        return storageId;
+    }
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+          Volume volume = _entityMgr.findById(Volume.class, getVolumeId());
+          if (volume != null) {
+              return volume.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_VOLUME_MIGRATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "Attempting to migrate volume Id: " + getVolumeId() + " to storage pool Id: "+ getStoragePoolId();
+    }
+
+
+    @Override
+    public void execute(){
+        Volume result;
+        try {
+            result = _storageService.migrateVolume(getVolumeId(), getStoragePoolId());
+             if (result != null) {
+                 VolumeResponse response = _responseGenerator.createVolumeResponse(result);
+                 response.setResponseName(getCommandName());
+                 this.setResponseObject(response);
+             }
+        } catch (ConcurrentOperationException e) {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to migrate volume: ");
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java
new file mode 100644
index 0000000..e42bf35
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java
@@ -0,0 +1,153 @@
+// 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.volume;
+
+import org.apache.cloudstack.api.response.*;
+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.BaseListTaggedResourcesCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.projects.Project;
+import com.cloud.storage.Volume;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+
+@APICommand(name="resizeVolume", description="Resizes a volume", responseObject=VolumeResponse.class)
+public class ResizeVolumeCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(ResizeVolumeCmd.class.getName());
+
+    private static final String s_name = "resizevolumeresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, entityType=VolumeResponse.class, type=CommandType.UUID, description="the ID of the disk volume")
+    private Long id;
+
+    @Parameter(name=ApiConstants.SIZE, type=CommandType.LONG, required=false, description="New volume size in G")
+    private Long size;
+
+    @Parameter(name=ApiConstants.SHRINK_OK, type=CommandType.BOOLEAN, required=false, description="Verify OK to Shrink")
+    private boolean shrinkOk;
+
+    @Parameter(name=ApiConstants.DISK_OFFERING_ID, entityType=DiskOfferingResponse.class, type=CommandType.UUID, required=false, description="new disk offering id")
+    private Long newDiskOfferingId;
+    
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getEntityId() {
+        return id;
+    }
+    
+    public Long getSize() {
+        return size;
+    }
+
+    public boolean getShrinkOk() {
+        return shrinkOk;
+    }
+
+    public Long getNewDiskOfferingId() {
+        return newDiskOfferingId;
+    }
+
+    
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+    
+    @Override
+    public AsyncJob.Type getInstanceType() {
+    	return AsyncJob.Type.Volume;
+    }
+
+    public static String getResultObjectName() {
+        return "volume";
+    }
+
+   @Override
+    public long getEntityOwnerId() {
+
+        Volume volume = _entityMgr.findById(Volume.class, getEntityId());
+        if (volume == null) {
+                throw new InvalidParameterValueException("Unable to find volume by id=" + id);
+        }
+
+        Account account = _accountService.getAccount(volume.getAccountId());
+        //Can resize volumes 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  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 volume " + id + "  is disabled: " + account);
+        }
+
+        return volume.getAccountId();
+    }
+
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_VOLUME_RESIZE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "Volume Id: " + getEntityId() + " to size " + getSize() + "G" ;
+    }
+    
+    @Override
+    public void execute(){
+        UserContext.current().setEventDetails("Volume Id: " + getEntityId() + " to size " + getSize() + "G");
+    	Volume volume = _storageService.resizeVolume(this);
+    	if (volume != null) {
+            VolumeResponse response = _responseGenerator.createVolumeResponse(volume);
+            //FIXME - have to be moved to ApiResponseHelper
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to resize volume");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java
new file mode 100644
index 0000000..4167ffd
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java
@@ -0,0 +1,144 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.user.volume;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.VolumeResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.storage.Volume;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "uploadVolume", description="Uploads a data disk.", responseObject=VolumeResponse.class)
+public class UploadVolumeCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(UploadVolumeCmd.class.getName());
+    private static final String s_name = "uploadvolumeresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.FORMAT, type=CommandType.STRING, required=true, description="the format for the volume. Possible values include QCOW2, OVA, and VHD.")
+    private String format;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="the name of the volume")
+    private String volumeName;
+
+    @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required=true, description="the URL of where the volume is hosted. Possible URL include http:// and https://")
+    private String url;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
+            required=true, description="the ID of the zone the volume is to be hosted on")
+    private Long zoneId;
+
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType = DomainResponse.class,
+            description="an optional domainId. If the account parameter is used, domainId must also be used.")
+    private Long domainId;
+
+    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="an optional accountName. Must be used with domainId.")
+    private String accountName;
+
+    @Parameter(name=ApiConstants.CHECKSUM, type=CommandType.STRING, description="the MD5 checksum value of this volume")
+    private String checksum;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getFormat() {
+        return format;
+    }
+
+    public String getVolumeName() {
+        return volumeName;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public String getChecksum() {
+        return checksum;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public void execute() throws ResourceUnavailableException,
+            InsufficientCapacityException, ServerApiException,
+            ConcurrentOperationException, ResourceAllocationException,
+            NetworkRuleConflictException {
+
+            Volume volume = _storageService.uploadVolume(this);
+            if (volume != null){
+                VolumeResponse response = _responseGenerator.createVolumeResponse(volume);
+                response.setResponseName(getCommandName());
+                this.setResponseObject(response);
+            } else {
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to upload volume");
+            }
+    }
+
+    @Override
+    public String getCommandName() {
+           return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Long accountId = finalyzeAccountId(accountName, domainId, null, true);
+        if (accountId == null) {
+            return UserContext.current().getCaller().getId();
+        }
+
+        return accountId;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "uploading volume: " + getVolumeName() + " in the zone " + getZoneId();
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_VOLUME_UPLOAD;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java
new file mode 100644
index 0000000..85a0ae4
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java
@@ -0,0 +1,148 @@
+// 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.vpc;
+
+import org.apache.cloudstack.api.response.PrivateGatewayResponse;
+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.StaticRouteResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.vpc.StaticRoute;
+import com.cloud.network.vpc.VpcGateway;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "createStaticRoute", description="Creates a static route", responseObject=StaticRouteResponse.class)
+public class CreateStaticRouteCmd extends BaseAsyncCreateCmd{
+    private static final String s_name = "createstaticrouteresponse";
+    public static final Logger s_logger = Logger.getLogger(CreateStaticRouteCmd.class.getName());
+
+    @Parameter(name=ApiConstants.GATEWAY_ID, type=CommandType.UUID, entityType=PrivateGatewayResponse.class,
+            required=true, description="the gateway id we are creating static route for")
+    private Long gatewayId;
+
+    @Parameter(name = ApiConstants.CIDR, required = true, type = CommandType.STRING, description = "static route cidr")
+    private String cidr;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+    public long getGatewayId() {
+        return gatewayId;
+    }
+
+    public String getCidr() {
+        return cidr;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+    @Override
+    public void create() throws ResourceAllocationException {
+        try {
+            StaticRoute result = _vpcService.createStaticRoute(getGatewayId(), getCidr());
+            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 getEntityTable() {
+        return "static_routes";
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_STATIC_ROUTE_CREATE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "creating static route";
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException {
+        boolean success = false;
+        StaticRoute route = _entityMgr.findById(StaticRoute.class, getEntityId());
+        try {
+            UserContext.current().setEventDetails("Static route Id: " + getEntityId());
+            success = _vpcService.applyStaticRoutes(route.getVpcId());
+
+            // State is different after the route is applied, so get new object here
+            route = _entityMgr.findById(StaticRoute.class, getEntityId());
+            StaticRouteResponse routeResponse = new StaticRouteResponse();
+            if (route != null) {
+                routeResponse = _responseGenerator.createStaticRouteResponse(route);
+                setResponseObject(routeResponse);
+            }
+            routeResponse.setResponseName(getCommandName());
+        } finally {
+            if (!success || route == null) {
+                _vpcService.revokeStaticRoute(getEntityId());
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create static route");
+            }
+        }
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+         VpcGateway gateway =  _vpcService.getVpcGateway(gatewayId);
+         if (gateway == null) {
+             throw new InvalidParameterValueException("Invalid gateway id is specified");
+         }
+         return _vpcService.getVpc(gateway.getVpcId()).getAccountId();
+    }
+
+    @Override
+    public String getSyncObjType() {
+        return BaseAsyncCmd.vpcSyncObject;
+    }
+
+    @Override
+    public Long getSyncObjId() {
+        VpcGateway gateway =  _vpcService.getVpcGateway(gatewayId);
+        if (gateway == null) {
+            throw new InvalidParameterValueException("Invalid id is specified for the gateway");
+        }
+        return gateway.getVpcId();
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.StaticRoute;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java
new file mode 100644
index 0000000..df16c8e
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java
@@ -0,0 +1,191 @@
+// 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.vpc;
+
+import org.apache.cloudstack.api.response.VpcResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ProjectResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.api.response.VpcOfferingResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+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 com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.vpc.Vpc;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "createVPC", description="Creates a VPC", responseObject=VpcResponse.class)
+public class CreateVPCCmd extends BaseAsyncCreateCmd{
+    public static final Logger s_logger = Logger.getLogger(CreateVPCCmd.class.getName());
+    private static final String s_name = "createvpcresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="the account associated with the VPC. " +
+            "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 VPC. " +
+            "If used with the account parameter returns the VPC associated with the account for the specified domain.")
+    private Long domainId;
+
+    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType=ProjectResponse.class,
+            description="create VPC for the project")
+    private Long projectId;
+
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
+            required=true, description="the ID of the availability zone")
+    private Long zoneId;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="the name of the VPC")
+    private String vpcName;
+
+    @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, required=true, description="the display text of " +
+            "the VPC")
+    private String displayText;
+
+    @Parameter(name=ApiConstants.CIDR, type=CommandType.STRING, required=true, description="the cidr of the VPC. All VPC " +
+            "guest networks' cidrs should be within this CIDR")
+    private String cidr;
+
+    @Parameter(name=ApiConstants.VPC_OFF_ID, type=CommandType.UUID, entityType=VpcOfferingResponse.class,
+            required=true, description="the ID of the VPC offering")
+    private Long vpcOffering;
+
+    @Parameter(name=ApiConstants.NETWORK_DOMAIN, type=CommandType.STRING,
+            description="VPC network domain. All networks inside the VPC will belong to this domain")
+    private String networkDomain;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getAccountName() {
+        return accountName;
+    }
+
+    public Long getDomainId() {
+        return domainId;
+    }
+
+    public Long getZoneId() {
+        return zoneId;
+    }
+
+    public String getVpcName() {
+        return vpcName;
+    }
+
+    public String getCidr() {
+        return cidr;
+    }
+
+    public String getDisplayText() {
+        return displayText;
+    }
+
+    public Long getVpcOffering() {
+        return vpcOffering;
+    }
+
+    public String getNetworkDomain() {
+        return networkDomain;
+    }
+
+    @Override
+    public void create() throws ResourceAllocationException {
+        Vpc vpc = _vpcService.createVpc(getZoneId(), getVpcOffering(), getEntityOwnerId(), getVpcName(), getDisplayText(),
+                getCidr(), getNetworkDomain());
+        if (vpc != null) {
+            this.setEntityId(vpc.getId());
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create a VPC");
+        }
+    }
+
+    @Override
+    public void execute() {
+        Vpc vpc = null;
+        try {
+             if (_vpcService.startVpc(this.getEntityId(), true)) {
+                 vpc = _vpcService.getVpc(getEntityId());
+             }
+        } catch (ResourceUnavailableException ex) {
+            s_logger.warn("Exception: ", ex);
+            throw new ServerApiException(BaseCmd.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
+        } catch (ConcurrentOperationException ex) {
+            s_logger.warn("Exception: ", ex);
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage());
+        } catch (InsufficientCapacityException ex) {
+            s_logger.info(ex);
+            s_logger.trace(ex);
+            throw new ServerApiException(BaseCmd.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage());
+        }
+
+        if (vpc != null) {
+            VpcResponse response = _responseGenerator.createVpcResponse(vpc);
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create VPC");
+        }
+    }
+
+    @Override
+    public String getEntityTable() {
+        return "vpc";
+    }
+
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_VPC_CREATE;
+    }
+
+
+    @Override
+    public String getEventDescription() {
+        return  "creating VPC. Id: " + getEntityId();
+    }
+
+    @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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java
new file mode 100644
index 0000000..c9e4463
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java
@@ -0,0 +1,121 @@
+// 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.vpc;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.StaticRouteResponse;
+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.vpc.StaticRoute;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "deleteStaticRoute", description="Deletes a static route", responseObject=SuccessResponse.class)
+public class DeleteStaticRouteCmd extends BaseAsyncCmd{
+    public static final Logger s_logger = Logger.getLogger(DeleteStaticRouteCmd.class.getName());
+    private static final String s_name = "deletestaticrouteresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = StaticRouteResponse.class,
+            required=true, description="the ID of the static route")
+    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_STATIC_ROUTE_DELETE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  ("Deleting static route id=" + id);
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        if (ownerId == null) {
+            StaticRoute route = _entityMgr.findById(StaticRoute.class, id);
+            if (route == null) {
+                throw new InvalidParameterValueException("Unable to find static route by id=" + id);
+            } else {
+                ownerId = route.getAccountId();
+            }
+        }
+        return ownerId;
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException {
+        UserContext.current().setEventDetails("Route Id: " + id);
+        boolean result = _vpcService.revokeStaticRoute(id);
+
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete static route");
+        }
+    }
+
+
+    @Override
+    public String getSyncObjType() {
+        return BaseAsyncCmd.vpcSyncObject;
+    }
+
+    @Override
+    public Long getSyncObjId() {
+        StaticRoute route =  _vpcService.getStaticRoute(id);
+        if (route == null) {
+            throw new InvalidParameterValueException("Invalid id is specified for the static route");
+        }
+        return route.getVpcId();
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.StaticRoute;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java
new file mode 100644
index 0000000..ed4e754
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.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.vpc;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.VpcResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.vpc.Vpc;
+import com.cloud.user.Account;
+
+@APICommand(name = "deleteVPC", description="Deletes a VPC", responseObject=SuccessResponse.class)
+public class DeleteVPCCmd extends BaseAsyncCmd{
+    public static final Logger s_logger = Logger.getLogger(DeleteVPCCmd.class.getName());
+    private static final String s_name = "deletevpcresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = VpcResponse.class,
+            required=true, description="the ID of the VPC")
+    private Long id;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getId() {
+        return id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_VPC_DELETE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "Deleting VPC id=" + getId();
+    }
+
+    @Override
+    public void execute() {
+        try {
+            boolean result = _vpcService.deleteVpc(getId());
+            if (result) {
+                SuccessResponse response = new SuccessResponse(getCommandName());
+                this.setResponseObject(response);
+            } else {
+                throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete VPC");
+            }
+        }catch (ResourceUnavailableException ex) {
+            s_logger.warn("Exception: ", ex);
+            throw new ServerApiException(BaseCmd.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
+        } catch (ConcurrentOperationException ex) {
+            s_logger.warn("Exception: ", ex);
+            throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage());
+        }
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Vpc vpc = _entityMgr.findById(Vpc.class, getId());
+        if (vpc != null) {
+            return vpc.getAccountId();
+        }
+
+        return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/c4c9d2d8/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java
new file mode 100644
index 0000000..08da25d
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java
@@ -0,0 +1,107 @@
+// 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.vpc;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.VpcResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.PrivateGatewayResponse;
+import com.cloud.network.vpc.PrivateGateway;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listPrivateGateways", description="List private gateways", responseObject=PrivateGatewayResponse.class)
+public class ListPrivateGatewaysCmd extends BaseListProjectAndAccountResourcesCmd{
+    public static final Logger s_logger = Logger.getLogger(ListPrivateGatewaysCmd.class.getName());
+
+    private static final String s_name = "listprivategatewaysresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=PrivateGatewayResponse.class,
+            description="list private gateway by id")
+    private Long id;
+
+    @Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, description="list gateways by ip address")
+    private String ipAddress;
+
+    @Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, description="list gateways by vlan")
+    private String vlan;
+
+    @Parameter(name=ApiConstants.VPC_ID, type=CommandType.UUID, entityType=VpcResponse.class,
+            description="list gateways by vpc")
+    private Long vpcId;
+
+    @Parameter(name=ApiConstants.STATE, type=CommandType.STRING, description="list gateways by state")
+    private String state;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+
+    public String getVlan() {
+        return vlan;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public Long getVpcId() {
+        return vpcId;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute() {
+        Pair<List<PrivateGateway>, Integer> gateways = _vpcService.listPrivateGateway(this);
+        ListResponse<PrivateGatewayResponse> response = new ListResponse<PrivateGatewayResponse>();
+        List<PrivateGatewayResponse> projectResponses = new ArrayList<PrivateGatewayResponse>();
+        for (PrivateGateway gateway : gateways.first()) {
+            PrivateGatewayResponse gatewayResponse = _responseGenerator.createPrivateGatewayResponse(gateway);
+            projectResponses.add(gatewayResponse);
+        }
+        response.setResponses(projectResponses, gateways.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/vpc/ListStaticRoutesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.java
new file mode 100644
index 0000000..e9fada0
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.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.vpc;
+
+import java.util.ArrayList;
+import java.util.List;
+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.PrivateGatewayResponse;
+import org.apache.cloudstack.api.response.StaticRouteResponse;
+import com.cloud.network.vpc.StaticRoute;
+import com.cloud.utils.Pair;
+import org.apache.cloudstack.api.response.VpcResponse;
+
+@APICommand(name = "listStaticRoutes", description="Lists all static routes", responseObject=StaticRouteResponse.class)
+public class ListStaticRoutesCmd extends BaseListTaggedResourcesCmd {
+    private static final String s_name = "liststaticroutesresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=StaticRouteResponse.class,
+            description="list static route by id")
+    private Long id;
+
+    @Parameter(name=ApiConstants.VPC_ID, type=CommandType.UUID, entityType=VpcResponse.class,
+            description="list static routes by vpc id")
+    private Long vpcId;
+
+    @Parameter(name=ApiConstants.GATEWAY_ID, type=CommandType.UUID, entityType=PrivateGatewayResponse.class,
+            description="list static routes by gateway id")
+    private Long gatewayId;
+
+    public Long getId() {
+        return id;
+    }
+
+    public Long getVpcId() {
+        return vpcId;
+    }
+
+    public Long getGatewayId() {
+        return gatewayId;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute(){
+        Pair<List<? extends StaticRoute>, Integer> result = _vpcService.listStaticRoutes(this);
+        ListResponse<StaticRouteResponse> response = new ListResponse<StaticRouteResponse>();
+        List<StaticRouteResponse> routeResponses = new ArrayList<StaticRouteResponse>();
+
+        for (StaticRoute route : result.first()) {
+            StaticRouteResponse ruleData = _responseGenerator.createStaticRouteResponse(route);
+            routeResponses.add(ruleData);
+        }
+        response.setResponses(routeResponses, result.second());
+        response.setResponseName(getCommandName());
+        this.setResponseObject(response);
+    }
+
+
+}