Example #1
0
 def test_make_name(self, prefix, iface):
     for index, value in _CONVERTED_VALUES:
         computed = drivename.make(iface, index)
         expected = prefix + value
         assert computed == expected, \
             "mismatch for %s: computed=%s expected=%s" % (
                 (iface, index), computed, expected)
Example #2
0
def test_change_cd_loading():
    sd_id = str(uuid.uuid4())
    img_id = str(uuid.uuid4())
    vol_id = str(uuid.uuid4())
    drive_spec = {
        "device": "cdrom",
        "domainID": sd_id,
        "poolID": str(uuid.uuid4()),
        "imageID": img_id,
        "volumeID": vol_id,
    }
    cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": drive_spec,
    }
    device = drivename.make(cdrom_spec["iface"], cdrom_spec["index"])

    with fake.VM(
            cif=ClientIF(),
            create_device_objects=True,
            xmldevices=EMPTY_CD_DEVICE_XML,
            metadata=EMPTY_CD_METADATA_XML
    ) as fakevm:
        fakevm._dom = fake.Domain()
        fakevm.changeCD(cdrom_spec)

        assert (sd_id, img_id, vol_id) in fakevm.cif.irs.prepared_volumes
        with fakevm._md_desc.device(devtype=hwclass.DISK, name=device) as dev:
            _assert_pdiv(drive_spec, dev)
            assert "change" not in dev
Example #3
0
    def test_specParams_ignore_empty(self):
        conf = {
            'device': 'cdrom',
            'iface': 'ide',
            'index': '3',
            'path': '',
            'readonly': 'true',
            'type': 'disk',
        }
        source_xml = """<?xml version='1.0' encoding='UTF-8'?>
<domain type="kvm" xmlns:ovirt-vm="http://ovirt.org/vm/1.0">
<metadata>
  <ovirt-vm:vm>
    <ovirt-vm:device name="hdd" devtype="disk">
      <ovirt-vm:specParams />
      </ovirt-vm:device>
    </ovirt-vm:vm>
  </metadata>
</domain>"""
        desc = metadata.Descriptor.from_xml(source_xml)
        with desc.device(devtype=conf['type'],
                         name=drivename.make(conf['iface'],
                                             conf['index'])) as dev:
            # test we ignore IO tune settings from metadata, should we
            # (unexpectedly) found it (see below to learn why)
            self.assertEqual(dev, {'specParams': {}})
Example #4
0
def test_cd_recovery_after_cd_eject(rec_vm_after_eject):
    # Simulate recovery when user wants to eject CD and failure happened once
    # the metadata was updated with change element and the CD has been already
    # ejected from VM.

    cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": CD_PDIV,
    }
    device = drivename.make(cdrom_spec["iface"], cdrom_spec["index"])

    # Prepare image for the CD to check that it is not torn down.
    drive = dict(CD_PDIV)
    drive["device"] = "cdrom"
    rec_vm_after_eject.cif.prepareVolumePath(drive)

    # Run VM with recovery turned on.
    rec_vm_after_eject.run()

    # Vm.run() waits for Vm._vmStartEvent which is set before recovery
    # starts. Wait little bit for recovery.
    wait_for_recovery(rec_vm_after_eject)

    volume = (
        CD_PDIV["domainID"],
        CD_PDIV["imageID"],
        CD_PDIV["volumeID"]
    )
    assert volume not in rec_vm_after_eject.cif.irs.prepared_volumes
    with rec_vm_after_eject._md_desc.device(
            devtype=hwclass.DISK, name=device) as dev:
        assert dev == {}
Example #5
0
def test_change_cd(vm_with_cd):
    new_sd_id = str(uuid.uuid4())
    new_img_id = str(uuid.uuid4())
    new_vol_id = str(uuid.uuid4())
    new_drive_spec = {
        "device": "cdrom",
        "domainID": new_sd_id,
        "poolID": str(uuid.uuid4()),
        "imageID": new_img_id,
        "volumeID": new_vol_id,
    }
    cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": new_drive_spec,
    }
    device = drivename.make(cdrom_spec["iface"], cdrom_spec["index"])

    # Change CD.
    vm_with_cd.changeCD(cdrom_spec)

    volume = (new_sd_id, new_img_id, new_vol_id)
    assert volume in vm_with_cd.cif.irs.prepared_volumes
    with vm_with_cd._md_desc.device(devtype=hwclass.DISK, name=device) as dev:
        _assert_pdiv(new_drive_spec, dev)
        assert "change" not in dev
