def testLookupFailure(self, methodname, fakemethod, active): def _connect(uri, username, passwd): mock = MockVirConnect(vms=self._vms) mock.listAllDomains = legacylistAllDomains setattr(mock, methodname, fakemethod) return mock with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), None)['vmList'] self.assertEqual( sorted(vm['vmName'] for vm in vms), sorted(spec.name for spec in VM_SPECS if spec.active == active))
def testGetExternalVMsWithoutDisksInfo(self): def internal_error(name): raise fake.Error(libvirt.VIR_ERR_INTERNAL_ERROR) # we need a sequence of just one vm mock = MockVirConnect(vms=self._vms[:1]) mock.storageVolLookupByPath = internal_error def _connect(uri, username, passwd): return mock with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), None)['vmList'] self.assertEqual(len(vms), 0)
def testGetExternalVMs(self): def _connect(uri, username, passwd): return MockVirConnect(vms=self._vms_with_snapshot) with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), None)['vmList'] self.assertEqual(len(vms), len(VM_SPECS) - 1) self.assertNotIn(self._vms_with_snapshot[4].ID, [vm['vmId'] for vm in vms]) for vm, spec in zip(vms, VM_SPECS): self._assertVmMatchesSpec(vm, spec) self._assertVmDisksMatchSpec(vm, spec)
def testXenBlockDevice(self): def _connect(uri, username, passwd): conn = MockVirConnect(vms=self._vms) conn.setType('Xen') return conn with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms(self.xen_url, 'user', ProtectedPassword('password'), None)['vmList'] # Import of VMs with block devices is not supported for Xen source # so the VMs RHEL_4 and RHEL_5 should not be in the list. self.assertEqual(len(vms), len(VM_SPECS) - 2) vm_names = [vm['vmName'] for vm in vms] self.assertTrue('RHEL_4' not in vm_names) self.assertTrue('RHEL_5' not in vm_names)
def testGetExternalVMs(self): def _connect(uri, username, passwd): return MockVirConnect(vms=self._vms_with_snapshot) with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), None)['vmList'] # Make sure that VM nr. 4 is now in the returned list # (the one with snapshot, see setUp()) assert len(vms) == len(VM_SPECS) assert self._vms_with_snapshot[4].ID not in \ [vm['vmId'] for vm in vms] specs = list(VM_SPECS) for vm, spec in zip(vms, specs): self._assertVmMatchesSpec(vm, spec) self._assertVmDisksMatchSpec(vm, spec)
def testGetExternalVMsList(self): def _connect(uri, username, passwd): return MockVirConnect(vms=self._vms_with_snapshot) vmIDs = [1, 3, 4] names = [vm.name for vm in VM_SPECS if vm.id in vmIDs] # Add a non-existent name to check that nothing bad happens. names.append('Some nonexistent name') with MonkeyPatchScope([(libvirtconnection, 'open_connection', _connect) ]): vms = v2v.get_external_vms('esx://mydomain', 'user', ProtectedPassword('password'), names)['vmList'] self.assertEqual(len(vms), len(vmIDs) - 1) self.assertNotIn(self._vms_with_snapshot[4].ID, [vm['vmId'] for vm in vms]) for vm, vmID in zip(vms, vmIDs): spec = VM_SPECS[vmID] self._assertVmMatchesSpec(vm, spec) self._assertVmDisksMatchSpec(vm, spec)
def test_decode(self): obj = self.Cls() data = b"\x80\x81\x82\x83" obj.password = ProtectedPassword(base64.b64encode(data)) assert obj.password.value == data
def test_valid(self): obj = self.Cls() obj.password = ProtectedPassword("12345678") assert obj.password.value == "12345678"
def test_unencoded_password(self): params = make_secret() params["password"] = ProtectedPassword("not base64 value") self.assertRaises(ValueError, secret.Secret, params)
def make_password(value): return ProtectedPassword(base64.b64encode(value.encode('utf8')))
def test_protect_password_error(self): secret = ProtectedPassword("top-secret") args = ["false", secret] with pytest.raises(cmdutils.Error) as e: commands.run(args) assert secret.value not in str(e.value)
def test_unprotect_passwords(self): secret = ProtectedPassword("top-secret") args = ["echo", "-n", secret] out = commands.run(args) assert out.decode() == secret.value
def test_invalid(self): obj = self.Cls() self.assertRaises(ValueError, setattr, obj, "password", ProtectedPassword("not base64 value"))
def test_invalid(self): obj = self.Cls() with pytest.raises(ValueError): obj.password = ProtectedPassword("not base64 value")
def test_ne(self): p1 = ProtectedPassword("12345678") p2 = ProtectedPassword("12345678") self.assertFalse(p1 != p2)
def test_pickle_copy(self): p1 = ProtectedPassword("12345678") p2 = pickle.loads(pickle.dumps(p1)) self.assertEqual(p1, p2)
def test_eq(self): p1 = ProtectedPassword("12345678") p2 = ProtectedPassword("12345678") self.assertEqual(p1, p2)
def test_value(self): p = ProtectedPassword("12345678") self.assertEqual("12345678", p.value)
def test_repr(self): p = ProtectedPassword("12345678") self.assertNotIn("12345678", repr(p))
def dict_protected(): return {"key": "value", "password": ProtectedPassword("12345678")}
def test_unencoded_password(self): params = make_secret() params["password"] = ProtectedPassword("not base64 value") with pytest.raises(ValueError): secret.Secret(params)
def protected(password): if password is None: return None return ProtectedPassword(password)
def get(target=None, killOnFailure=True): """Return current connection to libvirt or open a new one. Use target to get/create the connection object linked to that object. target must have a callable attribute named 'dispatchLibvirtEvents' which will be registered as a callback on libvirt events. Wrap methods of connection object so that they catch disconnection, and take the current process down. """ def wrapMethod(f): @functools.wraps(f) def wrapper(*args, **kwargs): try: ret = f(*args, **kwargs) if isinstance(ret, libvirt.virDomain): for name in dir(ret): method = getattr(ret, name) if callable(method) and name[0] != '_': setattr(ret, name, wrapMethod(function.weakmethod(method))) return ret except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() EDOMAINS = (libvirt.VIR_FROM_REMOTE, libvirt.VIR_FROM_RPC) ECODES = (libvirt.VIR_ERR_SYSTEM_ERROR, libvirt.VIR_ERR_INTERNAL_ERROR, libvirt.VIR_ERR_NO_CONNECT, libvirt.VIR_ERR_INVALID_CONN) if edom in EDOMAINS and ecode in ECODES: try: __connections.get(id(target)).pingLibvirt() except libvirt.libvirtError as e: edom = e.get_error_domain() ecode = e.get_error_code() if edom in EDOMAINS and ecode in ECODES: log.warning( 'connection to libvirt broken.' ' ecode: %d edom: %d', ecode, edom) if killOnFailure: log.critical('taking calling process down.') os.kill(os.getpid(), signal.SIGTERM) else: raise raise return wrapper with __connectionLock: conn = __connections.get(id(target)) if not conn: log.debug('trying to connect libvirt') password = ProtectedPassword(libvirt_password()) conn = open_connection('qemu:///system', SASL_USERNAME, password) __connections[id(target)] = conn setattr(conn, 'pingLibvirt', getattr(conn, 'getLibVersion')) for name in dir(libvirt.virConnect): method = getattr(conn, name) if callable(method) and name[0] != '_': setattr(conn, name, wrapMethod(function.weakmethod(method))) if target is not None: for ev in (libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, libvirt.VIR_DOMAIN_EVENT_ID_REBOOT, libvirt.VIR_DOMAIN_EVENT_ID_RTC_CHANGE, libvirt.VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON, libvirt.VIR_DOMAIN_EVENT_ID_GRAPHICS, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_JOB, libvirt.VIR_DOMAIN_EVENT_ID_WATCHDOG, libvirt.VIR_DOMAIN_EVENT_ID_JOB_COMPLETED, libvirt.VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD): conn.domainEventRegisterAny(None, ev, target.dispatchLibvirtEvents, ev) # In case we're running into troubles with keeping the connections # alive we should place here: # conn.setKeepAlive(interval=5, count=3) # However the values need to be considered wisely to not affect # hosts which are hosting a lot of virtual machines return conn
def test_no_marshal(self): p1 = ProtectedPassword("12345678") self.assertRaises(ValueError, marshal.dumps, p1)
def test_valid(self): obj = self.Cls() obj.password = ProtectedPassword("12345678") self.assertEqual("12345678", obj.password.value)
def test_protected_password(self): secret = ProtectedPassword("secret!") line = "'" + str(secret) + "'" self.assertEqual(cmdutils._list2cmdline([secret]), line)
def test_no_json(self): p1 = ProtectedPassword("12345678") self.assertRaises(TypeError, json.dumps, p1)