You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2012/12/04 20:32:06 UTC

[7/18] git commit: api_refactor: refactor volume apis

api_refactor: refactor volume apis

Signed-off-by: Rohit Yadav <bh...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/8773fc2a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/8773fc2a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/8773fc2a

Branch: refs/heads/api_refactoring
Commit: 8773fc2a55ee842594130d7fa066968f80963929
Parents: 25b5aad
Author: Rohit Yadav <bh...@apache.org>
Authored: Tue Dec 4 11:20:48 2012 -0800
Committer: Rohit Yadav <bh...@apache.org>
Committed: Tue Dec 4 11:20:48 2012 -0800

----------------------------------------------------------------------
 .../com/cloud/api/commands/AttachVolumeCmd.java    |  131 -----------
 .../com/cloud/api/commands/CreateVolumeCmd.java    |  175 ---------------
 .../com/cloud/api/commands/DeleteVolumeCmd.java    |   90 --------
 .../com/cloud/api/commands/DetachVolumeCmd.java    |  142 ------------
 .../com/cloud/api/commands/ExtractVolumeCmd.java   |  155 -------------
 api/src/com/cloud/api/commands/ListVolumesCmd.java |  135 -----------
 .../com/cloud/api/commands/MigrateVolumeCmd.java   |  106 ---------
 .../com/cloud/api/commands/UploadVolumeCmd.java    |  147 ------------
 api/src/com/cloud/server/ManagementService.java    |    2 +-
 api/src/com/cloud/storage/StorageService.java      |    6 +-
 api/src/com/cloud/vm/UserVmService.java            |    4 +-
 .../api/user/volume/command/AttachVolumeCmd.java   |  131 +++++++++++
 .../api/user/volume/command/CreateVolumeCmd.java   |  175 +++++++++++++++
 .../api/user/volume/command/DeleteVolumeCmd.java   |   90 ++++++++
 .../api/user/volume/command/DetachVolumeCmd.java   |  142 ++++++++++++
 .../api/user/volume/command/ExtractVolumeCmd.java  |  155 +++++++++++++
 .../api/user/volume/command/ListVolumesCmd.java    |  135 +++++++++++
 .../api/user/volume/command/MigrateVolumeCmd.java  |  106 +++++++++
 .../api/user/volume/command/UploadVolumeCmd.java   |  147 ++++++++++++
 client/tomcatconf/commands.properties.in           |   16 +-
 .../cloud/baremetal/BareMetalVmManagerImpl.java    |    4 +-
 .../src/com/cloud/server/ManagementServerImpl.java |    2 +-
 .../src/com/cloud/storage/StorageManagerImpl.java  |    6 +-
 .../com/cloud/storage/upload/UploadListener.java   |    2 +-
 server/src/com/cloud/vm/UserVmManagerImpl.java     |    4 +-
 .../test/com/cloud/vm/MockUserVmManagerImpl.java   |    4 +-
 26 files changed, 1106 insertions(+), 1106 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8773fc2a/api/src/com/cloud/api/commands/AttachVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/AttachVolumeCmd.java b/api/src/com/cloud/api/commands/AttachVolumeCmd.java