Example #6
0
 def test_make_name(self, prefix, iface):
     for index, value in _CONVERTED_VALUES:
         computed = drivename.make(iface, index)
         expected = prefix + value
         self.assertEqual(
             computed, expected,
             "mismatch for %s: computed=%s expected=%s" % (
                 (iface, index), computed, expected))
Example #7
0
    def test_deeply_nested_metadata_preserved(self):
        conf = {
            'device': 'cdrom',
            'iface': 'ide',
            'index': '3',
            'path': '',
            'readonly': 'true',
            'specParams': {
                'vmPayload': {
                    'file': {
                        'openstack/content/0000': 'something',
                        'openstack/latest/meta_data.json': 'something',
                        'openstack/latest/user_data': 'something',
                    },
                    'volId': 'config-2',
                }
            },
            'type': 'disk',
        }

        expected_xml = """<?xml version='1.0' encoding='UTF-8'?>
<vm>
<device name="hdd" devtype="disk">
  <device>cdrom</device>
    <iface>ide</iface>
    <index>3</index>
    <path />
    <readonly>true</readonly>
    <type>disk</type>
    <specParams>
      <vmPayload>
        <volId>config-2</volId>
        <file path='openstack/content/0000'>something</file>
        <file path='openstack/latest/meta_data.json'>something</file>
        <file path='openstack/latest/user_data'>something</file>
      </vmPayload>
    </specParams>
  </device>
</vm>"""

        desc = metadata.Descriptor()
        with desc.device(devtype=conf['type'],
                         name=drivename.make(conf['iface'],
                                             conf['index'])) as dev:
            dev.update(conf)
        dom = FakeDomain()
        desc.dump(dom)
        # the first dump() used to -wrongly- modify the supplied data
        desc.dump(dom)
        for produced_xml in dom.xml.values():
            self.assertXMLEqual(produced_xml, expected_xml)
Example #8
0
def test_change_cd_failed_libvirt_and_vol_teardown(monkeypatch, vm_with_cd):
    device = drivename.make("sata", "2")

    vm_with_cd._dom = fake.Domain(virtError=libvirt.VIR_ERR_XML_ERROR)

    def failing_teardown(self, sdUUID, spUUID, imgUUID, volUUID=None):
        raise Exception("Image teardown failed.")

    monkeypatch.setattr(fake.IRS, "teardownImage", failing_teardown)

    # Verify, that ChangeDiskFailed is thrown when libvirt fails to update disk
    # device and teardown of loaded CD also fails. Contrary to
    # test_change_cd_failed_libvirt(), now CD is loaded so tear down of the CD
    # is called, which will fail as we monkey patch it.
    with pytest.raises(exception.ChangeDiskFailed):
        vm_with_cd._change_cd(device, LOADING_DRIVE_SPEC)
Example #9
0
def test_cd_recovery_after_cd_change(rec_vm_after_change):
    # Simulate recovery when failure happened once the metadata was updated
    # with change element, new CD image was prepared and switched in VM, but
    # metadata after the change wasn't updated and old CD torn down. In this
    # case both images are prepared and old one needs to be torn down.

    cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": CD_PDIV,
    }
    device = drivename.make(cdrom_spec["iface"], cdrom_spec["index"])

    # Prepare image for old CD to check that it is torn down.
    drive = dict(CD_PDIV)
    drive["device"] = "cdrom"
    rec_vm_after_change.cif.prepareVolumePath(drive)

    # Prepare image for loaded CD.
    drive = dict(LOADING_PDIV)
    drive["device"] = "cdrom"
    rec_vm_after_change.cif.prepareVolumePath(drive)

    # Run VM with recovery turned on.
    rec_vm_after_change.run()

    # Vm.run() waits for Vm._vmStartEvent which is set before recovery
    # starts. Wait little bit for recovery.
    wait_for_recovery(rec_vm_after_change)

    old_volume = (
        CD_PDIV["domainID"],
        CD_PDIV["imageID"],
        CD_PDIV["volumeID"]
    )
    new_volume = (
        LOADING_PDIV["domainID"],
        LOADING_PDIV["imageID"],
        LOADING_PDIV["volumeID"]
    )
    assert old_volume not in rec_vm_after_change.cif.irs.prepared_volumes
    assert new_volume in rec_vm_after_change.cif.irs.prepared_volumes
    with rec_vm_after_change._md_desc.device(
            devtype=hwclass.DISK, name=device) as dev:
        _assert_pdiv(LOADING_PDIV, dev)
        assert "change" not in dev
