import salt.modules.virt as virt from salt._compat import ElementTree as ET from tests.support.mock import MagicMock, patch from .test_helpers import append_to_XMLDesc def test_update_xen_disk_volumes(make_mock_vm, make_mock_storage_pool): xml_def = """ my_vm 524288 524288 1 linux /usr/lib/grub2/x86_64-xen/grub.xen """ domain_mock = make_mock_vm(xml_def) make_mock_storage_pool("default", "dir", ["my_vm_system"]) make_mock_storage_pool("my-iscsi", "iscsi", ["unit:0:0:1"]) make_mock_storage_pool("vdb", "disk", ["vdb1"]) ret = virt.update( "my_vm", disks=[ {"name": "system", "pool": "default"}, {"name": "iscsi-data", "pool": "my-iscsi", "source_file": "unit:0:0:1"}, {"name": "vdb-data", "pool": "vdb", "source_file": "vdb1"}, {"name": "file-data", "pool": "default", "size": "10240"}, ], ) assert ret["definition"] define_mock = virt.libvirt.openAuth().defineXML setxml = ET.fromstring(define_mock.call_args[0][0]) assert "block" == setxml.find(".//disk[3]").get("type") assert "/path/to/vdb/vdb1" == setxml.find(".//disk[3]/source").get("dev") # Note that my_vm-file-data was not an existing volume before the update assert "file" == setxml.find(".//disk[4]").get("type") assert "/path/to/default/my_vm_file-data" == setxml.find(".//disk[4]/source").get( "file" ) def test_get_disks(make_mock_vm, make_mock_storage_pool): # test with volumes vm_def = """ srv01
""" domain_mock = make_mock_vm(vm_def) pool_mock = make_mock_storage_pool( "default", "dir", ["srv01_system", "srv01_data", "vm05_system"] ) # Append backing store to srv01_data volume XML description srv1data_mock = pool_mock.storageVolLookupByName("srv01_data") append_to_XMLDesc( srv1data_mock, """ /var/lib/libvirt/images/vol01 """, ) assert virt.get_disks("srv01") == { "vda": { "type": "disk", "file": "default/srv01_system", "file format": "qcow2", "disk size": 12345, "virtual size": 1234567, }, "vdb": { "type": "disk", "file": "default/srv01_data", "file format": "qcow2", "disk size": 12345, "virtual size": 1234567, "backing file": { "file": "/var/lib/libvirt/images/vol01", "file format": "qcow2", }, }, "vdc": { "type": "disk", "file": "default/vm05_system", "file format": "qcow2", "disk size": 12345, "virtual size": 1234567, "backing file": { "file": "/var/lib/libvirt/images/vm04_system.qcow2", "file format": "qcow2", "backing file": { "file": "/var/testsuite-data/disk-image-template.raw", "file format": "raw", }, }, }, "hda": { "type": "cdrom", "file format": "raw", "file": "http://dev-srv.tf.local:80/pub/iso/myimage.iso?foo=bar&baz=flurb", }, } def test_get_disk_convert_volumes(make_mock_vm, make_mock_storage_pool): vm_def = """ srv01
""" domain_mock = make_mock_vm(vm_def) pool_mock = make_mock_storage_pool("default", "dir", ["srv01_system", "srv01_data"]) subprocess_mock = MagicMock() popen_mock = MagicMock(spec=virt.subprocess.Popen) popen_mock.return_value.communicate.return_value = [ """[ { "virtual-size": 214748364800, "filename": "/path/to/srv01_extra", "cluster-size": 65536, "format": "qcow2", "actual-size": 340525056, "format-specific": { "type": "qcow2", "data": { "compat": "1.1", "lazy-refcounts": false, "refcount-bits": 16, "corrupt": false } }, "dirty-flag": false } ] """ ] subprocess_mock.Popen = popen_mock with patch.dict(virt.__dict__, {"subprocess": subprocess_mock}): assert { "vda": { "type": "disk", "file": "default/srv01_system", "file format": "qcow2", "disk size": 12345, "virtual size": 1234567, }, "vdb": { "type": "disk", "file": "default/srv01_data", "file format": "raw", "disk size": 12345, "virtual size": 1234567, }, "vdc": { "type": "disk", "file": "/path/to/srv01_extra", "file format": "qcow2", "cluster size": 65536, "disk size": 340525056, "virtual size": 214748364800, }, } == virt.get_disks("srv01") def test_update_approx_mem(make_mock_vm): """ test virt.update with memory parameter unchanged thought not exactly equals to the current value. This may happen since libvirt sometimes rounds the memory value. """ xml_def = """ my_vm 3177680 3177680 1 hvm restart """ domain_mock = make_mock_vm(xml_def) ret = virt.update("my_vm", mem={"boot": "3253941043B", "current": "3253941043B"}) assert not ret["definition"] def test_gen_hypervisor_features(): """ Test the virt._gen_xml hypervisor_features handling """ xml_data = virt._gen_xml( virt.libvirt.openAuth.return_value, "hello", 1, 512, {}, {}, "kvm", "hvm", "x86_64", hypervisor_features={"kvm-hint-dedicated": True}, ) root = ET.fromstring(xml_data) assert "on" == root.find("features/kvm/hint-dedicated").attrib["state"] def test_update_hypervisor_features(make_mock_vm): """ Test changing the hypervisor features of a guest """ xml_def = """ my_vm 524288 524288 1 linux /usr/lib/grub2/x86_64-xen/grub.xen restart """ domain_mock = make_mock_vm(xml_def) # Update with no change to the features ret = virt.update("my_vm", hypervisor_features={"kvm-hint-dedicated": True}) assert not ret["definition"] # Alter the features ret = virt.update("my_vm", hypervisor_features={"kvm-hint-dedicated": False}) assert ret["definition"] setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0]) assert "off" == setxml.find("features/kvm/hint-dedicated").get("state") # Add the features xml_def = """ my_vm 524288 524288 1 linux /usr/lib/grub2/x86_64-xen/grub.xen """ domain_mock = make_mock_vm(xml_def) ret = virt.update("my_vm", hypervisor_features={"kvm-hint-dedicated": True}) assert ret["definition"] setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0]) assert "on" == setxml.find("features/kvm/hint-dedicated").get("state") def test_gen_clock(): """ Test the virt._gen_xml clock property """ # Localtime with adjustment xml_data = virt._gen_xml( virt.libvirt.openAuth.return_value, "hello", 1, 512, {}, {}, "kvm", "hvm", "x86_64", clock={"adjustment": 3600, "utc": False}, ) root = ET.fromstring(xml_data) assert "localtime" == root.find("clock").get("offset") assert "3600" == root.find("clock").get("adjustment") # Specific timezone xml_data = virt._gen_xml( virt.libvirt.openAuth.return_value, "hello", 1, 512, {}, {}, "kvm", "hvm", "x86_64", clock={"timezone": "CEST"}, ) root = ET.fromstring(xml_data) assert "timezone" == root.find("clock").get("offset") assert "CEST" == root.find("clock").get("timezone") # UTC xml_data = virt._gen_xml( virt.libvirt.openAuth.return_value, "hello", 1, 512, {}, {}, "kvm", "hvm", "x86_64", clock={"utc": True}, ) root = ET.fromstring(xml_data) assert "utc" == root.find("clock").get("offset") # Timers xml_data = virt._gen_xml( virt.libvirt.openAuth.return_value, "hello", 1, 512, {}, {}, "kvm", "hvm", "x86_64", clock={ "timers": { "tsc": {"frequency": 3504000000, "mode": "native"}, "rtc": { "tickpolicy": "catchup", "slew": 4636, "threshold": 123, "limit": 2342, }, "hpet": {"present": False}, }, }, ) root = ET.fromstring(xml_data) assert "utc" == root.find("clock").get("offset") assert "3504000000" == root.find("clock/timer[@name='tsc']").get("frequency") assert "native" == root.find("clock/timer[@name='tsc']").get("mode") assert "catchup" == root.find("clock/timer[@name='rtc']").get("tickpolicy") assert {"slew": "4636", "threshold": "123", "limit": "2342"} == root.find( "clock/timer[@name='rtc']/catchup" ).attrib assert "no" == root.find("clock/timer[@name='hpet']").get("present") def test_update_clock(make_mock_vm): """ test virt.update with clock parameter """ xml_def = """ my_vm 524288 524288 1 linux /usr/lib/grub2/x86_64-xen/grub.xen restart """ domain_mock = make_mock_vm(xml_def) # Update with no change to the features ret = virt.update( "my_vm", clock={ "utc": False, "adjustment": -3600, "timers": { "tsc": {"frequency": 3504000000, "mode": "native"}, "kvmclock": {"present": False}, }, }, ) assert not ret["definition"] # Update ret = virt.update( "my_vm", clock={ "timezone": "CEST", "timers": { "rtc": { "track": "wall", "tickpolicy": "catchup", "slew": 4636, "threshold": 123, "limit": 2342, }, "hpet": {"present": True}, }, }, ) assert ret["definition"] setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0]) assert "timezone" == setxml.find("clock").get("offset") assert "CEST" == setxml.find("clock").get("timezone") assert {"rtc", "hpet"} == {t.get("name") for t in setxml.findall("clock/timer")} assert "catchup" == setxml.find("clock/timer[@name='rtc']").get("tickpolicy") assert "wall" == setxml.find("clock/timer[@name='rtc']").get("track") assert {"slew": "4636", "threshold": "123", "limit": "2342"} == setxml.find( "clock/timer[@name='rtc']/catchup" ).attrib assert "yes" == setxml.find("clock/timer[@name='hpet']").get("present") # Revert to UTC ret = virt.update("my_vm", clock={"utc": True, "adjustment": None, "timers": None}) assert ret["definition"] setxml = ET.fromstring(virt.libvirt.openAuth().defineXML.call_args[0][0]) assert {"offset": "utc"} == setxml.find("clock").attrib assert setxml.find("clock/timer") is None def test_update_stop_on_reboot_reset(make_mock_vm): """ Test virt.update to remove the on_reboot=destroy flag """ xml_def = """ my_vm 524288 524288 1 destroy hvm """ domain_mock = make_mock_vm(xml_def) ret = virt.update("my_vm") assert ret["definition"] define_mock = virt.libvirt.openAuth().defineXML setxml = ET.fromstring(define_mock.call_args[0][0]) assert "restart" == setxml.find("./on_reboot").text def test_update_stop_on_reboot(make_mock_vm): """ Test virt.update to add the on_reboot=destroy flag """ xml_def = """ my_vm 524288 524288 1 hvm """ domain_mock = make_mock_vm(xml_def) ret = virt.update("my_vm", stop_on_reboot=True) assert ret["definition"] define_mock = virt.libvirt.openAuth().defineXML setxml = ET.fromstring(define_mock.call_args[0][0]) assert "destroy" == setxml.find("./on_reboot").text def test_init_no_stop_on_reboot(make_capabilities): """ Test virt.init to add the on_reboot=restart flag """ make_capabilities() with patch.dict(virt.os.__dict__, {"chmod": MagicMock(), "makedirs": MagicMock()}): with patch.dict(virt.__salt__, {"cmd.run": MagicMock()}): virt.init("test_vm", 2, 2048, start=False) define_mock = virt.libvirt.openAuth().defineXML setxml = ET.fromstring(define_mock.call_args[0][0]) assert "restart" == setxml.find("./on_reboot").text def test_init_stop_on_reboot(make_capabilities): """ Test virt.init to add the on_reboot=destroy flag """ make_capabilities() with patch.dict(virt.os.__dict__, {"chmod": MagicMock(), "makedirs": MagicMock()}): with patch.dict(virt.__salt__, {"cmd.run": MagicMock()}): virt.init("test_vm", 2, 2048, stop_on_reboot=True, start=False) define_mock = virt.libvirt.openAuth().defineXML setxml = ET.fromstring(define_mock.call_args[0][0]) assert "destroy" == setxml.find("./on_reboot").text