deleted file mode 100755
index 752935b..0000000
--- a/api/src/com/cloud/api/commands/AttachVolumeCmd.java
+++ /dev/null
@@ -1,131 +0,0 @@
-// 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 com.cloud.api.commands;
-
-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.IdentityMapper;
-import org.apache.cloudstack.api.Implementation;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import com.cloud.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;
-
-@Implementation(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;
-
-    @IdentityMapper(entityTableName="volumes")
-    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the ID of the disk volume")
-    private Long id;
-
-    @IdentityMapper(entityTableName="vm_instance")
-    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.LONG, 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/8773fc2a/api/src/com/cloud/api/commands/CreateVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/CreateVolumeCmd.java b/api/src/com/cloud/api/commands/CreateVolumeCmd.java
deleted file mode 100644
index 86e10dd..0000000
--- a/api/src/com/cloud/api/commands/CreateVolumeCmd.java
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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 com.cloud.api.commands;
-
-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.IdentityMapper;
-import org.apache.cloudstack.api.Implementation;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import com.cloud.api.response.VolumeResponse;
-import com.cloud.async.AsyncJob;
-import com.cloud.event.EventTypes;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.storage.Volume;
-import com.cloud.user.UserContext;
-
-@Implementation(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;
-
-    @IdentityMapper(entityTableName="projects")
-    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.LONG, description="the project associated with the volume. Mutually exclusive with account parameter")
-    private Long projectId;
-
-    @IdentityMapper(entityTableName="domain")
-    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, 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;
-
-    @IdentityMapper(entityTableName="disk_offering")
-    @Parameter(name=ApiConstants.DISK_OFFERING_ID,required = false, type=CommandType.LONG, 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;
-
-    @IdentityMapper(entityTableName="snapshots")
-    @Parameter(name=ApiConstants.SNAPSHOT_ID, type=CommandType.LONG, description="the snapshot ID for the disk volume. Either diskOfferingId or snapshotId must be passed in.")
-    private Long snapshotId;
-
-    @IdentityMapper(entityTableName="data_center")
-    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, 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
-            response.setSnapshotId(getSnapshotId());  // 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/8773fc2a/api/src/com/cloud/api/commands/DeleteVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/DeleteVolumeCmd.java b/api/src/com/cloud/api/commands/DeleteVolumeCmd.java
deleted file mode 100644
index 7692cae..0000000
--- a/api/src/com/cloud/api/commands/DeleteVolumeCmd.java
+++ /dev/null
@@ -1,90 +0,0 @@
-// 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 com.cloud.api.commands;
-
-import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.IdentityMapper;
-import org.apache.cloudstack.api.Implementation;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import com.cloud.api.response.SuccessResponse;
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.storage.Volume;
-import com.cloud.user.Account;
-import com.cloud.user.UserContext;
-
-@Implementation(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 /////////////////////
-    /////////////////////////////////////////////////////
-
-    @IdentityMapper(entityTableName="volumes")
-    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, 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/8773fc2a/api/src/com/cloud/api/commands/DetachVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/DetachVolumeCmd.java b/api/src/com/cloud/api/commands/DetachVolumeCmd.java
deleted file mode 100755
index 377bc0e..0000000
--- a/api/src/com/cloud/api/commands/DetachVolumeCmd.java
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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 com.cloud.api.commands;
-
-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.IdentityMapper;
-import org.apache.cloudstack.api.Implementation;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import com.cloud.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;
-
-@Implementation(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 /////////////////////
-    /////////////////////////////////////////////////////
-
-    @IdentityMapper(entityTableName="volumes")
-    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, 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;
-
-    @IdentityMapper(entityTableName="vm_instance")
-    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.LONG, 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/8773fc2a/api/src/com/cloud/api/commands/ExtractVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/ExtractVolumeCmd.java b/api/src/com/cloud/api/commands/ExtractVolumeCmd.java
deleted file mode 100755
index 4de2175..0000000
--- a/api/src/com/cloud/api/commands/ExtractVolumeCmd.java
+++ /dev/null
@@ -1,155 +0,0 @@
-// 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 com.cloud.api.commands;
-
-import java.net.URISyntaxException;
-
-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.IdentityMapper;
-import org.apache.cloudstack.api.Implementation;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import com.cloud.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;
-
-@Implementation(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 /////////////////////
-    /////////////////////////////////////////////////////
-
-    @IdentityMapper(entityTableName="volumes")
-    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, 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;
-
-    @IdentityMapper(entityTableName="data_center")
-    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, 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");
-                response.setIdentityTableName("volumes");
-                response.setId(id);
-                response.setName(_entityMgr.findById(Volume.class, id).getName());
-                response.setZoneId(zoneId);
-                response.setZoneName(_entityMgr.findById(DataCenter.class, zoneId).getName());
-                response.setMode(mode);
-                response.setUploadId(uploadId);
-                response.setState(uploadInfo.getUploadState().toString());
-                response.setAccountId(getEntityOwnerId());
-                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/8773fc2a/api/src/com/cloud/api/commands/ListVolumesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/ListVolumesCmd.java b/api/src/com/cloud/api/commands/ListVolumesCmd.java
deleted file mode 100755
index fc1f8a1..0000000
--- a/api/src/com/cloud/api/commands/ListVolumesCmd.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// 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 com.cloud.api.commands;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
-import org.apache.cloudstack.api.IdentityMapper;
-import org.apache.cloudstack.api.Implementation;
-import org.apache.cloudstack.api.Parameter;
-import com.cloud.api.response.ListResponse;
-import com.cloud.api.response.VolumeResponse;
-import com.cloud.async.AsyncJob;
-import com.cloud.storage.Volume;
-import com.cloud.utils.Pair;
-
-
-@Implementation(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 /////////////////////
-    /////////////////////////////////////////////////////
-
-    @IdentityMapper(entityTableName="host")
-    @Parameter(name=ApiConstants.HOST_ID, type=CommandType.LONG, description="list volumes on specified host")
-    private Long hostId;
-
-    @IdentityMapper(entityTableName="volumes")
-    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, 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;
-
-    @IdentityMapper(entityTableName="host_pod_ref")
-    @Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, 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;
-
-    @IdentityMapper(entityTableName="vm_instance")
-    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.LONG, description="the ID of the virtual machine")
-    private Long virtualMachineId;
-
-    @IdentityMapper(entityTableName="data_center")
-    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, 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(){
-        Pair<List<? extends Volume>, Integer> volumes = _storageService.searchForVolumes(this);
-
-        ListResponse<VolumeResponse> response = new ListResponse<VolumeResponse>();
-        List<VolumeResponse> volResponses = new ArrayList<VolumeResponse>();
-        for (Volume volume : volumes.first()) {
-            VolumeResponse volResponse = _responseGenerator.createVolumeResponse(volume);
-            volResponse.setObjectName("volume");
-            volResponses.add(volResponse);
-        }
-
-        response.setResponses(volResponses, volumes.second());
-        response.setResponseName(getCommandName());
-        this.setResponseObject(response);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8773fc2a/api/src/com/cloud/api/commands/MigrateVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/MigrateVolumeCmd.java b/api/src/com/cloud/api/commands/MigrateVolumeCmd.java
deleted file mode 100644
index 7ad8448..0000000
--- a/api/src/com/cloud/api/commands/MigrateVolumeCmd.java
+++ /dev/null
@@ -1,106 +0,0 @@
-// 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 com.cloud.api.commands;
-
-import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseAsyncCmd;
-import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.IdentityMapper;
-import org.apache.cloudstack.api.Implementation;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import com.cloud.api.response.VolumeResponse;
-import com.cloud.event.EventTypes;
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.storage.Volume;
-import com.cloud.user.Account;
-
-
-@Implementation(description="Migrate volume", responseObject=VolumeResponse.class, since="3.0.0")
-public class MigrateVolumeCmd extends BaseAsyncCmd {
-    private static final String s_name = "migratevolumeresponse";
-
-     /////////////////////////////////////////////////////
-    //////////////// API parameters /////////////////////
-    /////////////////////////////////////////////////////
-
-    @IdentityMapper(entityTableName="volumes")
-    @Parameter(name=ApiConstants.VOLUME_ID, type=CommandType.LONG, required=true, description="the ID of the volume")
-    private Long volumeId;
-
-    @IdentityMapper(entityTableName="storage_pool")
-    @Parameter(name=ApiConstants.STORAGE_ID, type=CommandType.LONG, 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/8773fc2a/api/src/com/cloud/api/commands/UploadVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/UploadVolumeCmd.java b/api/src/com/cloud/api/commands/UploadVolumeCmd.java
deleted file mode 100755
index 600dfa0..0000000
--- a/api/src/com/cloud/api/commands/UploadVolumeCmd.java
+++ /dev/null
@@ -1,147 +0,0 @@
-// 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 com.cloud.api.commands;
-
-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.IdentityMapper;
-import org.apache.cloudstack.api.Implementation;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import com.cloud.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;
-
-@Implementation(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;
-
-    @IdentityMapper(entityTableName="data_center")
-    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required=true, description="the ID of the zone the volume is to be hosted on")
-    private Long zoneId;
-
-    @IdentityMapper(entityTableName="domain")
-    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, 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/8773fc2a/api/src/com/cloud/server/ManagementService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/server/ManagementService.java b/api/src/com/cloud/server/ManagementService.java
index 52ba29c..e2bc484 100755
--- a/api/src/com/cloud/server/ManagementService.java
+++ b/api/src/com/cloud/server/ManagementService.java
@@ -32,7 +32,7 @@ import org.apache.cloudstack.api.user.offering.command.ListServiceOfferingsCmd;
 import org.apache.cloudstack.api.user.ssh.command.CreateSSHKeyPairCmd;
 import org.apache.cloudstack.api.user.ssh.command.DeleteSSHKeyPairCmd;
 import com.cloud.api.commands.DestroySystemVmCmd;
-import com.cloud.api.commands.ExtractVolumeCmd;
+import org.apache.cloudstack.api.user.volume.command.ExtractVolumeCmd;
 import org.apache.cloudstack.api.user.template.command.ListTemplatesCmd;
 import org.apache.cloudstack.api.user.template.command.UpdateTemplateCmd;
 import org.apache.cloudstack.api.user.vm.command.GetVMPasswordCmd;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8773fc2a/api/src/com/cloud/storage/StorageService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/StorageService.java b/api/src/com/cloud/storage/StorageService.java
index b05bc15..9197bf2 100644
--- a/api/src/com/cloud/storage/StorageService.java
+++ b/api/src/com/cloud/storage/StorageService.java
@@ -21,11 +21,11 @@ import java.util.List;
 
 import com.cloud.api.commands.CancelPrimaryStorageMaintenanceCmd;
 import com.cloud.api.commands.CreateStoragePoolCmd;
-import com.cloud.api.commands.CreateVolumeCmd;
+import org.apache.cloudstack.api.user.volume.command.CreateVolumeCmd;
 import com.cloud.api.commands.DeletePoolCmd;
-import com.cloud.api.commands.ListVolumesCmd;
+import org.apache.cloudstack.api.user.volume.command.ListVolumesCmd;
 import com.cloud.api.commands.UpdateStoragePoolCmd;
-import com.cloud.api.commands.UploadVolumeCmd;
+import org.apache.cloudstack.api.user.volume.command.UploadVolumeCmd;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.InsufficientCapacityException;
 import com.cloud.exception.PermissionDeniedException;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8773fc2a/api/src/com/cloud/vm/UserVmService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java
index 8c897d3..04fa600 100755
--- a/api/src/com/cloud/vm/UserVmService.java
+++ b/api/src/com/cloud/vm/UserVmService.java
@@ -22,13 +22,13 @@ import java.util.Map;
 import javax.naming.InsufficientResourcesException;
 
 import org.apache.cloudstack.api.admin.vm.command.AssignVMCmd;
-import com.cloud.api.commands.AttachVolumeCmd;
+import org.apache.cloudstack.api.user.volume.command.AttachVolumeCmd;
 import org.apache.cloudstack.api.user.template.command.CreateTemplateCmd;
 import org.apache.cloudstack.api.user.vmgroup.command.CreateVMGroupCmd;
 import org.apache.cloudstack.api.user.vmgroup.command.DeleteVMGroupCmd;
 import org.apache.cloudstack.api.user.vm.command.DeployVMCmd;
 import org.apache.cloudstack.api.user.vm.command.DestroyVMCmd;
-import com.cloud.api.commands.DetachVolumeCmd;
+import org.apache.cloudstack.api.user.volume.command.DetachVolumeCmd;
 import org.apache.cloudstack.api.user.vm.command.ListVMsCmd;
 import org.apache.cloudstack.api.user.vm.command.RebootVMCmd;
 import org.apache.cloudstack.api.admin.vm.command.RecoverVMCmd;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8773fc2a/api/src/org/apache/cloudstack/api/user/volume/command/AttachVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/user/volume/command/AttachVolumeCmd.java b/api/src/org/apache/cloudstack/api/user/volume/command/AttachVolumeCmd.java
new file mode 100755
index 0000000..5dcd916
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/user/volume/command/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.user.volume.command;
+
+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.IdentityMapper;
+import org.apache.cloudstack.api.Implementation;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import com.cloud.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;
+
+@Implementation(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;
+
+    @IdentityMapper(entityTableName="volumes")
+    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the ID of the disk volume")
+    private Long id;
+
+    @IdentityMapper(entityTableName="vm_instance")
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.LONG, 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/8773fc2a/api/src/org/apache/cloudstack/api/user/volume/command/CreateVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/user/volume/command/CreateVolumeCmd.java b/api/src/org/apache/cloudstack/api/user/volume/command/CreateVolumeCmd.java
new file mode 100644
index 0000000..acc4598
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/user/volume/command/CreateVolumeCmd.java
@@ -0,0 +1,175 @@
+// 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.user.volume.command;
+
+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.IdentityMapper;
+import org.apache.cloudstack.api.Implementation;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import com.cloud.api.response.VolumeResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.storage.Volume;
+import com.cloud.user.UserContext;
+
+@Implementation(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;
+
+    @IdentityMapper(entityTableName="projects")
+    @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.LONG, description="the project associated with the volume. Mutually exclusive with account parameter")
+    private Long projectId;
+
+    @IdentityMapper(entityTableName="domain")
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.LONG, 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;
+
+    @IdentityMapper(entityTableName="disk_offering")
+    @Parameter(name=ApiConstants.DISK_OFFERING_ID,required = false, type=CommandType.LONG, 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;
+
+    @IdentityMapper(entityTableName="snapshots")
+    @Parameter(name=ApiConstants.SNAPSHOT_ID, type=CommandType.LONG, description="the snapshot ID for the disk volume. Either diskOfferingId or snapshotId must be passed in.")
+    private Long snapshotId;
+
+    @IdentityMapper(entityTableName="data_center")
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, 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
+            response.setSnapshotId(getSnapshotId());  // 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/8773fc2a/api/src/org/apache/cloudstack/api/user/volume/command/DeleteVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/user/volume/command/DeleteVolumeCmd.java b/api/src/org/apache/cloudstack/api/user/volume/command/DeleteVolumeCmd.java
new file mode 100644
index 0000000..d6e44c3
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/user/volume/command/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.user.volume.command;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.IdentityMapper;
+import org.apache.cloudstack.api.Implementation;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import com.cloud.api.response.SuccessResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.storage.Volume;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@Implementation(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 /////////////////////
+    /////////////////////////////////////////////////////
+
+    @IdentityMapper(entityTableName="volumes")
+    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, 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/8773fc2a/api/src/org/apache/cloudstack/api/user/volume/command/DetachVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/user/volume/command/DetachVolumeCmd.java b/api/src/org/apache/cloudstack/api/user/volume/command/DetachVolumeCmd.java
new file mode 100755
index 0000000..03ffe14
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/user/volume/command/DetachVolumeCmd.java
@@ -0,0 +1,142 @@
+// 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.user.volume.command;
+
+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.IdentityMapper;
+import org.apache.cloudstack.api.Implementation;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import com.cloud.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;
+
+@Implementation(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 /////////////////////
+    /////////////////////////////////////////////////////
+
+    @IdentityMapper(entityTableName="volumes")
+    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, 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;
+
+    @IdentityMapper(entityTableName="vm_instance")
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.LONG, 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/8773fc2a/api/src/org/apache/cloudstack/api/user/volume/command/ExtractVolumeCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/user/volume/command/ExtractVolumeCmd.java b/api/src/org/apache/cloudstack/api/user/volume/command/ExtractVolumeCmd.java
new file mode 100755
index 0000000..469b486
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/user/volume/command/ExtractVolumeCmd.java
@@ -0,0 +1,155 @@
+// 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.user.volume.command;
+
+import java.net.URISyntaxException;
+
+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.IdentityMapper;
+import org.apache.cloudstack.api.Implementation;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import com.cloud.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;
+
+@Implementation(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 /////////////////////
+    /////////////////////////////////////////////////////
+
+    @IdentityMapper(entityTableName="volumes")
+    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, 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;
+
+    @IdentityMapper(entityTableName="data_center")
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, 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");
+                response.setIdentityTableName("volumes");
+                response.setId(id);
+                response.setName(_entityMgr.findById(Volume.class, id).getName());
+                response.setZoneId(zoneId);
+                response.setZoneName(_entityMgr.findById(DataCenter.class, zoneId).getName());
+                response.setMode(mode);
+                response.setUploadId(uploadId);
+                response.setState(uploadInfo.getUploadState().toString());
+                response.setAccountId(getEntityOwnerId());
+                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/8773fc2a/api/src/org/apache/cloudstack/api/user/volume/command/ListVolumesCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/user/volume/command/ListVolumesCmd.java b/api/src/org/apache/cloudstack/api/user/volume/command/ListVolumesCmd.java
new file mode 100755
index 0000000..1d6aac8
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/user/volume/command/ListVolumesCmd.java
@@ -0,0 +1,135 @@
+// 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.user.volume.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
+import org.apache.cloudstack.api.IdentityMapper;
+import org.apache.cloudstack.api.Implementation;
+import org.apache.cloudstack.api.Parameter;
+import com.cloud.api.response.ListResponse;
+import com.cloud.api.response.VolumeResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.storage.Volume;
+import com.cloud.utils.Pair;
+
+
+@Implementation(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 /////////////////////
+    /////////////////////////////////////////////////////
+
+    @IdentityMapper(entityTableName="host")
+    @Parameter(name=ApiConstants.HOST_ID, type=CommandType.LONG, description="list volumes on specified host")
+    private Long hostId;
+
+    @IdentityMapper(entityTableName="volumes")
+    @Parameter(name=ApiConstants.ID, type=CommandType.LONG, 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;
+
+    @IdentityMapper(entityTableName="host_pod_ref")
+    @Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, 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;
+
+    @IdentityMapper(entityTableName="vm_instance")
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.LONG, description="the ID of the virtual machine")
+    private Long virtualMachineId;
+
+    @IdentityMapper(entityTableName="data_center")
+    @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, 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(){
+        Pair<List<? extends Volume>, Integer> volumes = _storageService.searchForVolumes(this);
+
+        ListResponse<VolumeResponse> response = new ListResponse<VolumeResponse>();
+        List<VolumeResponse> volResponses = new ArrayList<VolumeResponse>();
+        for (Volume volume : volumes.first()) {
+            VolumeResponse volResponse = _responseGenerator.createVolumeResponse(volume);
+            volResponse.setObjectName("volume");
+            volResponses.add(volResponse);
+        }
+
+        response.setResponses(volResponses, volumes.second());
+        response.setResponseName(getCommandName());
+        this.setResponseObject(response);
+    }
+}