Example #10
0
def test_change_cd_ejecting(vm_with_cd):
    sd_id = "88252cf6-381e-48f0-8795-a294a32c7149"
    vol_id = "626a493f-5214-4337-b580-96a1ce702c2a"

    # Eject CD.
    cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": None,
    }
    device = drivename.make(cdrom_spec["iface"], cdrom_spec["index"])

    vm_with_cd.changeCD(cdrom_spec)

    assert (sd_id, vol_id) not in vm_with_cd.cif.irs.prepared_volumes
    with vm_with_cd._md_desc.device(devtype=hwclass.DISK, name=device) as dev:
        assert dev == {}
Example #11
0
def test_cd_recovery_after_cd_eject_no_pdiv(rec_vm_after_eject_no_pdiv):
    # Simulate recovery when user wants to eject CD and failure happened once
    # the metadata was updated with change element and the CD has been already
    # ejected from VM. However, in this case there are no PDIV metadata about
    # ejected CD and therefore we cannot tear the image down during recovery.
    # This can happen when migrating from older engine to new one.

    cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": CD_PDIV,
    }
    device = drivename.make(cdrom_spec["iface"], cdrom_spec["index"])

    # Prepare image for the CD to check that it is not torn down.
    drive = dict(CD_PDIV)
    drive["device"] = "cdrom"
    rec_vm_after_eject_no_pdiv.cif.prepareVolumePath(drive)

    # Run VM with recovery turned on.
    rec_vm_after_eject_no_pdiv.run()

    # Vm.run() waits for Vm._vmStartEvent which is set before recovery
    # starts. Wait little bit for recovery.
    wait_for_recovery(rec_vm_after_eject_no_pdiv)

    volume = (
        CD_PDIV["domainID"],
        CD_PDIV["imageID"],
        CD_PDIV["volumeID"]
    )
    # As there are no metadata about ejected CD, we cannot tear it down during
    # recovery.
    assert volume in rec_vm_after_eject_no_pdiv.cif.irs.prepared_volumes
    with rec_vm_after_eject_no_pdiv._md_desc.device(
            devtype=hwclass.DISK, name=device) as dev:
        # No real device was found, recovery was skipped.
        expected = {
            "change": {
                "state": "ejecting",
            }
        }
        assert dev == expected
Example #12
0
def test_change_cd_failed_libvirt_and_discard_cd_change(monkeypatch):
    device = drivename.make("sata", "2")

    def failing_discard_cd_change(self, device):
        raise Exception("Discard CD change failed")

    monkeypatch.setattr(vm.Vm, "_discard_cd_change", failing_discard_cd_change)

    with fake.VM(
            cif=ClientIF(),
            create_device_objects=True,
            xmldevices=EMPTY_CD_DEVICE_XML,
            metadata=EMPTY_CD_METADATA_XML
    ) as fakevm:
        fakevm._dom = fake.Domain(virtError=libvirt.VIR_ERR_XML_ERROR)

        # Verify, that ChangeDiskFailed is thrown when libvirt fails to update
        # disk device and _diskcard_cd_change() fails as well. Teardown will
        # pass and monkey patched _discard_cd_change() will raise.
        with pytest.raises(exception.ChangeDiskFailed):
            fakevm._change_cd(device, LOADING_DRIVE_SPEC)
Example #13
0
def test_cd_recovery_before_cd_change(rec_vm_before_change):
    # Simulate recovery when failure happened once the metadata was updated
    # with change element and new CD image was prepared, but failed before
    # the CD was switched.
    # Failing even before preparing new CD image the situation is same, tearing
    # down image which is not prepared doesn't do anything.

    cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": CD_PDIV,
    }
    device = drivename.make(cdrom_spec["iface"], cdrom_spec["index"])

    # Prepare image for loaded CD.
    drive = dict(CD_PDIV)
    drive["device"] = "cdrom"
    rec_vm_before_change.cif.prepareVolumePath(drive)

    # Run VM with recovery turned on.
    rec_vm_before_change.run()

    # Vm.run() waits for Vm._vmStartEvent which is set before recovery
    # starts. Wait little bit for recovery.
    wait_for_recovery(rec_vm_before_change)

    # Check that the new CD image was torn down.
    volume = (
        LOADING_PDIV["domainID"],
        LOADING_PDIV["imageID"],
        LOADING_PDIV["volumeID"]
    )
    assert volume not in rec_vm_before_change.cif.irs.prepared_volumes

    # Check that metadata looks like before changing CD.
    with rec_vm_before_change._md_desc.device(
            devtype=hwclass.DISK, name=device) as dev:
        _assert_pdiv(CD_PDIV, dev)
        assert "change" not in dev
