Skip to content

Commit a5ee443

Browse files
committed
Merge release branch 4.8 to master
* 4.8: Removed sleeps and used validateList as requested. Added required_hardware="false" attr above test_02_root_volume_attach_detach Modified test_volumes.py to include a hypervisor test for root attach/detach testing Let hypervisor type KVM and Simulator detach root volumes. Updated test_volumes.py to include a test for detaching and reattaching a root volume from a vm. I also had to update base.py to allow attach_volume to have the parameter deviceid to be passed as needed.
2 parents 1f53adb + d11194a commit a5ee443

File tree

3 files changed

+141
-4
lines changed

3 files changed

+141
-4
lines changed

server/src/com/cloud/storage/VolumeApiServiceImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,8 +1744,8 @@ else if (jobResult instanceof Long) {
17441744
}
17451745

17461746
private void validateRootVolumeDetachAttach(VolumeVO volume, UserVmVO vm) {
1747-
if (!(vm.getHypervisorType() == HypervisorType.XenServer || vm.getHypervisorType() == HypervisorType.VMware)) {
1748-
throw new InvalidParameterValueException("Root volume detach is allowed for hypervisor type " + HypervisorType.XenServer + " only");
1747+
if (!(vm.getHypervisorType() == HypervisorType.XenServer || vm.getHypervisorType() == HypervisorType.VMware || vm.getHypervisorType() == HypervisorType.KVM || vm.getHypervisorType() == HypervisorType.Simulator)) {
1748+
throw new InvalidParameterValueException("Root volume detach is not supported for hypervisor type " + vm.getHypervisorType() );
17491749
}
17501750
if (!(vm.getState() == State.Stopped) || (vm.getState() == State.Destroyed)) {
17511751
throw new InvalidParameterValueException("Root volume detach can happen only when vm is in states: " + State.Stopped.toString() + " or " + State.Destroyed.toString());

test/integration/component/test_volumes.py

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,140 @@ def test_01_volume_attach_detach(self):
603603
"Check the state of VM"
604604
)
605605
except Exception as e:
606-
self.fail("Exception occuered: %s" % e)
606+
self.fail("Exception occurred: %s" % e)
607+
return
608+
609+
@attr(tags=["advanced", "advancedns"], required_hardware="false")
610+
def test_02_root_volume_attach_detach(self):
611+
"""Test Root Volume attach/detach to VM
612+
"""
613+
614+
# Validate the following
615+
# 1. Deploy a VM
616+
# 2. Verify that we are testing a supported hypervisor
617+
# 3. Check for root volume
618+
# 4. Stop VM
619+
# 5. Detach root volume
620+
# 6. Verify root volume detached
621+
# 7. Attach root volume
622+
# 8. Start VM
623+
624+
# Verify we are using a supported hypervisor
625+
if (self.hypervisor.lower() == 'vmware'
626+
or self.hypervisor.lower() == 'kvm'
627+
or self.hypervisor.lower() == 'simulator'
628+
or self.hypervisor.lower() == 'xenserver'):
629+
630+
try:
631+
# Check for root volume
632+
root_volume_response = Volume.list(
633+
self.apiclient,
634+
virtualmachineid=self.virtual_machine.id,
635+
type='ROOT',
636+
listall=True
637+
)
638+
639+
self.assertEqual(
640+
validateList(root_volume_response)[0],
641+
PASS,
642+
"Invalid response returned for root volume list"
643+
)
644+
645+
# Grab the root volume for later use
646+
root_volume = root_volume_response[0]
647+
648+
# Stop VM
649+
self.debug("Stopping the VM: %s" % self.virtual_machine.id)
650+
self.virtual_machine.stop(self.apiclient)
651+
652+
vm_response = VirtualMachine.list(
653+
self.apiclient,
654+
id=self.virtual_machine.id,
655+
)
656+
657+
# Ensure that vm_response is a valid list
658+
self.assertEqual(
659+
validateList(vm_response)[0],
660+
PASS,
661+
"Invalid response returned for vm_response list"
662+
)
663+
664+
vm = vm_response[0]
665+
self.assertEqual(
666+
vm.state,
667+
'Stopped',
668+
"Check the state of VM"
669+
)
670+
671+
# Detach root volume from VM
672+
self.virtual_machine.detach_volume(
673+
self.apiclient,
674+
root_volume
675+
)
676+
677+
# Verify that root disk is gone
678+
no_root_volume_response = Volume.list(
679+
self.apiclient,
680+
virtualmachineid=self.virtual_machine.id,
681+
type='ROOT',
682+
listall=True
683+
)
684+
685+
self.assertEqual(
686+
no_root_volume_response,
687+
None,
688+
"Check if root volume exists in ListVolumes"
689+
)
690+
691+
# Attach root volume to VM
692+
self.virtual_machine.attach_volume(
693+
self.apiclient,
694+
root_volume,
695+
0
696+
)
697+
698+
# Check for root volume
699+
new_root_volume_response = Volume.list(
700+
self.apiclient,
701+
virtualmachineid=self.virtual_machine.id,
702+
type='ROOT',
703+
listall=True
704+
)
705+
706+
# Ensure that new_root_volume_response is a valid list
707+
self.assertEqual(
708+
validateList(new_root_volume_response)[0],
709+
PASS,
710+
"Invalid response returned for new_root_volume_response list"
711+
)
712+
713+
# Start VM
714+
self.virtual_machine.start(self.apiclient)
715+
716+
vm_response = VirtualMachine.list(
717+
self.apiclient,
718+
id=self.virtual_machine.id,
719+
)
720+
721+
# Verify VM response to check whether VM deployment was successful
722+
self.assertEqual(
723+
validateList(vm_response)[0],
724+
PASS,
725+
"Invalid response returned for vm_response list during VM start up"
726+
)
727+
728+
vm = vm_response[0]
729+
self.assertEqual(
730+
vm.state,
731+
'Running',
732+
"Ensure the state of VM is running"
733+
)
734+
735+
except Exception as e:
736+
self.fail("Exception occurred: %s" % e)
737+
738+
else:
739+
self.skipTest("Root Volume attach/detach is not supported on %s " % self.hypervisor)
607740
return
608741

609742

tools/marvin/marvin/lib/base.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,11 +667,15 @@ def migrate_vm_with_volume(self, apiclient, hostid=None, migrateto=None):
667667
})
668668
apiclient.migrateVirtualMachineWithVolume(cmd)
669669

670-
def attach_volume(self, apiclient, volume):
670+
def attach_volume(self, apiclient, volume, deviceid=None):
671671
"""Attach volume to instance"""
672672
cmd = attachVolume.attachVolumeCmd()
673673
cmd.id = volume.id
674674
cmd.virtualmachineid = self.id
675+
676+
if deviceid is not None:
677+
cmd.deviceid = deviceid
678+
675679
return apiclient.attachVolume(cmd)
676680

677681
def detach_volume(self, apiclient, volume):

0 commit comments

Comments
 (0)