예제 #1
0
    def _monkeyPatchedMemorySample(self, freeMemory, totalMemory):
        node_id, cpu_id = 0, 0

        def fakeMemoryStats(cell):
            return {'free': freeMemory, 'total': totalMemory}

        def fakeNumaTopology():
            return {
                node_id: {
                    'cpus': [cpu_id],
                    'hugepages': {
                        4: {
                            'totalPages': '2500'
                        },
                        2048: {
                            'totalPages': '100'
                        }
                    }
                }
            }

        fakeConnection = fake.Connection()
        fakeConnection.free_pages = {'4': '5', '2048': '10'}

        return MonkeyPatchScope([(numa, 'topology', fakeNumaTopology),
                                 (numa, 'memory_by_cell', fakeMemoryStats),
                                 (numa.libvirtconnection, 'get',
                                  lambda: fakeConnection)])
예제 #2
0
 def test_register(self):
     params = make_secret(password="******")
     sec = secret.Secret(params)
     con = vmfakelib.Connection()
     sec.register(con)
     virsec = con.secrets[sec.uuid]
     self.assertEqual(virsec.value, "12345678")
예제 #3
0
 def test_define_cannot_change_usage_id(self):
     con = vmfakelib.Connection()
     xml1 = """
     <secret>
         <uuid>uuid</uuid>
         <usage type="ceph">
             <name>name 1</name>
         </usage>
     </secret>
     """
     xml2 = """
     <secret>
         <uuid>uuid</uuid>
         <usage type="ceph">
             <name>name 2</name>
         </usage>
     </secret>
     """
     con.secretDefineXML(xml1)
     try:
         con.secretDefineXML(xml2)
     except libvirt.libvirtError as e:
         self.assertEqual(e.get_error_code(),
                          libvirt.VIR_ERR_INTERNAL_ERROR)
     else:
         self.fail("libvirtError was not raised")
예제 #4
0
 def test_lookup_error(self):
     con = vmfakelib.Connection()
     try:
         con.secretLookupByUUIDString('no-such-uuid')
     except libvirt.libvirtError as e:
         self.assertEqual(e.get_error_code(), libvirt.VIR_ERR_NO_SECRET)
     else:
         self.fail("libvirtError was not raised")
예제 #5
0
 def test_lookup(self):
     con = vmfakelib.Connection()
     xml = """
     <secret>
         <uuid>uuid</uuid>
         <usage type="ceph">
             <name>name</name>
         </usage>
     </secret>
     """
     con.secretDefineXML(xml)
     sec = con.secretLookupByUUIDString('uuid')
     self.assertEqual(sec.usage_id, "name")
예제 #6
0
 def test_define_new_with_description(self):
     con = vmfakelib.Connection()
     xml = """
     <secret>
         <description>description</description>
         <uuid>uuid</uuid>
         <usage type="ceph">
             <name>name</name>
         </usage>
     </secret>
     """
     con.secretDefineXML(xml)
     sec = con.secrets['uuid']
     self.assertEqual(sec.description, "description")
예제 #7
0
 def test_define_new(self):
     con = vmfakelib.Connection()
     xml = """
     <secret>
         <uuid>uuid</uuid>
         <usage type="ceph">
             <name>name</name>
         </usage>
     </secret>
     """
     con.secretDefineXML(xml)
     sec = con.secrets['uuid']
     self.assertEqual(sec.uuid, "uuid")
     self.assertEqual(sec.usage_type, "ceph")
     self.assertEqual(sec.usage_id, "name")
     self.assertEqual(sec.description, None)
예제 #8
0
 def test_define_replace(self):
     con = vmfakelib.Connection()
     xml1 = """
     <secret>
         <description>old description</description>
         <uuid>uuid</uuid>
         <usage type="ceph">
             <name>name</name>
         </usage>
     </secret>
     """
     xml2 = """
     <secret>
         <description>new description</description>
         <uuid>uuid</uuid>
         <usage type="ceph">
             <name>name</name>
         </usage>
     </secret>
     """
     con.secretDefineXML(xml1)
     con.secretDefineXML(xml2)
     sec = con.secrets['uuid']
     self.assertEqual(sec.description, "new description")
