diff --git a/qubes/tests/int/basic.py b/qubes/tests/int/basic.py index 53a40734..1d3af6df 100644 --- a/qubes/tests/int/basic.py +++ b/qubes/tests/int/basic.py @@ -133,64 +133,14 @@ class TC_01_Properties(qubes.tests.SystemTestsMixin, qubes.tests.QubesTestCase): '/etc/systemd/system/multi-user.target.wants/' 'qubes-vm@{}.service'.format(self.vmname))) - def test_010_netvm(self): - if self.qc.get_default_netvm() is None: - self.skip("Set default NetVM before running this test") - self.netvm = self.qc.add_new_vm("QubesNetVm", - name=self.make_vm_name('netvm'), - template=self.qc.get_default_template()) - self.netvm.create_on_disk(verbose=False) - # TODO: remove this line after switching to core3 - self.save_and_reload_db() + def test_001_rename_libvirt_undefined(self): + self.vm.libvirt_domain.undefine() + self.vm._libvirt_domain = None - self.assertEquals(self.vm.netvm, self.qc.get_default_netvm()) - self.vm.uses_default_netvm = False - self.vm.netvm = None - self.assertIsNone(self.vm.netvm) - self.save_and_reload_db() - self.assertIsNone(self.vm.netvm) - - self.vm.netvm = self.qc[self.netvm.qid] - self.assertEquals(self.vm.netvm.qid, self.netvm.qid) - self.save_and_reload_db() - self.assertEquals(self.vm.netvm.qid, self.netvm.qid) - - self.vm.uses_default_netvm = True - # TODO: uncomment when properly implemented - # self.assertEquals(self.vm.netvm.qid, self.qc.get_default_netvm().qid) - self.save_and_reload_db() - self.assertEquals(self.vm.netvm.qid, self.qc.get_default_netvm().qid) - - with self.assertRaises(ValueError): - self.vm.netvm = self.vm - - def test_020_dispvm_netvm(self): - if self.qc.get_default_netvm() is None: - self.skip("Set default NetVM before running this test") - self.netvm = self.qc.add_new_vm("QubesNetVm", - name=self.make_vm_name('netvm'), - template=self.qc.get_default_template()) - self.netvm.create_on_disk(verbose=False) - - self.assertEquals(self.vm.netvm, self.vm.dispvm_netvm) - self.vm.uses_default_dispvm_netvm = False - self.vm.dispvm_netvm = None - self.assertIsNone(self.vm.dispvm_netvm) - self.save_and_reload_db() - self.assertIsNone(self.vm.dispvm_netvm) - - self.vm.dispvm_netvm = self.netvm - self.assertEquals(self.vm.dispvm_netvm, self.netvm) - self.save_and_reload_db() - self.assertEquals(self.vm.dispvm_netvm, self.netvm) - - self.vm.uses_default_dispvm_netvm = True - self.assertEquals(self.vm.dispvm_netvm, self.vm.netvm) - self.save_and_reload_db() - self.assertEquals(self.vm.dispvm_netvm, self.vm.netvm) - - with self.assertRaises(ValueError): - self.vm.dispvm_netvm = self.vm + newname = self.make_vm_name('newname') + with self.assertNotRaises( + (OSError, libvirt.libvirtError, qubes.exc.QubesException)): + self.vm.name = newname def test_030_clone(self): testvm1 = self.app.add_new_vm( @@ -281,6 +231,30 @@ class TC_01_Properties(qubes.tests.SystemTestsMixin, qubes.tests.QubesTestCase): self.assertEquals(testvm1.get_firewall_conf(), testvm3.get_firewall_conf()) + def test_020_name_conflict_app(self): + # TODO decide what exception should be here + with self.assertRaises((qubes.exc.QubesException, ValueError)): + self.vm2 = self.app.add_new_vm(qubes.vm.appvm.AppVM, + name=self.vmname, template=self.app.default_template) + self.vm2.create_on_disk() + + def test_021_name_conflict_template(self): + # TODO decide what exception should be here + with self.assertRaises((qubes.exc.QubesException, ValueError)): + self.vm2 = self.app.add_new_vm(qubes.vm.templatevm.TemplateVM, + name=self.vmname) + self.vm2.create_on_disk() + + def test_030_rename_conflict_app(self): + vm2name = self.make_vm_name('newname') + + self.vm2 = self.app.add_new_vm(qubes.vm.appvm.AppVM, + name=vm2name, template=self.app.default_template, label='red') + self.vm2.create_on_disk() + + with self.assertRaises(qubes.exc.QubesException): + self.vm2.name = self.vmname + class TC_02_QvmPrefs(qubes.tests.SystemTestsMixin, qubes.tests.QubesTestCase): def setUp(self): @@ -352,49 +326,6 @@ class TC_02_QvmPrefs(qubes.tests.SystemTestsMixin, qubes.tests.QubesTestCase): if valid: self.assertEquals(self.pref_get(name), expected) - def test_000_kernel(self): - self.setup_appvm() - - default_kernel = self.qc.get_default_kernel() - self.execute_tests('kernel', [ - ('default', default_kernel, True), - (default_kernel, default_kernel, True), - ('invalid', '', False), - ]) - - def test_001_include_in_backups(self): - self.setup_appvm() - self.execute_tests('include_in_backups', self.bool_test_values) - - def test_002_qrexec_timeout(self): - self.setup_appvm() - self.execute_tests('qrexec_timeout', [ - ('60', '60', True), - ('0', '0', True), - ('-10', '', False), - ('invalid', '', False) - ]) - - def test_003_internal(self): - self.setup_appvm() - self.execute_tests('include_in_backups', self.bool_test_values) - - def test_004_label(self): - self.setup_appvm() - self.execute_tests('label', [ - ('red', 'red', True), - ('blue', 'blue', True), - ('amber', '', False), - ]) - - def test_005_kernelopts(self): - self.setup_appvm() - self.execute_tests('kernelopts', [ - ('option', 'option', True), - ('default', 'nopat', True), - ('', '', True), - ]) - @unittest.skip('test not converted to core3 API') def test_006_template(self): templates = [tpl for tpl in self.app.domains.values() if @@ -408,83 +339,6 @@ class TC_02_QvmPrefs(qubes.tests.SystemTestsMixin, qubes.tests.QubesTestCase): ('invalid', '', False), ]) - def test_007_memory(self): - self.setup_appvm() - qh = qubes.qubes.QubesHost() - memory_total = qh.memory_total - - self.execute_tests('memory', [ - ('300', '300', True), - ('1500', '1500', True), - # TODO: - #('500M', '500', True), - #(str(self.testvm.maxmem+500), '', False), - (str(2*memory_total), '', False), - ]) - - def test_008_maxmem(self): - self.setup_appvm() - qh = qubes.qubes.QubesHost() - memory_total = qh.memory_total - - self.execute_tests('memory', [ - ('300', '300', True), - ('1500', '1500', True), - # TODO: - #('500M', '500', True), - #(str(self.testvm.memory-50), '', False), - (str(2*memory_total), '', False), - ]) - - def test_009_autostart(self): - self.setup_appvm() - self.execute_tests('autostart', self.bool_test_values) - - def test_010_pci_strictreset(self): - self.setup_appvm() - self.execute_tests('pci_strictreset', self.bool_test_values) - - def test_011_dispvm_netvm(self): - self.setup_appvm() - - default_netvm = self.qc.get_default_netvm().name - netvms = [tpl for tpl in self.qc.values() if tpl.is_netvm()] - if not netvms: - self.skip("No netvms installed") - some_netvm = netvms[0].name - if some_netvm == default_netvm: - if len(netvms) <= 1: - self.skip("At least two NetVM/ProxyVM required") - some_netvm = netvms[1].name - - self.execute_tests('dispvm_netvm', [ - (some_netvm, some_netvm, True), - (default_netvm, default_netvm, True), - ('default', default_netvm, True), - ('none', '', True), - (self.testvm.name, '', False), - ('invalid', '', False) - ]) - - def test_012_mac(self): - self.setup_appvm() - default_mac = self.testvm.mac - - self.execute_tests('mac', [ - ('00:11:22:33:44:55', '00:11:22:33:44:55', True), - ('auto', default_mac, True), - # TODO: - #('00:11:22:33:44:55:66', '', False), - ('invalid', '', False), - ]) - - def test_013_default_user(self): - self.setup_appvm() - self.execute_tests('default_user', [ - ('someuser', self.testvm.template.default_user, True) - # TODO: tests for standalone VMs - ]) - @unittest.skip('test not converted to core3 API') def test_014_pcidevs(self): self.setup_appvm() @@ -497,101 +351,6 @@ class TC_02_QvmPrefs(qubes.tests.SystemTestsMixin, qubes.tests.QubesTestCase): #('["12:12.0"]', '', False) ]) - def test_015_name(self): - self.setup_appvm() - self.execute_tests('name', [ - ('invalid!@#name', '', False), - # TODO: duplicate name test - would fail for now... - ]) - newname = self.make_vm_name('newname') - self.pref_set('name', newname, True) - self.qc.lock_db_for_reading() - self.qc.load() - self.qc.unlock_db() - self.testvm = self.qc.get_vm_by_name(newname) - self.assertEquals(self.pref_get('name'), newname) - - def test_016_vcpus(self): - self.setup_appvm() - self.execute_tests('vcpus', [ - ('1', '1', True), - ('100', '', False), - ('-1', '', False), - ('invalid', '', False), - ]) - - def test_017_debug(self): - self.setup_appvm() - self.execute_tests('debug', [ - ('on', 'True', True), - ('off', 'False', True), - ('true', 'True', True), - ('0', 'False', True), - ('invalid', '', False) - ]) - - def test_018_netvm(self): - self.setup_appvm() - - default_netvm = self.qc.get_default_netvm().name - netvms = [tpl for tpl in self.qc.values() if tpl.is_netvm()] - if not netvms: - self.skip("No netvms installed") - some_netvm = netvms[0].name - if some_netvm == default_netvm: - if len(netvms) <= 1: - self.skip("At least two NetVM/ProxyVM required") - some_netvm = netvms[1].name - - self.execute_tests('netvm', [ - (some_netvm, some_netvm, True), - (default_netvm, default_netvm, True), - ('default', default_netvm, True), - ('none', '', True), - (self.testvm.name, '', False), - ('invalid', '', False) - ]) - - def test_019_guiagent_installed(self): - self.setup_hvm() - self.execute_tests('guiagent_installed', self.bool_test_values) - - def test_020_qrexec_installed(self): - self.setup_hvm() - self.execute_tests('qrexec_installed', self.bool_test_values) - - def test_021_seamless_gui_mode(self): - self.setup_hvm() - # should reject seamless mode without gui agent - self.execute_tests('seamless_gui_mode', [ - ('True', '', False), - ('False', 'False', True), - ]) - self.execute_tests('guiagent_installed', [('True', 'True', True)]) - self.execute_tests('seamless_gui_mode', self.bool_test_values) - - def test_022_drive(self): - self.setup_hvm() - self.execute_tests('drive', [ - ('hd:dom0:/tmp/drive.img', 'hd:dom0:/tmp/drive.img', True), - ('hd:/tmp/drive.img', 'hd:dom0:/tmp/drive.img', True), - ('cdrom:dom0:/tmp/drive.img', 'cdrom:dom0:/tmp/drive.img', True), - ('cdrom:/tmp/drive.img', 'cdrom:dom0:/tmp/drive.img', True), - ('/tmp/drive.img', 'cdrom:dom0:/tmp/drive.img', True), - ('hd:drive.img', '', False), - ('drive.img', '', False), - ]) - - def test_023_timezone(self): - self.setup_hvm() - self.execute_tests('timezone', [ - ('localtime', 'localtime', True), - ('0', '0', True), - ('3600', '3600', True), - ('-7200', '-7200', True), - ('invalid', '', False), - ]) - @unittest.skip('test not converted to core3 API') def test_024_pv_reject_hvm_props(self): self.setup_appvm() @@ -660,6 +419,7 @@ class TC_03_QvmRevertTemplateChanges(qubes.tests.SystemTestsMixin, self.setup_pv_template() self._do_test() + @unittest.skip('HVM not yet implemented') def test_000_revert_hvm(self): """ Test qvm-revert-template-changes for HVM template diff --git a/qubes/tests/vm/__init__.py b/qubes/tests/vm/__init__.py index 442f6c2e..e4ec7e7c 100644 --- a/qubes/tests/vm/__init__.py +++ b/qubes/tests/vm/__init__.py @@ -33,9 +33,14 @@ class TestVMM(object): class TestHost(object): # pylint: disable=too-few-public-methods def __init__(self): - self.memory_total = 1000 + self.memory_total = 1000 * 1024 * 1024 + self.no_cpus = 4 class TestApp(qubes.tests.TestEmitter): + labels = {1: qubes.Label(1, '0xcc0000', 'red')} + get_label = qubes.Qubes.get_label + check_updates_vm = False + def __init__(self): super(TestApp, self).__init__() self.vmm = TestVMM() diff --git a/qubes/tests/vm/qubesvm.py b/qubes/tests/vm/qubesvm.py index 6b0af56e..4ab96c8f 100644 --- a/qubes/tests/vm/qubesvm.py +++ b/qubes/tests/vm/qubesvm.py @@ -22,9 +22,11 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +import os import unittest import uuid +import datetime import qubes import qubes.exc @@ -36,6 +38,9 @@ import qubes.tests class TestApp(object): labels = {1: qubes.Label(1, '0xcc0000', 'red')} + def __init__(self): + self.domains = {} + class TestProp(object): # pylint: disable=too-few-public-methods __name__ = 'testprop' @@ -44,9 +49,11 @@ class TestVM(object): # pylint: disable=too-few-public-methods app = TestApp() - def __init__(self): + def __init__(self, **kwargs): self.running = False self.installed_by_rpm = False + for k, v in kwargs.items(): + setattr(self, k, v) def is_running(self): return self.running @@ -108,6 +115,12 @@ class TC_00_setters(qubes.tests.QubesTestCase): with self.assertRaises(qubes.exc.QubesException): qubes.vm.qubesvm._setter_name(self.vm, self.prop, 'testname') + def test_017_setter_name_duplicate(self): + # pylint: disable=invalid-name + self.vm.app.domains['duplicate'] = TestVM(name='duplicate') + with self.assertRaises(qubes.exc.QubesException): + qubes.vm.qubesvm._setter_name(self.vm, self.prop, 'duplicate') + @unittest.skip('test not implemented') def test_020_setter_kernel(self): @@ -137,6 +150,82 @@ class TC_90_QubesVM(qubes.tests.QubesTestCase): qid=1, name=qubes.tests.VMPREFIX + 'test', **kwargs) + property_no_default = object() + + def assertPropertyValue(self, vm, prop_name, set_value, expected_value, + expected_xml_content=None): + # FIXME: any better exception list? or maybe all of that should be a + # single exception? + with self.assertNotRaises((ValueError, TypeError, KeyError)): + setattr(vm, prop_name, set_value) + self.assertEquals(getattr(vm, prop_name), expected_value) + if expected_xml_content is not None: + xml = vm.__xml__() + prop_xml = xml.xpath( + './properties/property[@name=\'{}\']'.format(prop_name)) + self.assertEquals(len(prop_xml), 1, "Property not found in XML") + self.assertEquals(prop_xml[0].text, expected_xml_content) + + def assertPropertyInvalidValue(self, vm, prop_name, set_value): + orig_value_set = True + orig_value = None + try: + orig_value = getattr(vm, prop_name) + except AttributeError: + orig_value_set = False + # FIXME: any better exception list? or maybe all of that should be a + # single exception? + with self.assertRaises((ValueError, TypeError, KeyError)): + setattr(vm, prop_name, set_value) + if orig_value_set: + self.assertEquals(getattr(vm, prop_name), orig_value) + else: + with self.assertRaises(AttributeError): + getattr(vm, prop_name) + + def assertPropertyDefaultValue(self, vm, prop_name, + expected_default=property_no_default): + if expected_default is self.property_no_default: + with self.assertRaises(AttributeError): + getattr(vm, prop_name) + else: + with self.assertNotRaises(AttributeError): + self.assertEquals(getattr(vm, prop_name), expected_default) + xml = vm.__xml__() + prop_xml = xml.xpath( + './properties/property[@name=\'{}\']'.format(prop_name)) + self.assertEquals(len(prop_xml), 0, "Property still found in XML") + + def _test_generic_bool_property(self, vm, prop_name, default=False): + self.assertPropertyDefaultValue(vm, prop_name, default) + self.assertPropertyValue(vm, prop_name, False, False, 'False') + self.assertPropertyValue(vm, prop_name, True, True, 'True') + delattr(vm, prop_name) + self.assertPropertyDefaultValue(vm, prop_name, default) + self.assertPropertyValue(vm, prop_name, 'True', True, 'True') + self.assertPropertyValue(vm, prop_name, 'False', False, 'False') + self.assertPropertyInvalidValue(vm, prop_name, 'xxx') + self.assertPropertyValue(vm, prop_name, 123, True) + self.assertPropertyInvalidValue(vm, prop_name, '') + + def setup_netvms(self, vm): + # usage of QubesVM here means that those tests should be after + # testing properties used here + self.netvm1 = qubes.vm.qubesvm.QubesVM(self.app, None, qid=2, + name=qubes.tests.VMPREFIX + 'netvm1', + provides_network=True) + self.netvm2 = qubes.vm.qubesvm.QubesVM(self.app, None, qid=3, + name=qubes.tests.VMPREFIX + 'netvm2', + provides_network=True) + self.nonetvm = qubes.vm.qubesvm.QubesVM(self.app, None, qid=4, + name=qubes.tests.VMPREFIX + 'nonet') + self.app.domains = {} + for domain in (vm, self.netvm1, self.netvm2, self.nonetvm): + self.app.domains[domain.qid] = domain + self.app.domains[domain] = domain + self.app.domains[domain.name] = domain + self.app.default_netvm = self.netvm1 + def test_000_init(self): self.get_vm() @@ -180,33 +269,342 @@ class TC_90_QubesVM(qubes.tests.QubesTestCase): with self.assertRaises(AttributeError): vm.uuid = uuid.uuid4() -# label = qubes.property('label', -# netvm = qubes.VMProperty('netvm', load_stage=4, allow_none=True, -# conf_file = qubes.property('conf_file', type=str, -# firewall_conf = qubes.property('firewall_conf', type=str, -# installed_by_rpm = qubes.property('installed_by_rpm', -# memory = qubes.property('memory', type=int, -# maxmem = qubes.property('maxmem', type=int, default=None, -# internal = qubes.property('internal', default=False, -# vcpus = qubes.property('vcpus', -# kernel = qubes.property('kernel', type=str, -# kernelopts = qubes.property('kernelopts', type=str, load_stage=4, -# mac = qubes.property('mac', type=str, -# debug = qubes.property('debug', type=bool, default=False, -# default_user = qubes.property('default_user', type=str, -# qrexec_timeout = qubes.property('qrexec_timeout', type=int, default=60, -# autostart = qubes.property('autostart', default=False, -# include_in_backups = qubes.property('include_in_backups', default=True, -# backup_content = qubes.property('backup_content', default=False, -# backup_size = qubes.property('backup_size', type=int, default=0, -# backup_path = qubes.property('backup_path', type=str, default='', -# backup_timestamp = qubes.property('backup_timestamp', default=None, + @unittest.skip('TODO: how to not fail on making an icon symlink here?') + def test_130_label(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'label') + self.assertPropertyValue(vm, 'label', self.app.labels[1], + self.app.labels[1], 'label-1') + del vm.label + self.assertPropertyDefaultValue(vm, 'label') + self.assertPropertyValue(vm, 'label', 'red', + self.app.labels[1], 'label-1') + self.assertPropertyValue(vm, 'label', 'label-1', + self.app.labels[1], 'label-1') + self.assertPropertyInvalidValue(vm, 'label', 'invalid') + self.assertPropertyInvalidValue(vm, 'label', 123) + + def test_140_netvm(self): + vm = self.get_vm() + self.setup_netvms(vm) + self.assertPropertyDefaultValue(vm, 'netvm', self.app.default_netvm) + self.assertPropertyValue(vm, 'netvm', self.netvm2, self.netvm2, + self.netvm2.name) + del vm.netvm + self.assertPropertyDefaultValue(vm, 'netvm', self.app.default_netvm) + self.assertPropertyValue(vm, 'netvm', self.netvm2.name, self.netvm2, + self.netvm2.name) + # XXX FIXME xml value + self.assertPropertyValue(vm, 'netvm', None, None, 'None') + self.assertPropertyInvalidValue(vm, 'netvm', 'invalid') + self.assertPropertyInvalidValue(vm, 'netvm', 123) + + def test_141_netvm_netvm(self): + vm = self.get_vm() + self.setup_netvms(vm) + self.assertPropertyInvalidValue(vm, 'netvm', self.nonetvm) + + def test_142_netvm_loopback(self): + vm = self.get_vm() + self.app.domains = {1: vm, vm: vm} + self.assertPropertyInvalidValue(vm, 'netvm', vm) + + def test_150_hvm(self): + vm = self.get_vm() + self._test_generic_bool_property(vm, 'hvm') + + def test_160_memory(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'memory', 400) + self.assertPropertyValue(vm, 'memory', 500, 500, '500') + del vm.memory + self.assertPropertyDefaultValue(vm, 'memory', 400) + self.assertPropertyValue(vm, 'memory', '500', 500, '500') + self.assertPropertyInvalidValue(vm, 'memory', -100) + self.assertPropertyInvalidValue(vm, 'memory', '-100') + self.assertPropertyInvalidValue(vm, 'memory', '') + self.assertPropertyInvalidValue(vm, 'memory', + 2 * self.app.host.memory_total) + # TODO: higher than maxmem + # TODO: human readable setter (500M, 4G)? + + def test_170_maxmem(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'maxmem', + self.app.host.memory_total / 1024 / 1024 / 2) + self.assertPropertyValue(vm, 'maxmem', 500, 500, '500') + del vm.maxmem + self.assertPropertyDefaultValue(vm, 'maxmem', + self.app.host.memory_total / 1024 / 1024 / 2) + self.assertPropertyValue(vm, 'maxmem', '500', 500, '500') + self.assertPropertyInvalidValue(vm, 'maxmem', -100) + self.assertPropertyInvalidValue(vm, 'maxmem', '-100') + self.assertPropertyInvalidValue(vm, 'maxmem', '') + self.assertPropertyInvalidValue(vm, 'maxmem', + 2 * self.app.host.memory_total) + # TODO: lower than memory + # TODO: human readable setter (500M, 4G)? + + def test_180_internal(self): + vm = self.get_vm() + self._test_generic_bool_property(vm, 'internal', False) + + def test_190_vcpus(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'vcpus', self.app.host.no_cpus) + self.assertPropertyValue(vm, 'vcpus', 3, 3, '3') + del vm.vcpus + self.assertPropertyDefaultValue(vm, 'vcpus', self.app.host.no_cpus) + self.assertPropertyValue(vm, 'vcpus', '3', 3, '3') + self.assertPropertyInvalidValue(vm, 'vcpus', 0) + self.assertPropertyInvalidValue(vm, 'vcpus', -2) + self.assertPropertyInvalidValue(vm, 'vcpus', '-2') + self.assertPropertyInvalidValue(vm, 'vcpus', '') + self.assertPropertyInvalidValue(vm, 'vcpus', + 2 * self.app.host.no_cpus) + + def test_200_debug(self): + vm = self.get_vm() + self._test_generic_bool_property(vm, 'debug', False) + + def test_210_installed_by_rpm(self): + vm = self.get_vm() + self._test_generic_bool_property(vm, 'installed_by_rpm', False) + + def test_220_include_in_backups(self): + vm = self.get_vm() + self._test_generic_bool_property(vm, 'include_in_backups', True) + + def test_230_backup_content(self): + vm = self.get_vm() + self._test_generic_bool_property(vm, 'backup_content', False) + + def test_240_firewall_conf(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'firewall_conf', 'firewall.xml') + self.assertPropertyValue(vm, 'firewall_conf', 'other.xml', + 'other.xml', 'other.xml') + del vm.firewall_conf + self.assertPropertyDefaultValue(vm, 'firewall_conf', + 'firewall.xml') + self.assertPropertyInvalidValue(vm, 'firewall_conf', None) @qubes.tests.skipUnlessDom0 - def test_200_create_on_disk(self): + def test_250_kernel(self): + kernels = os.listdir(os.path.join( + qubes.config.qubes_base_dir, + qubes.config.system_path['qubes_kernels_base_dir'])) + if not len(kernels): + self.skipTest('Needs at least one kernel installed') + self.app.default_kernel = kernels[0] vm = self.get_vm() - vm.create_on_disk() + self.assertPropertyDefaultValue(vm, 'kernel', kernels[0]) + self.assertPropertyValue(vm, 'kernel', kernels[-1], kernels[-1], + kernels[-1]) + del vm.kernel + self.assertPropertyDefaultValue(vm, 'kernel', kernels[0]) + self.assertPropertyInvalidValue(vm, 'kernel', 123) + self.assertPropertyInvalidValue(vm, 'kernel', 'invalid') + + def test_260_kernelopts(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'kernelopts', + qubes.config.defaults['kernelopts']) + self.assertPropertyValue(vm, 'kernelopts', 'some options', + 'some options', 'some options') + del vm.kernelopts + self.assertPropertyDefaultValue(vm, 'kernelopts', + qubes.config.defaults['kernelopts']) + self.assertPropertyValue(vm, 'kernelopts', '', + '', '') + # TODO? + # self.assertPropertyInvalidValue(vm, 'kernelopts', None), @unittest.skip('test not implemented') - def test_300_rename(self): - pass + def test_261_kernelopts_pcidevs(self): + vm = self.get_vm() + # how to do that here? use dummy DeviceManager/DeviceCollection? + # Disable events? + vm.devices['pci'].attach('something') + self.assertPropertyDefaultValue(vm, 'kernelopts', + qubes.config.defaults['kernelopts_pcidevs']) + + def test_270_qrexec_timeout(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'qrexec_timeout', 60) + self.assertPropertyValue(vm, 'qrexec_timeout', 3, 3, '3') + del vm.qrexec_timeout + self.assertPropertyDefaultValue(vm, 'qrexec_timeout', 60) + self.assertPropertyValue(vm, 'qrexec_timeout', '3', 3, '3') + self.assertPropertyInvalidValue(vm, 'qrexec_timeout', -2) + self.assertPropertyInvalidValue(vm, 'qrexec_timeout', '-2') + self.assertPropertyInvalidValue(vm, 'qrexec_timeout', '') + + def test_280_autostart(self): + vm = self.get_vm() + # FIXME any better idea to not involve systemctl call at this stage? + vm.events_enabled = False + self._test_generic_bool_property(vm, 'autostart', False) + + @qubes.tests.skipUnlessDom0 + def test_281_autostart_systemd(self): + vm = self.get_vm() + self.assertFalse(os.path.exists( + '/etc/systemd/system/multi-user.target.wants/' + 'qubes-vm@{}.service'.format(vm.name)), + "systemd service enabled before setting autostart") + vm.autostart = True + self.assertTrue(os.path.exists( + '/etc/systemd/system/multi-user.target.wants/' + 'qubes-vm@{}.service'.format(vm.name)), + "systemd service not enabled by autostart=True") + vm.autostart = False + self.assertFalse(os.path.exists( + '/etc/systemd/system/multi-user.target.wants/' + 'qubes-vm@{}.service'.format(vm.name)), + "systemd service not disabled by autostart=False") + vm.autostart = True + del vm.autostart + self.assertFalse(os.path.exists( + '/etc/systemd/system/multi-user.target.wants/' + 'qubes-vm@{}.service'.format(vm.name)), + "systemd service not disabled by resetting autostart") + + def test_290_dispvm_netvm(self): + vm = self.get_vm() + self.setup_netvms(vm) + self.assertPropertyDefaultValue(vm, 'dispvm_netvm', + self.app.default_netvm) + self.assertPropertyValue(vm, 'dispvm_netvm', self.netvm2, self.netvm2, + self.netvm2.name) + del vm.dispvm_netvm + self.assertPropertyDefaultValue(vm, 'dispvm_netvm', + self.app.default_netvm) + self.assertPropertyValue(vm, 'dispvm_netvm', self.netvm2.name, + self.netvm2, self.netvm2.name) + # XXX FIXME xml value + self.assertPropertyValue(vm, 'dispvm_netvm', None, None, 'None') + self.assertPropertyInvalidValue(vm, 'dispvm_netvm', 'invalid') + self.assertPropertyInvalidValue(vm, 'dispvm_netvm', 123) + + def test_291_dispvm_netvm_netvm(self): + vm = self.get_vm() + nonetvm = TestVM(qid=2, app=self.app, name='nonetvm') + self.app.domains = {1: vm, 2: nonetvm} + self.assertPropertyInvalidValue(vm, 'dispvm_netvm', nonetvm) + + def test_291_dispvm_netvm_default(self): + """Check if vm.dispvm_netvm default is really vm.netvm""" + vm = self.get_vm() + self.setup_netvms(vm) + vm.netvm = self.netvm2 + self.assertPropertyDefaultValue(vm, 'dispvm_netvm', self.netvm2) + del vm.netvm + self.assertPropertyDefaultValue(vm, 'dispvm_netvm', self.netvm1) + + def test_292_dispvm_netvm_loopback(self): + vm = self.get_vm() + self.app.domains = {1: vm, vm: vm} + self.assertPropertyInvalidValue(vm, 'dispvm_netvm', vm) + + @unittest.skip('TODO') + def test_300_qrexec_installed(self): + vm = self.get_vm() + self._test_generic_bool_property(vm, 'qrexec_installed') + # TODO: check inheritance from a template - in appvm copy of this test + + @unittest.skip('TODO') + def test_310_guiagent_installed(self): + vm = self.get_vm() + self._test_generic_bool_property(vm, 'guiagent_installed') + # TODO: check inheritance from a template - in appvm copy of this test + + @unittest.skip('TODO') + def test_320_seamless_gui_mod(self): + vm = self.get_vm() + self._test_generic_bool_property(vm, 'seamless_gui_mode') + # TODO: reject setting to True when guiagent_installed is false + + def test_330_mac(self): + vm = self.get_vm() + # TODO: calculate proper default here + default_mac = vm.mac + self.assertIsNotNone(default_mac) + self.assertPropertyDefaultValue(vm, 'mac', default_mac) + self.assertPropertyValue(vm, 'mac', '00:11:22:33:44:55', + '00:11:22:33:44:55', '00:11:22:33:44:55') + del vm.mac + self.assertPropertyDefaultValue(vm, 'mac', default_mac) + self.assertPropertyInvalidValue(vm, 'mac', 123) + self.assertPropertyInvalidValue(vm, 'mac', 'invalid') + self.assertPropertyInvalidValue(vm, 'mac', '00:11:22:33:44:55:66') + + def test_340_default_user(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'default_user', 'user') + self.assertPropertyValue(vm, 'default_user', 'someuser', 'someuser', + 'someuser') + del vm.default_user + self.assertPropertyDefaultValue(vm, 'default_user', 'user') + self.assertPropertyValue(vm, 'default_user', 123, '123', '123') + # TODO: check propagation for template-based VMs + + @unittest.skip('TODO') + def test_350_timezone(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'timezone', 'localtime') + self.assertPropertyValue(vm, 'timezone', 0, 0, '0') + del vm.timezone + self.assertPropertyDefaultValue(vm, 'timezone', 'localtime') + self.assertPropertyValue(vm, 'timezone', '0', 0, '0') + self.assertPropertyValue(vm, 'timezone', -3600, -3600, '-3600') + self.assertPropertyValue(vm, 'timezone', 7200, 7200, '7200') + + @unittest.skip('TODO') + def test_360_drive(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'drive', None) + # self.execute_tests('drive', [ + # ('hd:dom0:/tmp/drive.img', 'hd:dom0:/tmp/drive.img', True), + # ('hd:/tmp/drive.img', 'hd:dom0:/tmp/drive.img', True), + # ('cdrom:dom0:/tmp/drive.img', 'cdrom:dom0:/tmp/drive.img', True), + # ('cdrom:/tmp/drive.img', 'cdrom:dom0:/tmp/drive.img', True), + # ('/tmp/drive.img', 'cdrom:dom0:/tmp/drive.img', True), + # ('hd:drive.img', '', False), + # ('drive.img', '', False), + # ]) + + @unittest.skip('TODO') + def test_370_pci_strictreset(self): + vm = self.get_vm() + self._test_generic_bool_property(vm, 'pci_strictreset') + + def test_380_backup_size(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'backup_size', 0) + self.assertPropertyValue(vm, 'backup_size', 0, 0, '0') + del vm.backup_size + self.assertPropertyDefaultValue(vm, 'backup_size', 0) + self.assertPropertyValue(vm, 'backup_size', '0', 0, '0') + self.assertPropertyValue(vm, 'backup_size', 300, 300, '300') + + def test_390_backup_path(self): + vm = self.get_vm() + self.assertPropertyDefaultValue(vm, 'backup_path', '') + self.assertPropertyValue(vm, 'backup_path', 'some/dir', 'some/dir') + del vm.backup_path + self.assertPropertyDefaultValue(vm, 'backup_path', '') + + def test_400_backup_timestamp(self): + vm = self.get_vm() + timestamp = datetime.datetime(2016, 1, 1, 12, 14, 2) + timestamp_str = timestamp.strftime('%s') + self.assertPropertyDefaultValue(vm, 'backup_timestamp', None) + self.assertPropertyValue(vm, 'backup_timestamp', timestamp, + timestamp, timestamp_str) + del vm.backup_timestamp + self.assertPropertyDefaultValue(vm, 'backup_timestamp', None) + self.assertPropertyValue(vm, 'backup_timestamp', timestamp_str, + timestamp) + self.assertPropertyInvalidValue(vm, 'backup_timestamp', 'xxx') + self.assertPropertyInvalidValue(vm, 'backup_timestamp', None)