Example #14
0
    def test_specParams_ignore_iotune(self):
        conf = {
            'device': 'cdrom',
            'iface': 'ide',
            'index': '3',
            'path': '',
            'readonly': 'true',
            'type': 'disk',
        }
        source_xml = """<?xml version='1.0' encoding='UTF-8'?>
<domain type="kvm" xmlns:ovirt-vm="http://ovirt.org/vm/1.0">
<metadata>
  <ovirt-vm:vm>
    <ovirt-vm:device name="hdd" devtype="disk">
      <ovirt-vm:specParams>
        <ovirt-vm:ioTune>
          <ovirt-vm:read_iops_sec>100</ovirt-vm:read_iops_sec>
        </ovirt-vm:ioTune>
      </ovirt-vm:specParams>
      </ovirt-vm:device>
    </ovirt-vm:vm>
  </metadata>
</domain>"""
        desc = metadata.Descriptor.from_xml(source_xml)
        with desc.device(devtype=conf['type'],
                         name=drivename.make(conf['iface'],
                                             conf['index'])) as dev:
            # test we ignore IO tune settings from metadata, should we
            # (unexpectedly) found it (see below to learn why)
            self.assertEqual(dev, {'specParams': {}})

        expected_xml = u"""<?xml version='1.0' encoding='utf-8'?>
<ovirt-vm:vm xmlns:ovirt-vm="http://ovirt.org/vm/1.0">
    <ovirt-vm:device devtype="disk" name="hdd" />
</ovirt-vm:vm>"""
        # test we never serialize IO tune settings - they belong
        # in the plain regular libvirt domain XML.
        self.assertXMLEqual(desc.to_xml(), expected_xml)
Example #15
0
def test_cd_recovery_before_cd_eject(rec_vm_before_eject):
    # Simulate recovery when user wants to eject CD and failure happened once
    # the metadata was updated with change element, but the CD hasn't been
    # ejected from VM.

    cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": CD_PDIV,
    }
    device = drivename.make(cdrom_spec["iface"], cdrom_spec["index"])

    # Prepare image for the loaded CD.
    drive = dict(CD_PDIV)
    drive["device"] = "cdrom"
    rec_vm_before_eject.cif.prepareVolumePath(drive)

    # Run VM with recovery turned on.
    rec_vm_before_eject.run()

    # Vm.run() waits for Vm._vmStartEvent which is set before recovery
    # starts. Wait little bit for recovery.
    wait_for_recovery(rec_vm_before_eject)

    # Check that the CD image was not torn down.
    volume = (
        CD_PDIV["domainID"],
        CD_PDIV["imageID"],
        CD_PDIV["volumeID"]
    )
    assert volume in rec_vm_before_eject.cif.irs.prepared_volumes

    # Check that metadata looks like before ejecting CD.
    with rec_vm_before_eject._md_desc.device(
            devtype=hwclass.DISK, name=device) as dev:
        _assert_pdiv(CD_PDIV, dev)
        assert "change" not in dev
Example #16
0
def test_change_cd_teardown_old_cd_failed(monkeypatch, vm_with_cd):
    new_sd_id = str(uuid.uuid4())
    new_img_id = str(uuid.uuid4())
    new_vol_id = str(uuid.uuid4())
    new_drive_spec = {
        "device": "cdrom",
        "domainID": new_sd_id,
        "poolID": str(uuid.uuid4()),
        "imageID": new_img_id,
        "volumeID": new_vol_id,
    }
    new_cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": new_drive_spec,
    }
    device = drivename.make(new_cdrom_spec["iface"], new_cdrom_spec["index"])

    def failing_teardown(self, sdUUID, spUUID, imgUUID, volUUID=None):
        raise Exception("Image teardown failed.")

    monkeypatch.setattr(fake.IRS, "teardownImage", failing_teardown)

    # Change CD. Tearing down old CD will fail. However, we ignore the failure,
    # as we already successfully updated VM disk, so no exception should be
    # thrown from this call.
    vm_with_cd.changeCD(new_cdrom_spec)

    # Check new CD is prepared.
    volume = (new_sd_id, new_img_id, new_vol_id)
    assert volume in vm_with_cd.cif.irs.prepared_volumes

    # Assert metadata is in consistent state and new CD is loaded.
    with vm_with_cd._md_desc.device(devtype=hwclass.DISK, name=device) as dev:
        _assert_pdiv(new_drive_spec, dev)
        assert "change" not in dev
