Return-Path: X-Original-To: apmail-cloudstack-dev-archive@www.apache.org Delivered-To: apmail-cloudstack-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 83ABAFDEA for ; Fri, 19 Apr 2013 23:28:10 +0000 (UTC) Received: (qmail 12392 invoked by uid 500); 19 Apr 2013 23:28:10 -0000 Delivered-To: apmail-cloudstack-dev-archive@cloudstack.apache.org Received: (qmail 12354 invoked by uid 500); 19 Apr 2013 23:28:10 -0000 Mailing-List: contact dev-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list dev@cloudstack.apache.org Received: (qmail 12341 invoked by uid 99); 19 Apr 2013 23:28:09 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 19 Apr 2013 23:28:09 +0000 X-ASF-Spam-Status: No, hits=-0.7 required=5.0 tests=RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS,URIBL_DBL_REDIR X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of Jessica.Tomechak@citrix.com designates 66.165.176.63 as permitted sender) Received: from [66.165.176.63] (HELO SMTP02.CITRIX.COM) (66.165.176.63) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 19 Apr 2013 23:28:05 +0000 X-IronPort-AV: E=Sophos;i="4.87,512,1363132800"; d="scan'208";a="19591745" Received: from sjcpmailmx01.citrite.net ([10.216.14.74]) by FTLPIPO02.CITRIX.COM with ESMTP/TLS/RC4-MD5; 19 Apr 2013 23:27:41 +0000 Received: from SJCPMAILBOX01.citrite.net ([10.216.4.72]) by SJCPMAILMX01.citrite.net ([10.216.14.74]) with mapi; Fri, 19 Apr 2013 16:27:41 -0700 From: Jessica Tomechak To: Pranav Saxena , "dev@cloudstack.apache.org" CC: Sudha Ponnaganti , Srikanteswararao Talluri Date: Fri, 19 Apr 2013 16:27:38 -0700 Subject: RE: [UI support] Storage motion for Xenserver - Merged Thread-Topic: [UI support] Storage motion for Xenserver - Merged Thread-Index: Ac49EgOWv1Gg3HUcR3uYrrLH3P/KuwAQqllQ Message-ID: <7A92FF96DF135843B4B608FB576BFC3E01421CA793B3@SJCPMAILBOX01.citrite.net> References: <2307598D4FCF004D81B2C8892AA9A911043321@SINPEX01CL01.citrite.net> In-Reply-To: <2307598D4FCF004D81B2C8892AA9A911043321@SINPEX01CL01.citrite.net> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Virus-Checked: Checked by ClamAV on apache.org Pranav, thanks for the notification. I also took the liberty of making the = UI bug a sub-task of the main eng bug. https://issues.apache.org/jira/browse/CLOUDSTACK-2108 Thanks, Jessica T. CloudStack Tech Pubs How to File a Documentation Bug -----Original Message----- From: Pranav Saxena Sent: Friday, April 19, 2013 8:27 AM To: dev@cloudstack.apache.org Cc: Sudha Ponnaganti; Jessica Tomechak; Srikanteswararao Talluri Subject: [UI support] Storage motion for Xenserver - Merged UI support for enabling storage motion for Xenserver has been merged to asf= /master . Request the QA team and Docs team to pick this feature up for the= ir respective tasks. Thanks, Pranav -----Original Message----- From: aprateek@apache.org [mailto:aprateek@apache.org] Sent: Friday, April 19, 2013 11:45 AM To: commits@cloudstack.apache.org Subject: [4/4] git commit: updated refs/heads/master to 21ce3be Storage motion for Xenserver changes: 1. Implemented Api findStoragePoolsFo= rMigration. Added a new response objects to list storage pools available fo= r migration. 2. Updated migrateVolume api for allowing migrating volumes of= running vms. These changes are integrated into the latest storage refactor= ing changes. 3. Added the implementation for findHostsForMigration api. It = lists the hosts to which an instance can be migrated, including hosts from = within and across clusters to which an instance may be migrated with storag= e motion. The work of migrating a volume of a running vm is also done in co= pyAsync. 4. Updated the listHosts api for backward compatibility. 5. Added = the implementation for migrateVirtualMachineWithVolume api. It migrates an = instance with its volumes within a cluster and also across clusters. Also i= ntroduced a new XenServerStorageMotionStrategy for migrating volumes of a v= m. When a vm is being migrated with its volumes, the vm is put in migrating= state and a request is send to the volume manager to migrate the vm and its volumes. Volume mana= ger calls into the volume service which forwards the request to data motion= service after moving all the volumes to migrating state. Data motion servi= ce enumerates the strategies and the request reaches the XenServerStorageMo= tionStrategy. It calls in to the resource to complete the operation. 6. Res= olved an issue where storage xenmotion of 2nd VM created from the same temp= late to a host was failing with duplicate_vm exception. Made changes to rem= ove the mac_seed key value pair from other_config when vms are created. Thi= s is was storage motion to fail. 7. Updated the db upgrade schema script. 8= . Added the right permissions in commands.properties 9. Marvin tests for te= sting storage motion. Following scenarios are tested. 9.1. A virtual machin= e is migrated to another host. Its volumes are also migrated to another sto= rage pool. 9.2. Just the volumes of a vm are migrated to another storage po= ol while the vm continu es to run on the same host. 10. Unit tests for testing migration of a vm w= ith its volumes. Signed-off-by: Abhinandan Prateek Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/21ce3bef Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/21ce3bef Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/21ce3bef Branch: refs/heads/master Commit: 21ce3befc8ea9e1a6de449a21499a50ff141a183 Parents: eae22d2 Author: Devdeep Singh Authored: Mon Apr 15 11:42:18 2013 +0530 Committer: Abhinandan Prateek Committed: Fri Apr 19 11:36:42 2013 +0530 ---------------------------------------------------------------------- .../cloud/agent/api/MigrateWithStorageAnswer.java | 39 ++ .../cloud/agent/api/MigrateWithStorageCommand.java | 45 ++ .../api/MigrateWithStorageCompleteAnswer.java | 38 ++ .../api/MigrateWithStorageCompleteCommand.java | 36 ++ .../agent/api/MigrateWithStorageReceiveAnswer.java | 55 +++ .../api/MigrateWithStorageReceiveCommand.java | 45 ++ .../agent/api/MigrateWithStorageSendAnswer.java | 39 ++ .../agent/api/MigrateWithStorageSendCommand.java | 58 +++ .../agent/api/storage/MigrateVolumeAnswer.java | 38 ++ .../agent/api/storage/MigrateVolumeCommand.java | 51 ++ .../cloud/hypervisor/HypervisorCapabilities.java | 2 + api/src/com/cloud/server/ManagementService.java | 19 +- api/src/com/cloud/vm/UserVmService.java | 27 ++ .../org/apache/cloudstack/api/ApiConstants.java | 2 + .../apache/cloudstack/api/ResponseGenerator.java | 6 + .../admin/host/FindHostsForMigrationCmd.java | 107 +++++ .../api/command/admin/host/ListHostsCmd.java | 7 +- .../storage/FindStoragePoolsForMigrationCmd.java | 98 ++++ .../vm/MigrateVirtualMachineWithVolumeCmd.java | 160 +++++++ .../api/command/user/volume/MigrateVolumeCmd.java | 8 + .../api/response/HostForMigrationResponse.java | 365 +++++++++++++++ .../cloudstack/api/response/HostResponse.java | 1 - .../response/StoragePoolForMigrationResponse.java | 248 ++++++++++ .../api/response/StoragePoolResponse.java | 3 - client/tomcatconf/applicationContext.xml.in | 1 + client/tomcatconf/commands.properties.in | 3 + .../cloud/hypervisor/HypervisorCapabilitiesVO.java | 24 +- .../api/storage/ObjectInDataStoreStateMachine.java | 2 + .../subsystem/api/storage/VolumeService.java | 7 +- .../image/motion/DefaultImageMotionStrategy.java | 18 + .../storage/test/MockStorageMotionStrategy.java | 19 + .../storage/motion/AncientDataMotionStrategy.java | 84 ++++- .../storage/motion/DataMotionService.java | 9 + .../storage/motion/DataMotionServiceImpl.java | 16 + .../storage/motion/DataMotionStrategy.java | 10 + .../cloudstack/storage/volume/VolumeObject.java | 2 + .../storage/volume/VolumeServiceImpl.java | 166 +++++++- .../manager/allocator/impl/RandomAllocator.java | 56 +++ .../xen/resource/CitrixResourceBase.java | 4 +- .../xen/resource/XenServer56FP1Resource.java | 1 + .../xen/resource/XenServer610Resource.java | 359 ++++++++++++++- .../motion/XenServerStorageMotionStrategy.java | 239 ++++++++++ .../agent/manager/allocator/HostAllocator.java | 23 +- .../manager/allocator/impl/FirstFitAllocator.java | 47 ++ .../manager/allocator/impl/TestingAllocator.java | 7 + server/src/com/cloud/api/ApiDBUtils.java | 19 + server/src/com/cloud/api/ApiResponseHelper.java | 27 +- .../com/cloud/api/query/ViewResponseHelper.java | 37 ++ .../src/com/cloud/api/query/dao/HostJoinDao.java | 5 + .../com/cloud/api/query/dao/HostJoinDaoImpl.java | 135 ++++++- .../cloud/api/query/dao/StoragePoolJoinDao.java | 6 + .../api/query/dao/StoragePoolJoinDaoImpl.java | 59 +++- .../src/com/cloud/server/ManagementServerImpl.java | 284 ++++++++++-- server/src/com/cloud/storage/VolumeManager.java | 8 + .../src/com/cloud/storage/VolumeManagerImpl.java | 112 +++++- server/src/com/cloud/vm/UserVmManagerImpl.java | 123 +++++ server/src/com/cloud/vm/VirtualMachineManager.java | 4 + .../com/cloud/vm/VirtualMachineManagerImpl.java | 210 +++++++++- .../test/com/cloud/vm/MockUserVmManagerImpl.java | 8 + .../cloud/vm/MockVirtualMachineManagerImpl.java | 10 + .../cloud/vm/VirtualMachineManagerImplTest.java | 231 +++++++++- setup/db/db/schema-410to420.sql | 2 + test/integration/component/test_storage_motion.py | 298 ++++++++++++ tools/marvin/marvin/integration/lib/base.py | 22 + 64 files changed, 4109 insertions(+), 85 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/agent/api/MigrateWithStorageAnswer.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageAnswer.java b/ap= i/src/com/cloud/agent/api/MigrateWithStorageAnswer.java new file mode 100644 index 0000000..06aff32 --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageAnswer.java @@ -0,0 +1,39 @@ +// 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.agent.api; + +import java.util.List; +import com.cloud.agent.api.to.VolumeTO; + +public class MigrateWithStorageAnswer extends Answer { + + List volumeTos; + + public MigrateWithStorageAnswer(MigrateWithStorageCommand cmd, Excepti= on ex) { + super(cmd, ex); + volumeTos =3D null; + } + + public MigrateWithStorageAnswer(MigrateWithStorageCommand cmd, List volumeTos) { + super(cmd, true, null); + this.volumeTos =3D volumeTos; + } + + public List getVolumeTos() { + return volumeTos; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/agent/api/MigrateWithStorageCommand.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageCommand.java b/a= pi/src/com/cloud/agent/api/MigrateWithStorageCommand.java new file mode 100644 index 0000000..058aa15 --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageCommand.java @@ -0,0 +1,45 @@ +// 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.agent.api; + +import java.util.Map; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.api.to.StorageFilerTO; + +public class MigrateWithStorageCommand extends Command { + VirtualMachineTO vm; + Map volumeToFiler; + + public MigrateWithStorageCommand(VirtualMachineTO vm, Map volumeToFiler) { + this.vm =3D vm; + this.volumeToFiler =3D volumeToFiler; + } + + public VirtualMachineTO getVirtualMachine() { + return vm; + } + + public Map getVolumeToFiler() { + return volumeToFiler; + } + + @Override + public boolean executeInSequence() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/agent/api/MigrateWithStorageCompleteAnswer.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageCompleteAnswer.j= ava b/api/src/com/cloud/agent/api/MigrateWithStorageCompleteAnswer.java new file mode 100644 index 0000000..920cf48 --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageCompleteAnswer.java @@ -0,0 +1,38 @@ +// 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.agent.api; + +import java.util.List; +import com.cloud.agent.api.to.VolumeTO; + +public class MigrateWithStorageCompleteAnswer extends Answer { + List volumeTos; + + public MigrateWithStorageCompleteAnswer(MigrateWithStorageCompleteComm= and cmd, Exception ex) { + super(cmd, ex); + volumeTos =3D null; + } + + public MigrateWithStorageCompleteAnswer(MigrateWithStorageCompleteComm= and cmd, List volumeTos) { + super(cmd, true, null); + this.volumeTos =3D volumeTos; + } + + public List getVolumeTos() { + return volumeTos; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/agent/api/MigrateWithStorageCompleteCommand.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageCompleteCommand.= java b/api/src/com/cloud/agent/api/MigrateWithStorageCompleteCommand.java new file mode 100644 index 0000000..1303c07 --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageCompleteCommand.java @@ -0,0 +1,36 @@ +// 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.agent.api; + +import com.cloud.agent.api.to.VirtualMachineTO; + +public class MigrateWithStorageCompleteCommand extends Command { + VirtualMachineTO vm; + + public MigrateWithStorageCompleteCommand(VirtualMachineTO vm) { + this.vm =3D vm; + } + + public VirtualMachineTO getVirtualMachine() { + return vm; + } + + @Override + public boolean executeInSequence() { + return false; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/agent/api/MigrateWithStorageReceiveAnswer.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.ja= va b/api/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java new file mode 100644 index 0000000..3bf521c --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java @@ -0,0 +1,55 @@ +// 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.agent.api; + +import java.util.Map; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.api.to.NicTO; + +public class MigrateWithStorageReceiveAnswer extends Answer { + + Map volumeToSr; + Map nicToNetwork; + Map token; + + public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveComman= d cmd, Exception ex) { + super(cmd, ex); + volumeToSr =3D null; + nicToNetwork =3D null; + token =3D null; + } + + public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveComman= d cmd, Map volumeToSr, + Map nicToNetwork, Map token) { + super(cmd, true, null); + this.volumeToSr =3D volumeToSr; + this.nicToNetwork =3D nicToNetwork; + this.token =3D token; + } + + public Map getVolumeToSr() { + return volumeToSr; + } + + public Map getNicToNetwork() { + return nicToNetwork; + } + + public Map getToken() { + return token; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/agent/api/MigrateWithStorageReceiveCommand.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageReceiveCommand.j= ava b/api/src/com/cloud/agent/api/MigrateWithStorageReceiveCommand.java new file mode 100644 index 0000000..df67405 --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageReceiveCommand.java @@ -0,0 +1,45 @@ +// 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.agent.api; + +import java.util.Map; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.api.to.StorageFilerTO; + +public class MigrateWithStorageReceiveCommand extends Command { + VirtualMachineTO vm; + Map volumeToFiler; + + public MigrateWithStorageReceiveCommand(VirtualMachineTO vm, Map volumeToFiler) { + this.vm =3D vm; + this.volumeToFiler =3D volumeToFiler; + } + + public VirtualMachineTO getVirtualMachine() { + return vm; + } + + public Map getVolumeToFiler() { + return volumeToFiler; + } + + @Override + public boolean executeInSequence() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/agent/api/MigrateWithStorageSendAnswer.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageSendAnswer.java = b/api/src/com/cloud/agent/api/MigrateWithStorageSendAnswer.java new file mode 100644 index 0000000..7cf641f --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageSendAnswer.java @@ -0,0 +1,39 @@ +// 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.agent.api; + +import java.util.Set; +import com.cloud.agent.api.to.VolumeTO; + +public class MigrateWithStorageSendAnswer extends Answer { + + Set volumeToSet; + + public MigrateWithStorageSendAnswer(MigrateWithStorageSendCommand cmd,= Exception ex) { + super(cmd, ex); + volumeToSet =3D null; + } + + public MigrateWithStorageSendAnswer(MigrateWithStorageSendCommand cmd,= Set volumeToSet) { + super(cmd, true, null); + this.volumeToSet =3D volumeToSet; + } + + public Set getVolumeToSet() { + return volumeToSet; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/agent/api/MigrateWithStorageSendCommand.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java= b/api/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java new file mode 100644 index 0000000..d10db30 --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java @@ -0,0 +1,58 @@ +// 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.agent.api; + +import java.util.Map; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.api.to.NicTO; + +public class MigrateWithStorageSendCommand extends Command { + VirtualMachineTO vm; + Map volumeToSr; + Map nicToNetwork; + Map token; + + public MigrateWithStorageSendCommand(VirtualMachineTO vm, Map volumeToSr, + Map nicToNetwork, Map token) { + this.vm =3D vm; + this.volumeToSr =3D volumeToSr; + this.nicToNetwork =3D nicToNetwork; + this.token =3D token; + } + + public VirtualMachineTO getVirtualMachine() { + return vm; + } + + public Map getVolumeToSr() { + return volumeToSr; + } + + public Map getNicToNetwork() { + return nicToNetwork; + } + + public Map getToken() { + return token; + } + + @Override + public boolean executeInSequence() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/agent/api/storage/MigrateVolumeAnswer.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/storage/MigrateVolumeAnswer.java b= /api/src/com/cloud/agent/api/storage/MigrateVolumeAnswer.java new file mode 100644 index 0000000..d5efa95 --- /dev/null +++ b/api/src/com/cloud/agent/api/storage/MigrateVolumeAnswer.java @@ -0,0 +1,38 @@ +// 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.agent.api.storage; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; + +public class MigrateVolumeAnswer extends Answer { + private String volumePath; + + public MigrateVolumeAnswer(Command command, boolean success, String de= tails, String volumePath) { + super(command, success, details); + this.volumePath =3D volumePath; + } + + public MigrateVolumeAnswer(Command command) { + super(command); + this.volumePath =3D null; + } + + public String getVolumePath() { + return volumePath; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/agent/api/storage/MigrateVolumeCommand.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java = b/api/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java new file mode 100644 index 0000000..b82d848 --- /dev/null +++ b/api/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api.storage; + +import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.storage.StoragePool; + +public class MigrateVolumeCommand extends Command { + + long volumeId; + String volumePath; + StorageFilerTO pool; + + public MigrateVolumeCommand(long volumeId, String volumePath, StorageP= ool pool) { + this.volumeId =3D volumeId; + this.volumePath =3D volumePath; + this.pool =3D new StorageFilerTO(pool); + } + + @Override + public boolean executeInSequence() { + return true; + } + + public String getVolumePath() { + return volumePath; + } + + public long getVolumeId() { + return volumeId; + } + + public StorageFilerTO getPool() { + return pool; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/com= /cloud/hypervisor/HypervisorCapabilities.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/hypervisor/HypervisorCapabilities.java b/api= /src/com/cloud/hypervisor/HypervisorCapabilities.java index aff81b0..c954750 100644 --- a/api/src/com/cloud/hypervisor/HypervisorCapabilities.java +++ b/api/src/com/cloud/hypervisor/HypervisorCapabilities.java @@ -52,4 +52,6 @@ public interface HypervisorCapabilities extends Identity,= InternalIdentity{ */ Integer getMaxHostsPerCluster(); + boolean isStorageMotionSupported(); + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/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 460357b..2249407 100755 --- a/api/src/com/cloud/server/ManagementService.java +++ b/api/src/com/cloud/server/ManagementService.java @@ -75,9 +75,11 @@ import com.cloud.network.IpAddress; import com.cloud.org.Cluster; import com.cloud.storage.GuestOS; import com.cloud.storage.GuestOsCategory; +import com.cloud.storage.StoragePool; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.SSHKeyPair; import com.cloud.utils.Pair; +import com.cloud.utils.Ternary; import com.cloud.vm.InstanceGroup; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; @@ -388,10 +390,21 @@ public interface ManagementService { * @param Long * vmId * Id of The VM to migrate - * @return Pair, List> List of al= l Hosts in VM's cluster and list of Hosts with - * enough capacity + * @return Ternary, List, Map> List of all Hosts to which a VM + * can be migrated, list of Hosts with enough capacity and hos= ts requiring storage motion for migration. */ - Pair, Integer>, List> listHo= stsForMigrationOfVM(Long vmId, Long startIndex, Long pageSize); + Ternary, Integer>, List, Map= > listHostsForMigrationOfVM( + Long vmId, Long startIndex, Long pageSize); + + /** + * List storage pools for live migrating of a volume. The API returns = list of all pools in the cluster to which the + * volume can be migrated. Current pool is not included in the list. + * + * @param Long volumeId + * @return Pair, List> List of storage pools in cluster and list + * of pools with enough capacity. + */ + Pair, List> listSto= ragePoolsForMigrationOfVolume(Long volumeId); String[] listEventTypes(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/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 d963b74..aa21136 100755 --- a/api/src/com/cloud/vm/UserVmService.java +++ b/api/src/com/cloud/vm/UserVmService.java @@ -405,6 +405,33 @@ public interface UserVmService { */ VirtualMachine migrateVirtualMachine(Long vmId, Host destinationHost) = throws ResourceUnavailableException, ConcurrentOperationException, Manageme= ntServerException, VirtualMachineMigrationException; + /** + * Migrate the given VM with its volumes to the destination host. The = API returns the migrated VM if it succeeds. + * Only root admin can migrate a VM. + * + * @param destinationStorage + * TODO + * @param Long + * vmId of The VM to migrate + * @param Host + * destinationHost to migrate the VM + * @param Map + * A map of volume to which pool it should be migrated + * + * @return VirtualMachine migrated VM + * @throws ManagementServerException + * in case we get error finding the VM or host or access e= rrors or other internal errors. + * @throws ConcurrentOperationException + * if there are multiple users working on the same VM. + * @throws ResourceUnavailableException + * if the destination host to migrate the VM is not curren= tly available. + * @throws VirtualMachineMigrationException + * if the VM to be migrated is not in Running state + */ + VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destina= tionHost, Map volumeToPool) + throws ResourceUnavailableException, ConcurrentOperationExcept= ion, ManagementServerException, + VirtualMachineMigrationException; + UserVm moveVMToUser(AssignVMCmd moveUserVMCmd) throws ResourceAllocati= onException, ConcurrentOperationException, ResourceUnavailableException, In= sufficientCapacityException; VirtualMachine vmStorageMigration(Long vmId, StoragePool destPool); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/ApiConstants.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/= org/apache/cloudstack/api/ApiConstants.java index 8c32bb3..edaaeb3 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -365,6 +365,8 @@ public class ApiConstants { public static final String HA_HOST =3D "hahost"; public static final String CUSTOM_DISK_OFF_MAX_SIZE =3D "customdiskoff= eringmaxsize"; public static final String DEFAULT_ZONE_ID =3D "defaultzoneid"; + public static final String LIVE_MIGRATE =3D "livemigrate"; + public static final String MIGRATE_TO =3D "migrateto"; public static final String GUID =3D "guid"; public static final String VSWITCH_TYPE_GUEST_TRAFFIC =3D "guestvswitc= htype"; public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC =3D "publicvswi= tchtype"; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/ResponseGenerator.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api= /src/org/apache/cloudstack/api/ResponseGenerator.java index c0dd57e..a3aa9de 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -189,6 +189,10 @@ public interface ResponseGenerator { HostResponse createHostResponse(Host host); + HostForMigrationResponse createHostForMigrationResponse(Host host); + + HostForMigrationResponse createHostForMigrationResponse(Host host, Enu= mSet details); + VlanIpRangeResponse createVlanIpRangeResponse(Vlan vlan); IPAddressResponse createIPAddressResponse(IpAddress ipAddress); @@ -216,6 +220,8 @@ public interface ResponseGenerator { StoragePoolResponse createStoragePoolResponse(StoragePool pool); + StoragePoolForMigrationResponse createStoragePoolForMigrationResponse(= StoragePool pool); + ClusterResponse createClusterResponse(Cluster cluster, Boolean showCap= acities); FirewallRuleResponse createPortForwardingRuleResponse(PortForwardingRu= le fwRule); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/admin/host/FindHosts= ForMigrationCmd.java b/api/src/org/apache/cloudstack/api/command/admin/host= /FindHostsForMigrationCmd.java new file mode 100644 index 0000000..e6e45cc --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/host/FindHostsForMigr= ationCmd.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.admin.host; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.cloudstack.api.APICommand; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.HostForMigrationResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import com.cloud.host.Host; +import com.cloud.utils.Pair; +import com.cloud.utils.Ternary; + +@APICommand(name =3D "findHostsForMigration", description=3D"Find hosts su= itable for migrating a virtual machine.", + responseObject=3DHostForMigrationResponse.class) +public class FindHostsForMigrationCmd extends BaseListCmd { + public static final Logger s_logger =3D Logger.getLogger(FindHostsForM= igrationCmd.class.getName()); + + private static final String s_name =3D "findhostsformigrationresponse"= ; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=3DApiConstants.VIRTUAL_MACHINE_ID, type=3DCommandType.= UUID, entityType =3D UserVmResponse.class, + required=3Dfalse, description=3D"find hosts to which this VM c= an be migrated and flag the hosts with enough " + + "CPU/RAM to host the VM") + private Long virtualMachineId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getVirtualMachineId() { + return virtualMachineId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void execute() { + ListResponse response =3D null; + Pair,Integer> result; + List hostsWithCapacity =3D new ArrayList(); + Map hostsRequiringStorageMotion; + + Ternary,Integer>, List, = Map> hostsForMigration =3D + _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), this= .getStartIndex(), this.getPageSizeVal()); + result =3D hostsForMigration.first(); + hostsWithCapacity =3D hostsForMigration.second(); + hostsRequiringStorageMotion =3D hostsForMigration.third(); + + response =3D new ListResponse(); + List hostResponses =3D new ArrayList(); + for (Host host : result.first()) { + HostForMigrationResponse hostResponse =3D _responseGenerator.c= reateHostForMigrationResponse(host); + Boolean suitableForMigration =3D false; + if (hostsWithCapacity.contains(host)) { + suitableForMigration =3D true; + } + hostResponse.setSuitableForMigration(suitableForMigration); + + Boolean requiresStorageMotion =3D hostsRequiringStorageMotion.= get(host); + if (requiresStorageMotion !=3D null && requiresStorageMotion) = { + hostResponse.setRequiresStorageMotion(true); + } else { + hostResponse.setRequiresStorageMotion(false); + } + + hostResponse.setObjectName("host"); + hostResponses.add(hostResponse); + } + + response.setResponses(hostResponses, result.second()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/command/admin/host/ListHostsCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/admin/host/ListHosts= Cmd.java b/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCm= d.java index 29844c3..5ec7cf3 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.jav= a +++ b/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.jav= a @@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command.admin.host; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; +import java.util.Map; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,6 +38,7 @@ import com.cloud.async.AsyncJob; import com.cloud.exception.InvalidParameterValueException; import com.cloud.host.Host; import com.cloud.utils.Pair; +import com.cloud.utils.Ternary; @APICommand(name =3D "listHosts", description=3D"Lists hosts.", responseOb= ject=3DHostResponse.class) public class ListHostsCmd extends BaseListCmd { @@ -170,8 +172,8 @@ public class ListHostsCmd extends BaseListCmd { } else { Pair,Integer> result; List hostsWithCapacity =3D new ArrayList= (); - - Pair,Integer>, List>= hostsForMigration =3D _mgr.listHostsForMigrationOfVM(getVirtualMachineId()= , this.getStartIndex(), this.getPageSizeVal()); + Ternary,Integer>, List, Map> hostsForMigration =3D + _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), = this.getStartIndex(), this.getPageSizeVal()); result =3D hostsForMigration.first(); hostsWithCapacity =3D hostsForMigration.second(); @@ -192,6 +194,5 @@ public class ListHostsCmd extends BaseListCmd { } response.setResponseName(getCommandName()); this.setResponseObject(response); - } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCm= d.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/FindSt= oragePoolsForMigrationCmd.java b/api/src/org/apache/cloudstack/api/command/= admin/storage/FindStoragePoolsForMigrationCmd.java new file mode 100644 index 0000000..37d007c --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/FindStoragePo= olsForMigrationCmd.java @@ -0,0 +1,98 @@ +// 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.admin.storage; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.cloudstack.api.APICommand; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import com.cloud.async.AsyncJob; +import com.cloud.storage.StoragePool; +import com.cloud.utils.Pair; + +@APICommand(name =3D "findStoragePoolsForMigration", description=3D"Lists = storage pools available for migration of a volume.", + responseObject=3DStoragePoolForMigrationResponse.class) +public class FindStoragePoolsForMigrationCmd extends BaseListCmd { + public static final Logger s_logger =3D Logger.getLogger(FindStoragePo= olsForMigrationCmd.class.getName()); + + private static final String s_name =3D "findstoragepoolsformigrationre= sponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=3DApiConstants.ID, type=3DCommandType.UUID, entityType= =3D VolumeResponse.class, required=3Dtrue, + description=3D"the ID of the volume") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.StoragePool; + } + + @Override + public void execute() { + Pair, List> poo= ls =3D + _mgr.listStoragePoolsForMigrationOfVolume(getId()); + ListResponse response =3D new Lis= tResponse(); + List poolResponses =3D new ArrayL= ist(); + + List allPools =3D pools.first(); + List suitablePoolList =3D pools.second(); + for (StoragePool pool : allPools) { + StoragePoolForMigrationResponse poolResponse =3D _responseGene= rator.createStoragePoolForMigrationResponse(pool); + Boolean suitableForMigration =3D false; + for (StoragePool suitablePool : suitablePoolList) { + if (suitablePool.getId() =3D=3D pool.getId()) { + suitableForMigration =3D true; + break; + } + } + poolResponse.setSuitableForMigration(suitableForMigration); + poolResponse.setObjectName("storagepool"); + poolResponses.add(poolResponse); + } + + response.setResponses(poolResponses); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.= java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirt= ualMachineWithVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/ad= min/vm/MigrateVirtualMachineWithVolumeCmd.java new file mode 100644 index 0000000..b1eaf11 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMach= ineWithVolumeCmd.java @@ -0,0 +1,160 @@ +// 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.admin.vm; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.cloudstack.api.*; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.api.APICommand; + +import org.apache.cloudstack.api.BaseCmd.CommandType; +import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ManagementServerException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.VirtualMachineMigrationException; +import com.cloud.host.Host; +import com.cloud.storage.StoragePool; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; + +@APICommand(name =3D "migrateVirtualMachineWithVolume", description=3D"Att= empts Migration of a VM with its volumes to a different host", responseObje= ct=3DUserVmResponse.class) +public class MigrateVirtualMachineWithVolumeCmd extends BaseAsyncCmd { + public static final Logger s_logger =3D Logger.getLogger(MigrateVMCmd.= class.getName()); + + private static final String s_name =3D "migratevirtualmachinewithvolum= eresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=3DApiConstants.HOST_ID, type=3DCommandType.UUID, entit= yType=3DHostResponse.class, + required=3Dtrue, description=3D"Destination Host ID to migrate= VM to.") + private Long hostId; + + @Parameter(name=3DApiConstants.VIRTUAL_MACHINE_ID, type=3DCommandType.= UUID, entityType=3DUserVmResponse.class, + required=3Dtrue, description=3D"the ID of the virtual machine"= ) + private Long virtualMachineId; + + @Parameter(name =3D ApiConstants.MIGRATE_TO, type =3D CommandType.MAP,= required=3Dfalse, + description =3D "Map of pool to which each volume should be mi= grated (volume/pool pair)") + private Map migrateVolumeTo; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getHostId() { + return hostId; + } + + public Long getVirtualMachineId() { + return virtualMachineId; + } + + public Map getVolumeToPool() { + Map volumeToPoolMap =3D new HashMap(); + if (migrateVolumeTo !=3D null && !migrateVolumeTo.isEmpty()) { + Collection allValues =3D migrateVolumeTo.values(); + Iterator iter =3D allValues.iterator(); + while (iter.hasNext()) { + HashMap volumeToPool =3D (HashMap) iter.next(); + String volume =3D volumeToPool.get("volume"); + String pool =3D volumeToPool.get("pool"); + volumeToPoolMap.put(volume, pool); + } + } + return volumeToPoolMap; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + UserVm userVm =3D _entityMgr.findById(UserVm.class, getVirtualMach= ineId()); + if (userVm !=3D null) { + return userVm.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_VM_MIGRATE; + } + + @Override + public String getEventDescription() { + return "Attempting to migrate VM Id: " + getVirtualMachineId() + = " to host Id: "+ getHostId(); + } + + @Override + public void execute(){ + UserVm userVm =3D _userVmService.getUserVm(getVirtualMachineId()); + if (userVm =3D=3D null) { + throw new InvalidParameterValueException("Unable to find the V= M by id=3D" + getVirtualMachineId()); + } + + Host destinationHost =3D _resourceService.getHost(getHostId()); + if (destinationHost =3D=3D null) { + throw new InvalidParameterValueException("Unable to find the h= ost to migrate the VM, host id =3D" + getHostId()); + } + + try{ + VirtualMachine migratedVm =3D _userVmService.migrateVirtualMac= hineWithVolume(getVirtualMachineId(), + destinationHost, getVolumeToPool()); + if (migratedVm !=3D null) { + UserVmResponse response =3D _responseGenerator.createUserV= mResponse("virtualmachine", (UserVm)migratedVm).get(0); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, = "Failed to migrate vm"); + } + } catch (ResourceUnavailableException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE= _ERROR, ex.getMessage()); + } catch (ConcurrentOperationException e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.ge= tMessage()); + } catch (ManagementServerException e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.ge= tMessage()); + } catch (VirtualMachineMigrationException e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.ge= tMessage()); + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateV= olumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/Migra= teVolumeCmd.java index 287241a..ce40f0d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCm= d.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCm= d.java @@ -47,6 +47,10 @@ public class MigrateVolumeCmd extends BaseAsyncCmd { required=3Dtrue, description=3D"destination storage pool ID to= migrate the volume to") private Long storageId; + @Parameter(name=3DApiConstants.LIVE_MIGRATE, type=3DCommandType.BOOLEA= N, required=3Dfalse, + description=3D"if the volume should be live migrated when it i= s attached to a running vm") + private Boolean liveMigrate; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -58,6 +62,10 @@ public class MigrateVolumeCmd extends BaseAsyncCmd { public Long getStoragePoolId() { return storageId; } + + public boolean isLiveMigrate() { + return (liveMigrate !=3D null) ? liveMigrate : false; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/response/HostForMigrationResponse.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/response/HostForMigrationRes= ponse.java b/api/src/org/apache/cloudstack/api/response/HostForMigrationRes= ponse.java new file mode 100644 index 0000000..fde2440 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/HostForMigrationResponse.j= ava @@ -0,0 +1,365 @@ +// 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.response; + +import java.util.Date; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.host.Host; +import com.cloud.host.Status; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value=3DHost.class) +public class HostForMigrationResponse extends BaseResponse { + @SerializedName(ApiConstants.ID) @Param(description=3D"the ID of the h= ost") + private String id; + + @SerializedName(ApiConstants.NAME) @Param(description=3D"the name of t= he host") + private String name; + + @SerializedName(ApiConstants.STATE) @Param(description=3D"the state of= the host") + private Status state; + + @SerializedName("disconnected") @Param(description=3D"true if the host= is disconnected. False otherwise.") + private Date disconnectedOn; + + @SerializedName(ApiConstants.TYPE) @Param(description=3D"the host type= ") + private Host.Type hostType; + + @SerializedName("oscategoryid") @Param(description=3D"the OS category = ID of the host") + private String osCategoryId; + + @SerializedName("oscategoryname") @Param(description=3D"the OS categor= y name of the host") + private String osCategoryName; + + @SerializedName(ApiConstants.IP_ADDRESS) @Param(description=3D"the IP = address of the host") + private String ipAddress; + + @SerializedName(ApiConstants.ZONE_ID) @Param(description=3D"the Zone I= D of the host") + private String zoneId; + + @SerializedName(ApiConstants.ZONE_NAME) @Param(description=3D"the Zone= name of the host") + private String zoneName; + + @SerializedName(ApiConstants.POD_ID) @Param(description=3D"the Pod ID = of the host") + private String podId; + + @SerializedName("podname") @Param(description=3D"the Pod name of the h= ost") + private String podName; + + @SerializedName("version") @Param(description=3D"the host version") + private String version; + + @SerializedName(ApiConstants.HYPERVISOR) @Param(description=3D"the hos= t hypervisor") + private HypervisorType hypervisor; + + @SerializedName("cpunumber") @Param(description=3D"the CPU number of t= he host") + private Integer cpuNumber; + + @SerializedName("cpuspeed") @Param(description=3D"the CPU speed of the= host") + private Long cpuSpeed; + + @SerializedName("cpuallocated") @Param(description=3D"the amount of th= e host's CPU currently allocated") + private String cpuAllocated; + + @SerializedName("cpuused") @Param(description=3D"the amount of the hos= t's CPU currently used") + private String cpuUsed; + + @SerializedName("cpuwithoverprovisioning") @Param(description=3D"the a= mount of the host's CPU after applying the cpu.overprovisioning.factor ") + private String cpuWithOverprovisioning; + + @SerializedName("averageload") @Param(description=3D"the cpu average l= oad on the host") + private Long averageLoad; + + @SerializedName("networkkbsread") @Param(description=3D"the incoming n= etwork traffic on the host") + private Long networkKbsRead; + + @SerializedName("networkkbswrite") @Param(description=3D"the outgoing = network traffic on the host") + private Long networkKbsWrite; + + @SerializedName("memorytotal") @Param(description=3D"the memory total = of the host") + private Long memoryTotal; + + @SerializedName("memoryallocated") @Param(description=3D"the amount of= the host's memory currently allocated") + private Long memoryAllocated; + + @SerializedName("memoryused") @Param(description=3D"the amount of the = host's memory currently used") + private Long memoryUsed; + + @SerializedName("disksizetotal") @Param(description=3D"the total disk = size of the host") + private Long diskSizeTotal; + + @SerializedName("disksizeallocated") @Param(description=3D"the host's = currently allocated disk size") + private Long diskSizeAllocated; + + @SerializedName("capabilities") @Param(description=3D"capabilities of = the host") + private String capabilities; + + @SerializedName("lastpinged") @Param(description=3D"the date and time = the host was last pinged") + private Date lastPinged; + + @SerializedName("managementserverid") @Param(description=3D"the manage= ment server ID of the host") + private Long managementServerId; + + @SerializedName("clusterid") @Param(description=3D"the cluster ID of t= he host") + private String clusterId; + + @SerializedName("clustername") @Param(description=3D"the cluster name = of the host") + private String clusterName; + + @SerializedName("clustertype") @Param(description=3D"the cluster type = of the cluster that host belongs to") + private String clusterType; + + @SerializedName("islocalstorageactive") @Param(description=3D"true if = local storage is active, false otherwise") + private Boolean localStorageActive; + + @SerializedName(ApiConstants.CREATED) @Param(description=3D"the date a= nd time the host was created") + private Date created; + + @SerializedName("removed") @Param(description=3D"the date and time the= host was removed") + private Date removed; + + @SerializedName("events") @Param(description=3D"events available for t= he host") + private String events; + + @SerializedName("hosttags") @Param(description=3D"comma-separated list= of tags for the host") + private String hostTags; + + @SerializedName("hasenoughcapacity") @Param(description=3D"true if thi= s host has enough CPU and RAM capacity to migrate a VM to it, false otherwi= se") + private Boolean hasEnoughCapacity; + + @SerializedName("suitableformigration") @Param(description=3D"true if = this host is suitable(has enough capacity and satisfies all conditions like= hosttags, max guests vm limit etc) to migrate a VM to it , false otherwise= ") + private Boolean suitableForMigration; + + @SerializedName("requiresStorageMotion") @Param(description=3D"true if= migrating a vm to this host requires storage motion, false otherwise") + private Boolean requiresStorageMotion; + + @SerializedName("resourcestate") @Param(description=3D"the resource st= ate of the host") + private String resourceState; + + @SerializedName(ApiConstants.HYPERVISOR_VERSION) @Param(description=3D= "the hypervisor version") + private String hypervisorVersion; + + @SerializedName(ApiConstants.HA_HOST) @Param(description=3D"true if th= e host is Ha host (dedicated to vms started by HA process; false otherwise"= ) + private Boolean haHost; + + @Override + public String getObjectId() { + return this.getId(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id =3D id; + } + + public void setName(String name) { + this.name =3D name; + } + + public void setState(Status state) { + this.state =3D state; + } + + public void setDisconnectedOn(Date disconnectedOn) { + this.disconnectedOn =3D disconnectedOn; + } + + public void setHostType(Host.Type hostType) { + this.hostType =3D hostType; + } + + public void setOsCategoryId(String osCategoryId) { + this.osCategoryId =3D osCategoryId; + } + + public void setOsCategoryName(String osCategoryName) { + this.osCategoryName =3D osCategoryName; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress =3D ipAddress; + } + + public void setZoneId(String zoneId) { + this.zoneId =3D zoneId; + } + + public void setZoneName(String zoneName) { + this.zoneName =3D zoneName; + } + + public void setPodId(String podId) { + this.podId =3D podId; + } + + public void setPodName(String podName) { + this.podName =3D podName; + } + + public void setVersion(String version) { + this.version =3D version; + } + + public void setHypervisor(HypervisorType hypervisor) { + this.hypervisor =3D hypervisor; + } + + public void setCpuNumber(Integer cpuNumber) { + this.cpuNumber =3D cpuNumber; + } + + public void setCpuSpeed(Long cpuSpeed) { + this.cpuSpeed =3D cpuSpeed; + } + + public String getCpuAllocated() { + return cpuAllocated; + } + + public void setCpuAllocated(String cpuAllocated) { + this.cpuAllocated =3D cpuAllocated; + } + + public void setCpuUsed(String cpuUsed) { + this.cpuUsed =3D cpuUsed; + } + + public void setAverageLoad(Long averageLoad) { + this.averageLoad =3D averageLoad; + } + + public void setNetworkKbsRead(Long networkKbsRead) { + this.networkKbsRead =3D networkKbsRead; + } + + public void setNetworkKbsWrite(Long networkKbsWrite) { + this.networkKbsWrite =3D networkKbsWrite; + } + + public void setMemoryTotal(Long memoryTotal) { + this.memoryTotal =3D memoryTotal; + } + + public void setMemoryAllocated(Long memoryAllocated) { + this.memoryAllocated =3D memoryAllocated; + } + + public void setMemoryUsed(Long memoryUsed) { + this.memoryUsed =3D memoryUsed; + } + + public void setDiskSizeTotal(Long diskSizeTotal) { + this.diskSizeTotal =3D diskSizeTotal; + } + + public void setDiskSizeAllocated(Long diskSizeAllocated) { + this.diskSizeAllocated =3D diskSizeAllocated; + } + + public void setCapabilities(String capabilities) { + this.capabilities =3D capabilities; + } + + public void setLastPinged(Date lastPinged) { + this.lastPinged =3D lastPinged; + } + + public void setManagementServerId(Long managementServerId) { + this.managementServerId =3D managementServerId; + } + + public void setClusterId(String clusterId) { + this.clusterId =3D clusterId; + } + + public void setClusterName(String clusterName) { + this.clusterName =3D clusterName; + } + + public void setClusterType(String clusterType) { + this.clusterType =3D clusterType; + } + + public void setLocalStorageActive(Boolean localStorageActive) { + this.localStorageActive =3D localStorageActive; + } + + public void setCreated(Date created) { + this.created =3D created; + } + + public void setRemoved(Date removed) { + this.removed =3D removed; + } + + public void setEvents(String events) { + this.events =3D events; + } + + public String getHostTags() { + return hostTags; + } + + public void setHostTags(String hostTags) { + this.hostTags =3D hostTags; + } + + public void setHasEnoughCapacity(Boolean hasEnoughCapacity) { + this.hasEnoughCapacity =3D hasEnoughCapacity; + } + + public void setSuitableForMigration(Boolean suitableForMigration) { + this.suitableForMigration =3D suitableForMigration; + } + + public void setRequiresStorageMotion(Boolean requiresStorageMotion) { + this.requiresStorageMotion =3D requiresStorageMotion; + } + + public String getResourceState() { + return resourceState; + } + + public void setResourceState(String resourceState) { + this.resourceState =3D resourceState; + } + + public String getCpuWithOverprovisioning() { + return cpuWithOverprovisioning; + } + + public void setCpuWithOverprovisioning(String cpuWithOverprovisioning)= { + this.cpuWithOverprovisioning =3D cpuWithOverprovisioning; + } + + public void setHypervisorVersion(String hypervisorVersion) { + this.hypervisorVersion =3D hypervisorVersion; + } + + public void setHaHost(Boolean haHost) { + this.haHost =3D haHost; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/response/HostResponse.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/response/HostResponse.java b= /api/src/org/apache/cloudstack/api/response/HostResponse.java index f5aa8f9..687687d 100644 --- a/api/src/org/apache/cloudstack/api/response/HostResponse.java +++ b/api/src/org/apache/cloudstack/api/response/HostResponse.java @@ -330,7 +330,6 @@ public class HostResponse extends BaseResponse { this.hasEnoughCapacity =3D hasEnoughCapacity; } - public void setSuitableForMigration(Boolean suitableForMigration) { this.suitableForMigration =3D suitableForMigration; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/response/StoragePoolForMigrationResponse.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolForMigra= tionResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolF= orMigrationResponse.java new file mode 100644 index 0000000..f0bbcb1 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationRes= ponse.java @@ -0,0 +1,248 @@ +// 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.response; + +import java.util.Date; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.serializer.Param; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolStatus; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value=3DStoragePool.class) +public class StoragePoolForMigrationResponse extends BaseResponse { + @SerializedName("id") @Param(description=3D"the ID of the storage pool= ") + private String id; + + @SerializedName("zoneid") @Param(description=3D"the Zone ID of the sto= rage pool") + private String zoneId; + + @SerializedName(ApiConstants.ZONE_NAME) @Param(description=3D"the Zone= name of the storage pool") + private String zoneName; + + @SerializedName("podid") @Param(description=3D"the Pod ID of the stora= ge pool") + private String podId; + + @SerializedName("podname") @Param(description=3D"the Pod name of the s= torage pool") + private String podName; + + @SerializedName("name") @Param(description=3D"the name of the storage = pool") + private String name; + + @SerializedName("ipaddress") @Param(description=3D"the IP address of t= he storage pool") + private String ipAddress; + + @SerializedName("path") @Param(description=3D"the storage pool path") + private String path; + + @SerializedName("created") @Param(description=3D"the date and time the= storage pool was created") + private Date created; + + @SerializedName("type") @Param(description=3D"the storage pool type") + private String type; + + @SerializedName("clusterid") @Param(description=3D"the ID of the clust= er for the storage pool") + private String clusterId; + + @SerializedName("clustername") @Param(description=3D"the name of the c= luster for the storage pool") + private String clusterName; + + @SerializedName("disksizetotal") @Param(description=3D"the total disk = size of the storage pool") + private Long diskSizeTotal; + + @SerializedName("disksizeallocated") @Param(description=3D"the host's = currently allocated disk size") + private Long diskSizeAllocated; + + @SerializedName("disksizeused") @Param(description=3D"the host's curre= ntly used disk size") + private Long diskSizeUsed; + + @SerializedName("tags") @Param(description=3D"the tags for the storage= pool") + private String tags; + + @SerializedName(ApiConstants.STATE) @Param(description=3D"the state of= the storage pool") + private StoragePoolStatus state; + + @SerializedName(ApiConstants.SCOPE) @Param(description=3D"the scope of= the storage pool") + private String scope; + + @SerializedName("suitableformigration") @Param(description=3D"true if = this pool is suitable to migrate a volume," + + " false otherwise") + private Boolean suitableForMigration; + + /** + * @return the scope + */ + public String getScope() { + return scope; + } + + /** + * @param scope the scope to set + */ + public void setScope(String scope) { + this.scope =3D scope; + } + + @Override + public String getObjectId() { + return this.getId(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id =3D id; + } + + public String getZoneId() { + return zoneId; + } + + public void setZoneId(String zoneId) { + this.zoneId =3D zoneId; + } + + public String getZoneName() { + return zoneName; + } + + public void setZoneName(String zoneName) { + this.zoneName =3D zoneName; + } + + public String getPodId() { + return podId; + } + + public void setPodId(String podId) { + this.podId =3D podId; + } + + public String getPodName() { + return podName; + } + + public void setPodName(String podName) { + this.podName =3D podName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name =3D name; + } + + public String getIpAddress() { + return ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress =3D ipAddress; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path =3D path; + } + + public Date getCreated() { + return created; + } + + public void setCreated(Date created) { + this.created =3D created; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type =3D type; + } + + public String getClusterId() { + return clusterId; + } + + public void setClusterId(String clusterId) { + this.clusterId =3D clusterId; + } + + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName =3D clusterName; + } + + public Long getDiskSizeTotal() { + return diskSizeTotal; + } + + public void setDiskSizeTotal(Long diskSizeTotal) { + this.diskSizeTotal =3D diskSizeTotal; + } + + public Long getDiskSizeAllocated() { + return diskSizeAllocated; + } + + public void setDiskSizeAllocated(Long diskSizeAllocated) { + this.diskSizeAllocated =3D diskSizeAllocated; + } + + public Long getDiskSizeUsed() { + return diskSizeUsed; + } + + public void setDiskSizeUsed(Long diskSizeUsed) { + this.diskSizeUsed =3D diskSizeUsed; + } + + public String getTags() { + return tags; + } + + public void setTags(String tags) { + this.tags =3D tags; + } + + public StoragePoolStatus getState() { + return state; + } + + public void setState(StoragePoolStatus state) { + this.state =3D state; + } + + public void setSuitableForMigration(Boolean suitableForMigration) { + this.suitableForMigration =3D suitableForMigration; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/api/src/org= /apache/cloudstack/api/response/StoragePoolResponse.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse= .java b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java index 0b16226..e034b17 100644 --- a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java +++ b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java @@ -83,8 +83,6 @@ public class StoragePoolResponse extends BaseResponse { @SerializedName(ApiConstants.SCOPE) @Param(description=3D"the scope of= the storage pool") private String scope; - - /** * @return the scope */ @@ -239,5 +237,4 @@ public class StoragePoolResponse extends BaseResponse { public void setState(StoragePoolStatus state) { this.state =3D state; } - } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/client/tomc= atconf/applicationContext.xml.in ---------------------------------------------------------------------- diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatcon= f/applicationContext.xml.in index 7487a5e..d2ea380 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -714,6 +714,7 @@ + http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/client/tomc= atconf/commands.properties.in ---------------------------------------------------------------------- diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/c= ommands.properties.in index 10fcfe3..b49e1fb 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -69,6 +69,7 @@ changeServiceForVirtualMachine=3D15 scaleVirtualMachine=3D15 assignVirtualMachine=3D1 migrateVirtualMachine=3D1 +migrateVirtualMachineWithVolume=3D1 recoverVirtualMachine=3D7 #### snapshot commands @@ -254,6 +255,7 @@ deleteHost=3D3 prepareHostForMaintenance=3D1 cancelHostMaintenance=3D1 listHosts=3D3 +findHostsForMigration=3D1 addSecondaryStorage=3D1 updateHostPassword=3D1 @@ -288,6 +290,7 @@ deleteStoragePool=3D1 listClusters=3D3 enableStorageMaintenance=3D1 cancelStorageMaintenance=3D1 +findStoragePoolsForMigration=3D1 #### security group commands createSecurityGroup=3D15 http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/core/src/co= m/cloud/hypervisor/HypervisorCapabilitiesVO.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java b/= core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java index fafc0a3..6689066 100644 --- a/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java +++ b/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java @@ -64,16 +64,21 @@ public class HypervisorCapabilitiesVO implements Hyperv= isorCapabilities { @Column(name=3D"vm_snapshot_enabled") private Boolean vmSnapshotEnabled; - + + @Column(name=3D"storage_motion_supported") + private boolean storageMotionSupported; + protected HypervisorCapabilitiesVO() { this.uuid =3D UUID.randomUUID().toString(); } - public HypervisorCapabilitiesVO(HypervisorType hypervisorType, String = hypervisorVersion, Long maxGuestsLimit, boolean securityGroupEnabled) { + public HypervisorCapabilitiesVO(HypervisorType hypervisorType, String = hypervisorVersion, Long maxGuestsLimit, + boolean securityGroupEnabled, boolean storageMotionSupported) = { this.hypervisorType =3D hypervisorType; this.hypervisorVersion =3D hypervisorVersion; this.maxGuestsLimit =3D maxGuestsLimit; this.securityGroupEnabled =3D securityGroupEnabled; + this.storageMotionSupported =3D storageMotionSupported; this.uuid =3D UUID.randomUUID().toString(); } @@ -135,6 +140,21 @@ public class HypervisorCapabilitiesVO implements Hyper= visorCapabilities { return maxGuestsLimit; } + /** + * @param storageMotionSupported + */ + public void setStorageMotionSupported(boolean storageMotionSupported) = { + this.storageMotionSupported =3D storageMotionSupported; + } + + /** + * @return if storage motion is supported + */ + @Override + public boolean isStorageMotionSupported() { + return storageMotionSupported; + } + public long getId() { return id; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/engine/api/= src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreSta= teMachine.java ---------------------------------------------------------------------- diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/stor= age/ObjectInDataStoreStateMachine.java b/engine/api/src/org/apache/cloudsta= ck/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java index f619ef4..94ae800 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/Obj= ectInDataStoreStateMachine.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/Obj= ectInDataStoreStateMachine.java @@ -28,6 +28,7 @@ public interface ObjectInDataStoreStateMachine extends St= ateObject createVolumeFromTemplateAsync(VolumeI= nfo volume, long dataStoreId, TemplateInfo template); AsyncCallFuture copyVolume(VolumeInfo srcVolume, Data= Store destStore); + AsyncCallFuture migrateVolume(VolumeInfo srcVolume, D= ataStore destStore); + AsyncCallFuture migrateVolumes(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost); boolean destroyVolume(long volumeId) throws ConcurrentOperationExcepti= on; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21ce3bef/engine/stor= age/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImage= MotionStrategy.java ---------------------------------------------------------------------- diff --git a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/i= mage/motion/DefaultImageMotionStrategy.java b/engine/storage/imagemotion/sr= c/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.jav= a index a70fd8a..1c21496 100644 --- a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/mo= tion/DefaultImageMotionStrategy.java +++ b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/mo= tion/DefaultImageMotionStrategy.java @@ -18,12 +18,15 @@ */ package org.apache.cloudstack.storage.image.motion; +import java.util.Map; + import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResul= t; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; @@ -33,6 +36,8 @@ import org.apache.cloudstack.storage.endpoint.EndPointSel= ector; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo= ; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.Host; //At least one of datastore is coming from image store or image cache stor= e @@ -96,6 +101,11 @@ public class DefaultImageMotionStrategy implements Imag= eMotionStrategy { } @Override + public boolean canHandle(Map volumeMap, Host sr= cHost, Host destHost) { + return false; + } + + @Override public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { DataStore destStore =3D destData.getDataStore(); @@ -137,4 +147,12 @@ public class DefaultImageMotionStrategy implements Ima= geMotionStrategy { } + @Override + public Void copyAsync(Map volumeMap, VirtualMac= hineTO vmTo, Host srcHost, Host destHost, + AsyncCompletionCallback callback) { + CopyCommandResult result =3D new CopyCommandResult("", null); + result.setResult("not implemented"); + callback.complete(result); + return null; + } }