예제 #9
0
class TestVmOperations(XMLTestCase):
    # just numbers, no particular meaning
    UPDATE_OFFSETS = [-3200, 3502, -2700, 3601]
    BASE_OFFSET = 42

    VNC_DEVICE = {'type': 'graphics', 'device': 'vnc', 'port': '-1'}
    SPICE_DEVICE = {'type': 'graphics', 'device': 'spice', 'port': '-1'}

    GRAPHIC_DEVICES = [
        SPICE_DEVICE,
        VNC_DEVICE,
    ]

    @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection())
    @permutations([[define.NORMAL], [define.ERROR]])
    def testTimeOffsetNotPresentByDefault(self, exitCode):
        with fake.VM() as testvm:
            testvm.setDownStatus(exitCode, vmexitreason.GENERIC_ERROR)
            self.assertFalse('timeOffset' in testvm.getStats())

    @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection())
    @permutations([[define.NORMAL], [define.ERROR]])
    def testTimeOffsetRoundtrip(self, exitCode):
        with fake.VM({'timeOffset': self.BASE_OFFSET}) as testvm:
            testvm.setDownStatus(exitCode, vmexitreason.GENERIC_ERROR)
            self.assertEqual(testvm.getStats()['timeOffset'], self.BASE_OFFSET)

    @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection())
    @permutations([[define.NORMAL], [define.ERROR]])
    def testTimeOffsetRoundtriupAcrossInstances(self, exitCode):
        # bz956741
        lastOffset = 0
        for offset in self.UPDATE_OFFSETS:
            with fake.VM({'timeOffset': lastOffset}) as testvm:
                testvm.onRTCUpdate(offset)
                testvm.setDownStatus(exitCode, vmexitreason.GENERIC_ERROR)
                vmOffset = testvm.getStats()['timeOffset']
                self.assertEqual(vmOffset, str(lastOffset + offset))
                # the field in getStats is str, not int
                lastOffset = int(vmOffset)

    @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection())
    @permutations([[define.NORMAL], [define.ERROR]])
    def testTimeOffsetUpdateIfAbsent(self, exitCode):
        # bz956741 (-like, simpler case)
        with fake.VM() as testvm:
            for offset in self.UPDATE_OFFSETS:
                testvm.onRTCUpdate(offset)
            # beware of type change!
            testvm.setDownStatus(exitCode, vmexitreason.GENERIC_ERROR)
            self.assertEqual(testvm.getStats()['timeOffset'],
                             str(self.UPDATE_OFFSETS[-1]))

    @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection())
    @permutations([[define.NORMAL], [define.ERROR]])
    def testTimeOffsetUpdateIfPresent(self, exitCode):
        with fake.VM({'timeOffset': self.BASE_OFFSET}) as testvm:
            for offset in self.UPDATE_OFFSETS:
                testvm.onRTCUpdate(offset)
            # beware of type change!
            testvm.setDownStatus(exitCode, vmexitreason.GENERIC_ERROR)
            self.assertEqual(testvm.getStats()['timeOffset'],
                             str(self.BASE_OFFSET + self.UPDATE_OFFSETS[-1]))

    def testUpdateSingleDeviceGraphics(self):
        devXmls = ('<graphics connected="disconnect" passwd="12345678"'
                   ' port="5900" type="spice"/>',
                   '<graphics passwd="12345678" port="5900" type="vnc"/>')
        for device, devXml in zip(self.GRAPHIC_DEVICES, devXmls):
            graphics_xml = ('<graphics type="{device}" port="{port}"/>'.format(
                **device))
            domXml = '''
                <devices>
                    <graphics type="%s" port="5900" />
                </devices>''' % device['device']
            self._verifyDeviceUpdate(device, graphics_xml, domXml, devXml,
                                     _GRAPHICS_DEVICE_PARAMS)

    def testUpdateSingleDeviceGraphicsNoConnected(self):
        graphics_params = dict(_GRAPHICS_DEVICE_PARAMS)
        del graphics_params['existingConnAction']
        devXmls = ('<graphics passwd="12345678"'
                   ' port="5900" type="spice"/>',
                   '<graphics passwd="12345678" port="5900" type="vnc"/>')
        for device, devXml in zip(self.GRAPHIC_DEVICES, devXmls):
            graphics_xml = ('<graphics type="{device}" port="{port}"/>'.format(
                **device))
            domXml = '''
                <devices>
                    <graphics type="%s" port="5900" />
                </devices>''' % device['device']
            self._verifyDeviceUpdate(device, graphics_xml, domXml, devXml,
                                     graphics_params)

    def testUpdateMultipleDeviceGraphics(self):
        devXmls = ('<graphics connected="disconnect" passwd="12345678"'
                   ' port="5900" type="spice"/>',
                   '<graphics passwd="12345678" port="5901" type="vnc"/>')
        domXml = '''
            <devices>
                <graphics type="spice" port="5900" />
                <graphics type="vnc" port="5901" />
            </devices>'''
        graphics_xml = ''
        for device in self.GRAPHIC_DEVICES:
            graphics_xml += (
                '<graphics type="{device}" port="{port}"/>'.format(**device))
        for device, devXml in zip(self.GRAPHIC_DEVICES, devXmls):
            self._verifyDeviceUpdate(device, graphics_xml, domXml, devXml,
                                     _GRAPHICS_DEVICE_PARAMS)

    def _updateGraphicsDevice(self, testvm, device_type, graphics_params):
        def _check_ticket_params(domXML, conf, params):
            self.assertEqual(params, _TICKET_PARAMS)

        def _fake_set_vnc_pwd(username, pwd):
            pass

        with MonkeyPatchScope([
            (hooks, 'before_vm_set_ticket', _check_ticket_params),
            (saslpasswd2, 'set_vnc_password', _fake_set_vnc_pwd)
        ]):
            params = {'graphicsType': device_type}
            params.update(graphics_params)
            return testvm.updateDevice(params)

    def _verifyDeviceUpdate(self, device, allDevices, domXml, devXml,
                            graphics_params):
        with fake.VM(xmldevices=allDevices) as testvm:
            testvm._dom = fake.Domain(domXml)

            self._updateGraphicsDevice(testvm, device['device'],
                                       graphics_params)

            self.assertXMLEqual(testvm._dom.devXml, devXml)

    def testSetSaslPasswordInFips(self):
        graphics_params = dict(_GRAPHICS_DEVICE_PARAMS)
        del graphics_params['existingConnAction']
        device = self.GRAPHIC_DEVICES[1]  # VNC
        graphics_xml = ('<graphics type="%s" port="5900"/>' %
                        (device['device'], ))
        device_xml = '<devices>%s</devices>' '' % (graphics_xml, )

        with fake.VM(xmldevices=graphics_xml) as testvm:

            def _fake_set_vnc_pwd(username, pwd):
                testvm.pwd = pwd
                testvm.username = username

            testvm._dom = fake.Domain(device_xml)
            testvm.pwd = "invalid"
            params = {'graphicsType': device['device']}
            params.update(graphics_params)
            params['params']['fips'] = 'true'
            params['params']['vncUsername'] = '******'

            with MonkeyPatchScope([(saslpasswd2, 'set_vnc_password',
                                    _fake_set_vnc_pwd)]):
                testvm.updateDevice(params)

            self.assertEqual(password.unprotect(params['password']),
                             testvm.pwd)
            self.assertEqual(params['params']['vncUsername'], testvm.username)

    def testClearSaslPasswordNoFips(self):
        graphics_params = dict(_GRAPHICS_DEVICE_PARAMS)
        del graphics_params['existingConnAction']
        device = self.GRAPHIC_DEVICES[1]  # VNC
        graphics_xml = ('<graphics type="%s" port="5900"/>' %
                        (device['device'], ))
        device_xml = '<devices>%s</devices>' '' % (graphics_xml, )

        with fake.VM(xmldevices=graphics_xml) as testvm:

            def _fake_remove_pwd(username):
                testvm.username = username

            testvm._dom = fake.Domain(device_xml)
            params = {'graphicsType': device['device']}
            params.update(graphics_params)
            params['params']['vncUsername'] = '******'

            with MonkeyPatchScope([(saslpasswd2, 'remove_vnc_password',
                                    _fake_remove_pwd)]):
                testvm.updateDevice(params)

            self.assertEqual(params['params']['vncUsername'], testvm.username)

    def testDomainNotRunningWithoutDomain(self):
        with fake.VM() as testvm:
            self.assertFalse(testvm._isDomainRunning())

    def testDomainNotRunningByState(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain(domState=libvirt.VIR_DOMAIN_SHUTDOWN)
            self.assertFalse(testvm._isDomainRunning())

    def testDomainIsRunning(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain(domState=libvirt.VIR_DOMAIN_RUNNING)
            self.assertTrue(testvm._isDomainRunning())

    def testDomainIsReadyForCommands(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain()
            self.assertTrue(testvm.isDomainReadyForCommands())

    @permutations([
        # code, text
        [libvirt.VIR_ERR_NO_DOMAIN, "Disappeared domain"],
        [libvirt.VIR_ERR_OPERATION_INVALID, "Operation invalid"],
    ])
    def testIgnoreKnownErrors(self, code, text):
        def _fail(*args):
            raise_libvirt_error(code, text)

        with fake.VM() as testvm:
            dom = fake.Domain()
            dom.controlInfo = _fail
            testvm._dom = dom
            self.assertFalse(testvm.isDomainReadyForCommands())

    def testDomainNoneNotReadyForCommands(self):
        with fake.VM() as testvm:
            self.assertFalse(testvm.isDomainReadyForCommands())

    def testReadyForCommandsRaisesLibvirtError(self):
        def _fail(*args):
            # anything != NO_DOMAIN is good
            raise_libvirt_error(libvirt.VIR_ERR_INTERNAL_ERROR,
                                "Fake internal error")

        with fake.VM() as testvm:
            dom = fake.Domain()
            dom.controlInfo = _fail
            testvm._dom = dom
            self.assertRaises(libvirt.libvirtError,
                              testvm.isDomainReadyForCommands)

    def testReadPauseCodeDomainRunning(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain(domState=libvirt.VIR_DOMAIN_RUNNING)
            self.assertEqual(testvm._readPauseCode(), 'NOERR')

    def testReadPauseCodeDomainPausedCrash(self):
        with fake.VM() as testvm:
            # if paused for different reason we must not extend the disk
            # so anything else is ok
            dom = fake.Domain(domState=libvirt.VIR_DOMAIN_PAUSED,
                              domReason=libvirt.VIR_DOMAIN_PAUSED_CRASHED)
            testvm._dom = dom
            self.assertNotEqual(testvm._readPauseCode(), 'ENOSPC')

    def testReadPauseCodeDomainPausedENOSPC(self):
        with fake.VM() as testvm:
            dom = fake.Domain(domState=libvirt.VIR_DOMAIN_PAUSED,
                              domReason=libvirt.VIR_DOMAIN_PAUSED_IOERROR)
            dom.setDiskErrors({
                'vda': libvirt.VIR_DOMAIN_DISK_ERROR_NO_SPACE,
                'hdc': libvirt.VIR_DOMAIN_DISK_ERROR_NONE
            })
            testvm._dom = dom
            self.assertEqual(testvm._readPauseCode(), 'ENOSPC')

    def testReadPauseCodeDomainPausedEIO(self):
        with fake.VM() as testvm:
            dom = fake.Domain(domState=libvirt.VIR_DOMAIN_PAUSED,
                              domReason=libvirt.VIR_DOMAIN_PAUSED_IOERROR)
            dom.setDiskErrors({
                'vda': libvirt.VIR_DOMAIN_DISK_ERROR_NONE,
                'hdc': libvirt.VIR_DOMAIN_DISK_ERROR_UNSPEC
            })
            testvm._dom = dom
            self.assertEqual(testvm._readPauseCode(), 'EIO')

    @permutations([[1000, 24], [900, 0], [1200, -128]])
    def testSetCpuTuneQuote(self, quota, offset):
        with fake.VM() as testvm:
            # we need a different behaviour with respect to
            # plain fake.Domain. Seems simpler to just add
            # a new special-purpose trivial fake here.
            testvm._dom = ChangingSchedulerDomain(offset)
            testvm.setCpuTuneQuota(quota)
            self.assertEqual(quota + offset,
                             testvm._vcpuTuneInfo['vcpu_quota'])

    @permutations([[100000, 128], [150000, 0], [9999, -99]])
    def testSetCpuTunePeriod(self, period, offset):
        with fake.VM() as testvm:
            # same as per testSetCpuTuneQuota
            testvm._dom = ChangingSchedulerDomain(offset)
            testvm.setCpuTunePeriod(period)
            self.assertEqual(period + offset,
                             testvm._vcpuTuneInfo['vcpu_period'])

    @brokentest("sometimes on CI tries to connect to libvirt")
    @permutations([[
        libvirt.VIR_ERR_OPERATION_DENIED, 'setNumberOfCpusErr',
        'Failed to set the number of cpus'
    ], [libvirt.VIR_ERR_NO_DOMAIN, 'noVM', None]])
    def testSetNumberOfVcpusFailed(self, virt_error, vdsm_error,
                                   error_message):
        def _fail(*args):
            raise_libvirt_error(virt_error, error_message)

        with MonkeyPatchScope([(hooks, 'before_set_num_of_cpus', lambda: None)
                               ]):
            with fake.VM() as testvm:
                dom = fake.Domain()
                dom.setVcpusFlags = _fail
                testvm._dom = dom

                res = testvm.setNumberOfCpus(4)  # random value

                self.assertEqual(res, response.error(vdsm_error))

    def testUpdateDeviceGraphicsFailed(self):
        with fake.VM(devices=self.GRAPHIC_DEVICES) as testvm:
            message = 'fake timeout while setting ticket'
            device = 'spice'
            domXml = '''
                <devices>
                    <graphics type="%s" port="5900" />
                </devices>''' % device

            def _fail(*args):
                raise virdomain.TimeoutError(defmsg=message)

            domain = fake.Domain(domXml)
            domain.updateDeviceFlags = _fail
            testvm._dom = domain

            self.assertRaises(exception.SpiceTicketError,
                              self._updateGraphicsDevice, testvm, device,
                              _GRAPHICS_DEVICE_PARAMS)

    def testAcpiShutdownDisconnected(self):
        with fake.VM() as testvm:
            testvm._dom = virdomain.Disconnected(vmid='testvm')
            self.assertTrue(response.is_error(testvm.acpiShutdown()))

    def testAcpiShutdownConnected(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain(vmId='testvm')
            self.assertFalse(response.is_error(testvm.acpiShutdown()))

    def testAcpiRebootDisconnected(self):
        with fake.VM() as testvm:
            testvm._dom = virdomain.Disconnected(vmid='testvm')
            self.assertTrue(response.is_error(testvm.acpiReboot()))

    def testAcpiRebootConnected(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain(vmId='testvm')
            self.assertFalse(response.is_error(testvm.acpiReboot()))

    @permutations([
        # info, expected
        ({
            'readonly': True,
            'diskType': storage.DISK_TYPE.BLOCK
        }, []),
        ({
            'readonly': True,
            'diskType': storage.DISK_TYPE.FILE
        }, []),
        ({
            'readonly': False,
            'diskType': storage.DISK_TYPE.FILE
        }, []),
        ({
            'readonly': False,
            'diskType': storage.DISK_TYPE.FILE
        }, []),
        ({
            'readonly': False,
            'diskType': storage.DISK_TYPE.BLOCK,
            'format': 'raw'
        }, []),
        ({
            'readonly': False,
            'diskType': storage.DISK_TYPE.BLOCK
        }, ['vda']),
        ({
            'readonly': False,
            'diskType': storage.DISK_TYPE.FILE,
            'diskReplicate': {
                'format': 'cow',
                'diskType': storage.DISK_TYPE.BLOCK
            }
        }, ['vda']),
    ])
    def testGetChunkedDrives(self, disk_conf, expected):
        with fake.VM() as testvm:
            vda = storage.Drive(self.log, **drive_config(**disk_conf))
            testvm._devices[hwclass.DISK] = [vda]

            drives = [drive.name for drive in testvm.getChunkedDrives()]
            self.assertEqual(drives, expected)
예제 #10
0
class TestVmOperations(TestCaseBase):
    # just numbers, no particular meaning
    UPDATE_OFFSETS = [-3200, 3502, -2700, 3601]
    BASE_OFFSET = 42

    GRAPHIC_DEVICES = [{
        'type': 'graphics',
        'device': 'spice',
        'port': '-1'
    }, {
        'type': 'graphics',
        'device': 'vnc',
        'port': '-1'
    }]

    @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection())
    @permutations([[define.NORMAL], [define.ERROR]])
    def testTimeOffsetNotPresentByDefault(self, exitCode):
        with fake.VM() as testvm:
            testvm.setDownStatus(exitCode, vmexitreason.GENERIC_ERROR)
            self.assertFalse('timeOffset' in testvm.getStats())

    @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection())
    @permutations([[define.NORMAL], [define.ERROR]])
    def testTimeOffsetRoundtrip(self, exitCode):
        with fake.VM({'timeOffset': self.BASE_OFFSET}) as testvm:
            testvm.setDownStatus(exitCode, vmexitreason.GENERIC_ERROR)
            self.assertEqual(testvm.getStats()['timeOffset'], self.BASE_OFFSET)

    @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection())
    @permutations([[define.NORMAL], [define.ERROR]])
    def testTimeOffsetRoundtriupAcrossInstances(self, exitCode):
        # bz956741
        lastOffset = 0
        for offset in self.UPDATE_OFFSETS:
            with fake.VM({'timeOffset': lastOffset}) as testvm:
                testvm.onRTCUpdate(offset)
                testvm.setDownStatus(exitCode, vmexitreason.GENERIC_ERROR)
                vmOffset = testvm.getStats()['timeOffset']
                self.assertEqual(vmOffset, str(lastOffset + offset))
                # the field in getStats is str, not int
                lastOffset = int(vmOffset)

    @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection())
    @permutations([[define.NORMAL], [define.ERROR]])
    def testTimeOffsetUpdateIfAbsent(self, exitCode):
        # bz956741 (-like, simpler case)
        with fake.VM() as testvm:
            for offset in self.UPDATE_OFFSETS:
                testvm.onRTCUpdate(offset)
            # beware of type change!
            testvm.setDownStatus(exitCode, vmexitreason.GENERIC_ERROR)
            self.assertEqual(testvm.getStats()['timeOffset'],
                             str(self.UPDATE_OFFSETS[-1]))

    @MonkeyPatch(libvirtconnection, 'get', lambda x: fake.Connection())
    @permutations([[define.NORMAL], [define.ERROR]])
    def testTimeOffsetUpdateIfPresent(self, exitCode):
        with fake.VM({'timeOffset': self.BASE_OFFSET}) as testvm:
            for offset in self.UPDATE_OFFSETS:
                testvm.onRTCUpdate(offset)
            # beware of type change!
            testvm.setDownStatus(exitCode, vmexitreason.GENERIC_ERROR)
            self.assertEqual(testvm.getStats()['timeOffset'],
                             str(self.BASE_OFFSET + self.UPDATE_OFFSETS[-1]))

    def testUpdateSingleDeviceGraphics(self):
        devXmls = ('<graphics connected="disconnect" passwd="12345678"'
                   ' port="5900" type="spice"/>',
                   '<graphics passwd="12345678" port="5900" type="vnc"/>')
        for device, devXml in zip(self.GRAPHIC_DEVICES, devXmls):
            domXml = '''
                <devices>
                    <graphics type="%s" port="5900" />
                </devices>''' % device['device']
            self._verifyDeviceUpdate(device, device, domXml, devXml,
                                     _GRAPHICS_DEVICE_PARAMS)

    def testUpdateSingleDeviceGraphicsNoConnected(self):
        graphics_params = dict(_GRAPHICS_DEVICE_PARAMS)
        del graphics_params['existingConnAction']
        devXmls = ('<graphics passwd="12345678"'
                   ' port="5900" type="spice"/>',
                   '<graphics passwd="12345678" port="5900" type="vnc"/>')
        for device, devXml in zip(self.GRAPHIC_DEVICES, devXmls):
            domXml = '''
                <devices>
                    <graphics type="%s" port="5900" />
                </devices>''' % device['device']
            self._verifyDeviceUpdate(device, device, domXml, devXml,
                                     graphics_params)

    def testUpdateMultipleDeviceGraphics(self):
        devXmls = ('<graphics connected="disconnect" passwd="12345678"'
                   ' port="5900" type="spice"/>',
                   '<graphics passwd="12345678" port="5901" type="vnc"/>')
        domXml = '''
            <devices>
                <graphics type="spice" port="5900" />
                <graphics type="vnc" port="5901" />
            </devices>'''
        for device, devXml in zip(self.GRAPHIC_DEVICES, devXmls):
            self._verifyDeviceUpdate(device, self.GRAPHIC_DEVICES, domXml,
                                     devXml, _GRAPHICS_DEVICE_PARAMS)

    def _updateGraphicsDevice(self, testvm, device_type, graphics_params):
        def _check_ticket_params(domXML, conf, params):
            self.assertEqual(params, _TICKET_PARAMS)

        with MonkeyPatchScope([(hooks, 'before_vm_set_ticket',
                                _check_ticket_params)]):
            params = {'graphicsType': device_type}
            params.update(graphics_params)
            return testvm.updateDevice(params)

    def _verifyDeviceUpdate(self, device, allDevices, domXml, devXml,
                            graphics_params):
        with fake.VM(devices=allDevices) as testvm:
            testvm._dom = fake.Domain(domXml)

            self._updateGraphicsDevice(testvm, device['device'],
                                       graphics_params)

            self.assertEquals(testvm._dom.devXml, devXml)

    def testDomainNotRunningWithoutDomain(self):
        with fake.VM() as testvm:
            self.assertFalse(testvm._isDomainRunning())

    def testDomainNotRunningByState(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain(domState=libvirt.VIR_DOMAIN_SHUTDOWN)
            self.assertFalse(testvm._isDomainRunning())

    def testDomainIsRunning(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain(domState=libvirt.VIR_DOMAIN_RUNNING)
            self.assertTrue(testvm._isDomainRunning())

    def testDomainIsReadyForCommands(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain()
            self.assertTrue(testvm.isDomainReadyForCommands())

    def testDomainDisappearedNotReadyForCommands(self):
        def _fail(*args):
            raise_libvirt_error(libvirt.VIR_ERR_NO_DOMAIN,
                                "Disappeared domain")

        with fake.VM() as testvm:
            dom = fake.Domain()
            dom.controlInfo = _fail
            testvm._dom = dom
            self.assertFalse(testvm.isDomainReadyForCommands())

    def testDomainNoneNotReadyForCommands(self):
        with fake.VM() as testvm:
            self.assertFalse(testvm.isDomainReadyForCommands())

    def testReadyForCommandsRaisesLibvirtError(self):
        def _fail(*args):
            # anything != NO_DOMAIN is good
            raise_libvirt_error(libvirt.VIR_ERR_INTERNAL_ERROR,
                                "Fake internal error")

        with fake.VM() as testvm:
            dom = fake.Domain()
            dom.controlInfo = _fail
            testvm._dom = dom
            self.assertRaises(libvirt.libvirtError,
                              testvm.isDomainReadyForCommands)

    def testReadPauseCodeDomainRunning(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain(domState=libvirt.VIR_DOMAIN_RUNNING)
            self.assertEqual(testvm._readPauseCode(), 'NOERR')

    def testReadPauseCodeDomainPausedCrash(self):
        # REQUIRED_FOR: el6
        if not hasattr(libvirt, 'VIR_DOMAIN_PAUSED_CRASHED'):
            raise SkipTest('libvirt.VIR_DOMAIN_PAUSED_CRASHED undefined')

        with fake.VM() as testvm:
            # if paused for different reason we must not extend the disk
            # so anything else is ok
            dom = fake.Domain(domState=libvirt.VIR_DOMAIN_PAUSED,
                              domReason=libvirt.VIR_DOMAIN_PAUSED_CRASHED)
            testvm._dom = dom
            self.assertNotEqual(testvm._readPauseCode(), 'ENOSPC')

    def testReadPauseCodeDomainPausedENOSPC(self):
        with fake.VM() as testvm:
            dom = fake.Domain(domState=libvirt.VIR_DOMAIN_PAUSED,
                              domReason=libvirt.VIR_DOMAIN_PAUSED_IOERROR)
            dom.setDiskErrors({
                'vda': libvirt.VIR_DOMAIN_DISK_ERROR_NO_SPACE,
                'hdc': libvirt.VIR_DOMAIN_DISK_ERROR_NONE
            })
            testvm._dom = dom
            self.assertEqual(testvm._readPauseCode(), 'ENOSPC')

    def testReadPauseCodeDomainPausedEIO(self):
        with fake.VM() as testvm:
            dom = fake.Domain(domState=libvirt.VIR_DOMAIN_PAUSED,
                              domReason=libvirt.VIR_DOMAIN_PAUSED_IOERROR)
            dom.setDiskErrors({
                'vda': libvirt.VIR_DOMAIN_DISK_ERROR_NONE,
                'hdc': libvirt.VIR_DOMAIN_DISK_ERROR_UNSPEC
            })
            testvm._dom = dom
            self.assertEqual(testvm._readPauseCode(), 'EOTHER')

    @permutations([[1000, 24], [900, 0], [1200, -128]])
    def testSetCpuTuneQuote(self, quota, offset):
        with fake.VM() as testvm:
            # we need a different behaviour with respect to
            # plain fake.Domain. Seems simpler to just add
            # a new special-purpose trivial fake here.
            testvm._dom = ChangingSchedulerDomain(offset)
            testvm.setCpuTuneQuota(quota)
            self.assertEqual(quota + offset,
                             testvm._vcpuTuneInfo['vcpu_quota'])

    @permutations([[100000, 128], [150000, 0], [9999, -99]])
    def testSetCpuTunePeriod(self, period, offset):
        with fake.VM() as testvm:
            # same as per testSetCpuTuneQuota
            testvm._dom = ChangingSchedulerDomain(offset)
            testvm.setCpuTunePeriod(period)
            self.assertEqual(period + offset,
                             testvm._vcpuTuneInfo['vcpu_period'])

    @brokentest("sometimes on CI tries to connect to libvirt")
    @permutations([[
        libvirt.VIR_ERR_OPERATION_DENIED, 'setNumberOfCpusErr',
        'Failed to set the number of cpus'
    ], [libvirt.VIR_ERR_NO_DOMAIN, 'noVM', None]])
    def testSetNumberOfVcpusFailed(self, virt_error, vdsm_error,
                                   error_message):
        def _fail(*args):
            raise_libvirt_error(virt_error, error_message)

        with MonkeyPatchScope([(hooks, 'before_set_num_of_cpus', lambda: None)
                               ]):
            with fake.VM() as testvm:
                dom = fake.Domain()
                dom.setVcpusFlags = _fail
                testvm._dom = dom

                res = testvm.setNumberOfCpus(4)  # random value

                self.assertEqual(res, response.error(vdsm_error))

    def testUpdateDeviceGraphicsFailed(self):
        with fake.VM(devices=self.GRAPHIC_DEVICES) as testvm:
            message = 'fake timeout while setting ticket'
            device = 'spice'
            domXml = '''
                <devices>
                    <graphics type="%s" port="5900" />
                </devices>''' % device

            def _fail(*args):
                raise virdomain.TimeoutError(defmsg=message)

            domain = fake.Domain(domXml)
            domain.updateDeviceFlags = _fail
            testvm._dom = domain

            res = self._updateGraphicsDevice(testvm, device,
                                             _GRAPHICS_DEVICE_PARAMS)

            self.assertEqual(res, response.error('ticketErr', message))

    def testAcpiShutdownDisconnected(self):
        with fake.VM() as testvm:
            testvm._dom = virdomain.Disconnected(vmid='testvm')
            self.assertTrue(response.is_error(testvm.acpiShutdown()))

    def testAcpiShutdownConnected(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain(vmId='testvm')
            self.assertFalse(response.is_error(testvm.acpiShutdown()))

    def testAcpiRebootDisconnected(self):
        with fake.VM() as testvm:
            testvm._dom = virdomain.Disconnected(vmid='testvm')
            self.assertTrue(response.is_error(testvm.acpiReboot()))

    def testAcpiRebootConnected(self):
        with fake.VM() as testvm:
            testvm._dom = fake.Domain(vmId='testvm')
            self.assertFalse(response.is_error(testvm.acpiReboot()))
예제 #11
0
 def setUp(self):
     self.connection = vmfakelib.Connection()
     self.patch = Patch([(libvirtconnection, 'get', lambda: self.connection)
                         ])
     self.patch.apply()