Example #17
0
def test_change_cd_failed_libvirt():
    sd_id = str(uuid.uuid4())
    vol_id = str(uuid.uuid4())
    drive_spec = {
        "device": "cdrom",
        "domainID": sd_id,
        "poolID": str(uuid.uuid4()),
        "imageID": str(uuid.uuid4()),
        "volumeID": vol_id,
    }
    cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": drive_spec,
    }
    device = drivename.make(cdrom_spec["iface"], cdrom_spec["index"])

    with fake.VM(
            cif=ClientIF(),
            create_device_objects=True,
            xmldevices=EMPTY_CD_DEVICE_XML,
            metadata=EMPTY_CD_METADATA_XML
    ) as fakevm:
        fakevm._dom = fake.Domain(virtError=libvirt.VIR_ERR_XML_ERROR)

        # Verify, that ChangeDiskFailed is thrown when libvirt fails to update
        # disk device. No CD is loaded, so if libvirt succeeded, no other
        # exception is thrown.
        with pytest.raises(exception.ChangeDiskFailed):
            fakevm.changeCD(cdrom_spec)

        # We started with empty CD. Verify that the image was torn down and
        # metadata was reset back to empty.
        assert (sd_id, vol_id) not in fakevm.cif.irs.prepared_volumes
        with fakevm._md_desc.device(devtype=hwclass.DISK, name=device) as dev:
            assert dev == {}
Example #18
0
def _get_drive_conf_identifying_attrs(conf):
    return {
        'devtype': conf['type'],
        'name': drivename.make(conf['iface'], conf['index']),
    }
def _get_drive_conf_identifying_attrs(conf):
    return {
        'devtype': conf['type'],
        'name': drivename.make(conf['iface'], conf['index']),
    }
Example #20
0
 def test_make_name_invalid_parameters(self, iface, index):
     with pytest.raises(ValueError):
         drivename.make(iface, index)
Example #21
0
def test_change_cd_apply_cd_change_failed(monkeypatch):
    old_sd_id = str(uuid.uuid4())
    old_vol_id = str(uuid.uuid4())
    old_drive_spec = {
        "device": "cdrom",
        "domainID": old_sd_id,
        "poolID": str(uuid.uuid4()),
        "imageID": str(uuid.uuid4()),
        "volumeID": old_vol_id,
    }
    old_cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": old_drive_spec,
    }

    new_drive_spec = {
        "device": "cdrom",
        "domainID": str(uuid.uuid4()),
        "poolID": str(uuid.uuid4()),
        "imageID": str(uuid.uuid4()),
        "volumeID": str(uuid.uuid4()),
    }
    new_cdrom_spec = {
        "iface": "sata",
        "index": "2",
        "drive_spec": new_drive_spec,
    }
    device = drivename.make(new_cdrom_spec["iface"], new_cdrom_spec["index"])

    with fake.VM(
            cif=ClientIF(),
            create_device_objects=True,
            xmldevices=EMPTY_CD_DEVICE_XML,
            metadata=EMPTY_CD_METADATA_XML
    ) as fakevm:
        fakevm._dom = fake.Domain()

        # Insert CD.
        fakevm.changeCD(old_cdrom_spec)

        def failing_apply_cd_change(self, device):
            raise Exception("Apply CD change failed")

        monkeypatch.setattr(
            vm.Vm, "_apply_cd_change", failing_apply_cd_change)

        # Change CD. Apply cd change to metadata will fail, but as we already
        # succeeded to change CD, we ignore this error. The old disk should be
        # torn down and the call should succeed.
        fakevm.changeCD(new_cdrom_spec)

        # Tear down of the old image should succeed.
        assert (old_sd_id, old_vol_id) not in fakevm.cif.irs.prepared_volumes

        # As updating of metadata failed, metadata will be in inconsistent
        # state and should contain old CD and `change` element with new CD
        # PDIV.
        with fakevm._md_desc.device(devtype=hwclass.DISK, name=device) as dev:
            _assert_pdiv(old_drive_spec, dev)
            assert "change" in dev
            _assert_pdiv(new_drive_spec, dev["change"])