def testValidDisk(self): """Test access on a valid disk image.""" self.mox.StubOutWithMock(os, 'access') os.access('/home/ebroder/disk.img', os.R_OK | os.W_OK).AndReturn(True) self.mox.ReplayAll() domains._validatePath('/home/ebroder/disk.img', os.R_OK | os.W_OK)
def test(self): """Test privops.domains.createNetwork. With all of the functionality pulled into helper functions, createNetwork doesn't actually do all that much work. """ name = 'debmarshal-12' memory = '128M' disks = ['/home/ebroder/root.img'] net = 'debmarshal-0' mac = '00:11:22:33:44:55' self.mox.StubOutWithMock(utils, 'getCaller') utils.getCaller().MultipleTimes().AndReturn(500) self.mox.StubOutWithMock(debmarshal.utils, 'acquireLock') debmarshal.utils.acquireLock('debmarshal-domlist', fcntl.LOCK_EX) self.mox.StubOutWithMock(hypervisors.qemu.QEMU, 'open') qemu_con = self.mox.CreateMock(libvirt.virConnect) hypervisors.qemu.QEMU.open().AndReturn(qemu_con) self.mox.StubOutWithMock(domains, '_validateNetwork') domains._validateNetwork(net, qemu_con) self.mox.StubOutWithMock(domains, '_validatePath') for d in disks: domains._validatePath(d, os.R_OK | os.W_OK) self.mox.StubOutWithMock(domains, '_findUnusedName') domains._findUnusedName(qemu_con).AndReturn(name) self.mox.StubOutWithMock(hypervisors.qemu.QEMU, 'domainXMLString') hypervisors.qemu.QEMU.domainXMLString( mox.IgnoreArg()).AndReturn('<fake_xml/>') self.mox.StubOutWithMock(domains, 'loadDomainState') domains.loadDomainState().AndReturn({('debmarshal-1', 'qemu'): 500}) self.mox.StubOutWithMock(utils, 'storeState') utils.storeState({ ('debmarshal-1', 'qemu'): 500, (name, 'qemu'): 500 }, 'debmarshal-domains') qemu_con.createLinux('<fake_xml/>', 0) self.mox.ReplayAll() self.assertEqual( privops.Privops().createDomain(memory, disks, net, mac, 'qemu', 'x86_64', {}), name)
def test(self): """Test privops.domains.createNetwork. With all of the functionality pulled into helper functions, createNetwork doesn't actually do all that much work. """ name = 'debmarshal-12' memory = '128M' disks = ['/home/ebroder/root.img'] net = 'debmarshal-0' mac = '00:11:22:33:44:55' self.mox.StubOutWithMock(utils, 'getCaller') utils.getCaller().MultipleTimes().AndReturn(500) self.mox.StubOutWithMock(debmarshal.utils, 'acquireLock') debmarshal.utils.acquireLock('debmarshal-domlist', fcntl.LOCK_EX) self.mox.StubOutWithMock(hypervisors.qemu.QEMU, 'open') qemu_con = self.mox.CreateMock(libvirt.virConnect) hypervisors.qemu.QEMU.open().AndReturn(qemu_con) self.mox.StubOutWithMock(domains, '_validateNetwork') domains._validateNetwork(net, qemu_con) self.mox.StubOutWithMock(domains, '_validatePath') for d in disks: domains._validatePath(d, os.R_OK | os.W_OK) self.mox.StubOutWithMock(domains, '_findUnusedName') domains._findUnusedName(qemu_con).AndReturn(name) self.mox.StubOutWithMock(hypervisors.qemu.QEMU, 'domainXMLString') hypervisors.qemu.QEMU.domainXMLString(mox.IgnoreArg()).AndReturn( '<fake_xml/>') self.mox.StubOutWithMock(domains, 'loadDomainState') domains.loadDomainState().AndReturn({ ('debmarshal-1', 'qemu'): 500}) self.mox.StubOutWithMock(utils, 'storeState') utils.storeState({ ('debmarshal-1', 'qemu'): 500, (name, 'qemu'): 500}, 'debmarshal-domains') qemu_con.createLinux('<fake_xml/>', 0) self.mox.ReplayAll() self.assertEqual(privops.Privops().createDomain( memory, disks, net, mac, 'qemu', 'x86_64', {}), name)
def createDomain(self, memory, disks, network, mac, hypervisor, arch, extra, _debmarshal_sender=None): """Create a virtual machine domain. createDomain creates a domain for a virtual machine used as part of a debmarshal test and boots it up. We do no validation or accounting of memory allocations from the privileged side. Since debmarshal is intended to be run on single-user machines, the worst case scenario is a DoS of yourself. When supported by the hypervisor, createDomain can also pass in a hypervisor, initrd, and command line, bypassing the BIOS. Args: memory: str containing the amount of memory to be allocated to the new domain. This should include a suffix such as 'G' or 'M' to indicate the units of the amount. disks: list of strs of paths to disk images, in the order that they should be attached to the guest. All disk images must be owned by the user calling createDomain. network: The name of the network to attach this VM to. The netwok must have been created using debmarshal.privops.createNetwork by the user calling createDomain. mac: The MAC address of the new VM. hypervisor: What hypervisor to use to start this VM. While it's possible to mix hypervisors amongst the domains for a single test suite, it is the caller's responsibility to keep track of that when destroyDomain is called later. Currently only qemu is supported. arch: The CPU architecture for the VM, or an empty string if the architecture should be the same as that of the host. extra: A dict of optional extra configuration arguments, e.g.: kernel: The kernel to boot with, if requested. The kernel should be readable by the user calling createDomain. initrd: The initrd to boot with, if requested. The initrd should also be readable by the user calling createDomain cmdline: Additional command-line arguments to pass to the kernel. Returns: The name of the new domain. """ utils.caller = _debmarshal_sender hyper_class = hypervisors.base.hypervisors[hypervisor] virt_con = hyper_class.open() domains._validateNetwork(network, virt_con) for d in disks: domains._validatePath(d, os.R_OK | os.W_OK) allowed_extras = set(['kernel', 'initrd', 'cmdline', 'on_poweroff', 'on_reboot']) if set(extra) - allowed_extras != set(): raise errors.InvalidInput("Invalid extra parameter specified.") if 'kernel' in extra: if 'initrd' not in extra: raise errors.InvalidInput( "Must specify both a kernel and initrd, or neither.") domains._validatePath(extra['kernel'], os.R_OK) domains._validatePath(extra['initrd'], os.R_OK) for opt in ['on_poweroff', 'on_reboot']: if opt in extra and extra[opt] not in ('destroy', 'restart'): raise errors.InvalidInput( "%s must be one of 'destroy' or 'restart'" % opt) name = domains._findUnusedName(virt_con) memory = debmarshal.utils.parseKBytes(memory) vm_params = vm.VM(name=name, memory=memory, disks=disks, network=network, mac=mac, arch=arch, extra=extra) dom_xml = hyper_class.domainXMLString(vm_params) # The new domain is intentionally recorded to the statefile before # starting the VM, because it's much worse to have a running VM we # don't know about than to have state on a VM that doesn't # actually exist (loadDomainState already handles the latter # case). doms = domains.loadDomainState() doms[(name, hypervisor)] = utils.getCaller() utils.storeState(doms, 'debmarshal-domains') virt_con.createLinux(dom_xml, 0) utils.caller = None return name
def createDomain(self, memory, disks, network, mac, hypervisor, arch, extra, _debmarshal_sender=None): """Create a virtual machine domain. createDomain creates a domain for a virtual machine used as part of a debmarshal test and boots it up. We do no validation or accounting of memory allocations from the privileged side. Since debmarshal is intended to be run on single-user machines, the worst case scenario is a DoS of yourself. When supported by the hypervisor, createDomain can also pass in a hypervisor, initrd, and command line, bypassing the BIOS. Args: memory: str containing the amount of memory to be allocated to the new domain. This should include a suffix such as 'G' or 'M' to indicate the units of the amount. disks: list of strs of paths to disk images, in the order that they should be attached to the guest. All disk images must be owned by the user calling createDomain. network: The name of the network to attach this VM to. The netwok must have been created using debmarshal.privops.createNetwork by the user calling createDomain. mac: The MAC address of the new VM. hypervisor: What hypervisor to use to start this VM. While it's possible to mix hypervisors amongst the domains for a single test suite, it is the caller's responsibility to keep track of that when destroyDomain is called later. Currently only qemu is supported. arch: The CPU architecture for the VM, or an empty string if the architecture should be the same as that of the host. extra: A dict of optional extra configuration arguments, e.g.: kernel: The kernel to boot with, if requested. The kernel should be readable by the user calling createDomain. initrd: The initrd to boot with, if requested. The initrd should also be readable by the user calling createDomain cmdline: Additional command-line arguments to pass to the kernel. Returns: The name of the new domain. """ utils.caller = _debmarshal_sender hyper_class = hypervisors.base.hypervisors[hypervisor] virt_con = hyper_class.open() domains._validateNetwork(network, virt_con) for d in disks: domains._validatePath(d, os.R_OK | os.W_OK) allowed_extras = set( ['kernel', 'initrd', 'cmdline', 'on_poweroff', 'on_reboot']) if set(extra) - allowed_extras != set(): raise errors.InvalidInput("Invalid extra parameter specified.") if 'kernel' in extra: if 'initrd' not in extra: raise errors.InvalidInput( "Must specify both a kernel and initrd, or neither.") domains._validatePath(extra['kernel'], os.R_OK) domains._validatePath(extra['initrd'], os.R_OK) for opt in ['on_poweroff', 'on_reboot']: if opt in extra and extra[opt] not in ('destroy', 'restart'): raise errors.InvalidInput( "%s must be one of 'destroy' or 'restart'" % opt) name = domains._findUnusedName(virt_con) memory = debmarshal.utils.parseKBytes(memory) vm_params = vm.VM(name=name, memory=memory, disks=disks, network=network, mac=mac, arch=arch, extra=extra) dom_xml = hyper_class.domainXMLString(vm_params) # The new domain is intentionally recorded to the statefile before # starting the VM, because it's much worse to have a running VM we # don't know about than to have state on a VM that doesn't # actually exist (loadDomainState already handles the latter # case). doms = domains.loadDomainState() doms[(name, hypervisor)] = utils.getCaller() utils.storeState(doms, 'debmarshal-domains') virt_con.createLinux(dom_xml, 0) utils.caller = None return name