123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771 |
- from unittest import mock
- import argparse
- import asyncio
- import datetime
- import io
- import os
- import pathlib
- import subprocess
- import tempfile
- import rpm
- import qubesadmin.tests
- import qubesadmin.tools.qvm_template
- class TC_00_qvm_template(qubesadmin.tests.QubesTestCase):
- def setUp(self):
- super().setUp()
- def tearDown(self):
- super().tearDown()
- def test_000_verify_rpm_success(self):
- ts = mock.MagicMock()
- # Just return a dict instead of rpm.hdr
- hdr = {
- rpm.RPMTAG_SIGPGP: 'xxx', # non-empty
- rpm.RPMTAG_SIGGPG: 'xxx', # non-empty
- }
- ts.hdrFromFdno.return_value = hdr
- ret = qubesadmin.tools.qvm_template.verify_rpm('/dev/null', ts)
- ts.hdrFromFdno.assert_called_once()
- self.assertEqual(hdr, ret)
- self.assertAllCalled()
- def test_001_verify_rpm_nosig_fail(self):
- ts = mock.MagicMock()
- # Just return a dict instead of rpm.hdr
- hdr = {
- rpm.RPMTAG_SIGPGP: None, # empty
- rpm.RPMTAG_SIGGPG: None, # empty
- }
- ts.hdrFromFdno.return_value = hdr
- ret = qubesadmin.tools.qvm_template.verify_rpm('/dev/null', ts)
- ts.hdrFromFdno.assert_called_once()
- self.assertEqual(ret, None)
- self.assertAllCalled()
- def test_002_verify_rpm_nosig_success(self):
- ts = mock.MagicMock()
- # Just return a dict instead of rpm.hdr
- hdr = {
- rpm.RPMTAG_SIGPGP: None, # empty
- rpm.RPMTAG_SIGGPG: None, # empty
- }
- ts.hdrFromFdno.return_value = hdr
- ret = qubesadmin.tools.qvm_template.verify_rpm('/dev/null', ts, True)
- ts.hdrFromFdno.assert_called_once()
- self.assertEqual(ret, hdr)
- self.assertAllCalled()
- def test_003_verify_rpm_badsig_fail(self):
- ts = mock.MagicMock()
- def f(*args):
- raise rpm.error('public key not trusted')
- ts.hdrFromFdno.side_effect = f
- ret = qubesadmin.tools.qvm_template.verify_rpm('/dev/null', ts)
- ts.hdrFromFdno.assert_called_once()
- self.assertEqual(ret, None)
- self.assertAllCalled()
- @mock.patch('subprocess.Popen')
- def test_010_extract_rpm_success(self, mock_popen):
- pipe = mock.Mock()
- mock_popen.return_value.stdout = pipe
- mock_popen.return_value.wait.return_value = 0
- with tempfile.NamedTemporaryFile() as fd, \
- tempfile.TemporaryDirectory() as dir:
- path = fd.name
- dirpath = dir
- ret = qubesadmin.tools.qvm_template.extract_rpm(
- 'test-vm', path, dirpath)
- self.assertEqual(ret, True)
- self.assertEqual(mock_popen.mock_calls, [
- mock.call(['rpm2cpio', path], stdout=subprocess.PIPE),
- mock.call([
- 'cpio',
- '-idm',
- '-D',
- dirpath,
- './var/lib/qubes/vm-templates/test-vm/*'
- ], stdin=pipe, stdout=subprocess.DEVNULL),
- mock.call().wait(),
- mock.call().wait()
- ])
- self.assertAllCalled()
- @mock.patch('subprocess.Popen')
- def test_011_extract_rpm_fail(self, mock_popen):
- pipe = mock.Mock()
- mock_popen.return_value.stdout = pipe
- mock_popen.return_value.wait.return_value = 1
- with tempfile.NamedTemporaryFile() as fd, \
- tempfile.TemporaryDirectory() as dir:
- path = fd.name
- dirpath = dir
- ret = qubesadmin.tools.qvm_template.extract_rpm(
- 'test-vm', path, dirpath)
- self.assertEqual(ret, False)
- self.assertEqual(mock_popen.mock_calls, [
- mock.call(['rpm2cpio', path], stdout=subprocess.PIPE),
- mock.call([
- 'cpio',
- '-idm',
- '-D',
- dirpath,
- './var/lib/qubes/vm-templates/test-vm/*'
- ], stdin=pipe, stdout=subprocess.DEVNULL),
- mock.call().wait()
- ])
- self.assertAllCalled()
- def add_new_vm_side_effect(self, *args, **kwargs):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\0test-vm class=TemplateVM state=Halted\n'
- self.app.domains.clear_cache()
- return self.app.domains['test-vm']
- @mock.patch('os.remove')
- @mock.patch('os.rename')
- @mock.patch('os.makedirs')
- @mock.patch('subprocess.check_call')
- @mock.patch('qubesadmin.tools.qvm_template.confirm_action')
- @mock.patch('qubesadmin.tools.qvm_template.extract_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.download')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.rpm_transactionset')
- def test_100_install_local_success(
- self,
- mock_ts,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename,
- mock_remove):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = b'0\0'
- build_time = '2020-09-01 22:30:00' # 1598970600
- install_time = '2020-09-01 23:30:00.508230'
- for key, val in [
- ('name', 'test-vm'),
- ('epoch', '2'),
- ('version', '4.1'),
- ('release', '2020'),
- ('reponame', '@commandline'),
- ('buildtime', build_time),
- ('installtime', install_time),
- ('license', 'GPL'),
- ('url', 'https://qubes-os.org'),
- ('summary', 'Summary'),
- ('description', 'Desc|desc')]:
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Set',
- f'template-{key}',
- val.encode())] = b'0\0'
- mock_verify.return_value = {
- rpm.RPMTAG_NAME : 'qubes-template-test-vm',
- rpm.RPMTAG_BUILDTIME : 1598970600,
- rpm.RPMTAG_DESCRIPTION : 'Desc\ndesc',
- rpm.RPMTAG_EPOCHNUM : 2,
- rpm.RPMTAG_LICENSE : 'GPL',
- rpm.RPMTAG_RELEASE : '2020',
- rpm.RPMTAG_SUMMARY : 'Summary',
- rpm.RPMTAG_URL : 'https://qubes-os.org',
- rpm.RPMTAG_VERSION : '4.1'
- }
- mock_dl_list.return_value = {}
- mock_call.side_effect = self.add_new_vm_side_effect
- mock_time = mock.Mock(wraps=datetime.datetime)
- mock_time.today.return_value = \
- datetime.datetime.fromisoformat(install_time)
- with mock.patch('builtins.open', mock.mock_open()) as mock_open, \
- mock.patch('datetime.datetime', new=mock_time), \
- mock.patch('tempfile.TemporaryDirectory') as mock_tmpdir, \
- mock.patch('sys.stderr', new=io.StringIO()) as mock_err, \
- tempfile.NamedTemporaryFile(suffix='.rpm') as template_file:
- path = template_file.name
- args = argparse.Namespace(
- templates=[path],
- keyring='/usr/share/qubes/repo-templates/keys',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- yes=False,
- allow_pv=False,
- pool=None
- )
- mock_tmpdir.return_value.__enter__.return_value = \
- '/var/tmp/qvm-template-tmpdir'
- qubesadmin.tools.qvm_template.install(args, self.app)
- # Lock file created
- self.assertEqual(mock_open.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck', 'x'),
- mock.call().__enter__(),
- mock.call().__exit__(None, None, None)
- ])
- # Keyring created
- self.assertEqual(mock_ts.mock_calls, [
- mock.call('/usr/share/qubes/repo-templates/keys')
- ])
- # Package verified
- self.assertEqual(mock_verify.mock_calls, [
- mock.call(path, mock_ts('/usr/share/qubes/repo-templates/keys'),
- False)
- ])
- # Attempt to get download list
- selector = qubesadmin.tools.qvm_template.VersionSelector.LATEST
- self.assertEqual(mock_dl_list.mock_calls, [
- mock.call(args, self.app, version_selector=selector)
- ])
- # Nothing downloaded
- self.assertEqual(mock_dl.mock_calls, [
- mock.call(args, self.app, path_override='/var/cache/qvm-template',
- dl_list={}, suffix='.unverified', version_selector=selector)
- ])
- # Package is extracted
- self.assertEqual(mock_extract.mock_calls, [
- mock.call('test-vm', path, '/var/tmp/qvm-template-tmpdir')
- ])
- # No packages overwritten, so no confirm needed
- self.assertEqual(mock_confirm.mock_calls, [])
- # qvm-template-postprocess is called
- self.assertEqual(mock_call.mock_calls, [
- mock.call([
- 'qvm-template-postprocess',
- '--really',
- '--no-installed-by-rpm',
- 'post-install',
- 'test-vm',
- '/var/tmp/qvm-template-tmpdir'
- '/var/lib/qubes/vm-templates/test-vm'
- ])
- ])
- # Cache directory created
- self.assertEqual(mock_mkdirs.mock_calls, [
- mock.call(args.cachedir, exist_ok=True)
- ])
- # No templates downloaded, thus no renames needed
- self.assertEqual(mock_rename.mock_calls, [])
- # Lock file removed
- self.assertEqual(mock_remove.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck')
- ])
- self.assertAllCalled()
- @mock.patch('os.remove')
- @mock.patch('os.rename')
- @mock.patch('os.makedirs')
- @mock.patch('subprocess.check_call')
- @mock.patch('qubesadmin.tools.qvm_template.confirm_action')
- @mock.patch('qubesadmin.tools.qvm_template.extract_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.download')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.rpm_transactionset')
- def test_101_install_local_postprocargs_success(
- self,
- mock_ts,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename,
- mock_remove):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = b'0\0'
- build_time = '2020-09-01 22:30:00' # 1598970600
- install_time = '2020-09-01 23:30:00.508230'
- for key, val in [
- ('name', 'test-vm'),
- ('epoch', '2'),
- ('version', '4.1'),
- ('release', '2020'),
- ('reponame', '@commandline'),
- ('buildtime', build_time),
- ('installtime', install_time),
- ('license', 'GPL'),
- ('url', 'https://qubes-os.org'),
- ('summary', 'Summary'),
- ('description', 'Desc|desc')]:
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Set',
- f'template-{key}',
- val.encode())] = b'0\0'
- mock_verify.return_value = {
- rpm.RPMTAG_NAME : 'qubes-template-test-vm',
- rpm.RPMTAG_BUILDTIME : 1598970600,
- rpm.RPMTAG_DESCRIPTION : 'Desc\ndesc',
- rpm.RPMTAG_EPOCHNUM : 2,
- rpm.RPMTAG_LICENSE : 'GPL',
- rpm.RPMTAG_RELEASE : '2020',
- rpm.RPMTAG_SUMMARY : 'Summary',
- rpm.RPMTAG_URL : 'https://qubes-os.org',
- rpm.RPMTAG_VERSION : '4.1'
- }
- mock_dl_list.return_value = {}
- mock_call.side_effect = self.add_new_vm_side_effect
- mock_time = mock.Mock(wraps=datetime.datetime)
- mock_time.today.return_value = \
- datetime.datetime.fromisoformat(install_time)
- with mock.patch('builtins.open', mock.mock_open()) as mock_open, \
- mock.patch('datetime.datetime', new=mock_time), \
- mock.patch('tempfile.TemporaryDirectory') as mock_tmpdir, \
- mock.patch('sys.stderr', new=io.StringIO()) as mock_err, \
- tempfile.NamedTemporaryFile(suffix='.rpm') as template_file:
- path = template_file.name
- args = argparse.Namespace(
- templates=[path],
- keyring='/usr/share/qubes/repo-templates/keys',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- yes=False,
- allow_pv=True,
- pool='my-pool'
- )
- mock_tmpdir.return_value.__enter__.return_value = \
- '/var/tmp/qvm-template-tmpdir'
- qubesadmin.tools.qvm_template.install(args, self.app)
- # Lock file created
- self.assertEqual(mock_open.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck', 'x'),
- mock.call().__enter__(),
- mock.call().__exit__(None, None, None)
- ])
- # Keyring created
- self.assertEqual(mock_ts.mock_calls, [
- mock.call('/usr/share/qubes/repo-templates/keys')
- ])
- # Package verified
- self.assertEqual(mock_verify.mock_calls, [
- mock.call(path, mock_ts('/usr/share/qubes/repo-templates/keys'),
- False)
- ])
- # Attempt to get download list
- selector = qubesadmin.tools.qvm_template.VersionSelector.LATEST
- self.assertEqual(mock_dl_list.mock_calls, [
- mock.call(args, self.app, version_selector=selector)
- ])
- # Nothing downloaded
- self.assertEqual(mock_dl.mock_calls, [
- mock.call(args, self.app, path_override='/var/cache/qvm-template',
- dl_list={}, suffix='.unverified', version_selector=selector)
- ])
- # Package is extracted
- self.assertEqual(mock_extract.mock_calls, [
- mock.call('test-vm', path, '/var/tmp/qvm-template-tmpdir')
- ])
- # No packages overwritten, so no confirm needed
- self.assertEqual(mock_confirm.mock_calls, [])
- # qvm-template-postprocess is called
- self.assertEqual(mock_call.mock_calls, [
- mock.call([
- 'qvm-template-postprocess',
- '--really',
- '--no-installed-by-rpm',
- '--allow-pv',
- '--pool',
- 'my-pool',
- 'post-install',
- 'test-vm',
- '/var/tmp/qvm-template-tmpdir'
- '/var/lib/qubes/vm-templates/test-vm'
- ])
- ])
- # Cache directory created
- self.assertEqual(mock_mkdirs.mock_calls, [
- mock.call(args.cachedir, exist_ok=True)
- ])
- # No templates downloaded, thus no renames needed
- self.assertEqual(mock_rename.mock_calls, [])
- # Lock file removed
- self.assertEqual(mock_remove.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck')
- ])
- self.assertAllCalled()
- @mock.patch('os.remove')
- @mock.patch('os.rename')
- @mock.patch('os.makedirs')
- @mock.patch('subprocess.check_call')
- @mock.patch('qubesadmin.tools.qvm_template.confirm_action')
- @mock.patch('qubesadmin.tools.qvm_template.extract_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.download')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.rpm_transactionset')
- def test_102_install_local_badsig_fail(
- self,
- mock_ts,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename,
- mock_remove):
- mock_verify.return_value = None
- mock_time = mock.Mock(wraps=datetime.datetime)
- with mock.patch('builtins.open', mock.mock_open()) as mock_open, \
- mock.patch('datetime.datetime', new=mock_time), \
- mock.patch('tempfile.TemporaryDirectory') as mock_tmpdir, \
- mock.patch('sys.stderr', new=io.StringIO()) as mock_err, \
- tempfile.NamedTemporaryFile(suffix='.rpm') as template_file:
- path = template_file.name
- args = argparse.Namespace(
- templates=[path],
- keyring='/usr/share/qubes/repo-templates/keys',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- yes=False,
- allow_pv=False,
- pool=None
- )
- mock_tmpdir.return_value.__enter__.return_value = \
- '/var/tmp/qvm-template-tmpdir'
- # Should raise parser.error
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.install(args, self.app)
- # Lock file created
- self.assertEqual(mock_open.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck', 'x'),
- mock.call().__enter__(),
- mock.call().__exit__(None, None, None)
- ])
- # Check error message
- self.assertTrue('verification failed' in mock_err.getvalue())
- # Keyring created
- self.assertEqual(mock_ts.mock_calls, [
- mock.call('/usr/share/qubes/repo-templates/keys')
- ])
- # Package verified
- self.assertEqual(mock_verify.mock_calls, [
- mock.call(path, mock_ts('/usr/share/qubes/repo-templates/keys'),
- False)
- ])
- # Should not be executed:
- self.assertEqual(mock_dl_list.mock_calls, [])
- self.assertEqual(mock_dl.mock_calls, [])
- self.assertEqual(mock_extract.mock_calls, [])
- self.assertEqual(mock_confirm.mock_calls, [])
- self.assertEqual(mock_call.mock_calls, [])
- self.assertEqual(mock_rename.mock_calls, [])
- # Lock file removed
- self.assertEqual(mock_remove.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck')
- ])
- self.assertAllCalled()
- @mock.patch('os.remove')
- @mock.patch('os.rename')
- @mock.patch('os.makedirs')
- @mock.patch('subprocess.check_call')
- @mock.patch('qubesadmin.tools.qvm_template.confirm_action')
- @mock.patch('qubesadmin.tools.qvm_template.extract_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.download')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.rpm_transactionset')
- def test_103_install_local_exists_fail(
- self,
- mock_ts,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename,
- mock_remove):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\0test-vm class=TemplateVM state=Halted\n'
- mock_verify.return_value = {
- rpm.RPMTAG_NAME : 'qubes-template-test-vm',
- rpm.RPMTAG_BUILDTIME : 1598970600,
- rpm.RPMTAG_DESCRIPTION : 'Desc\ndesc',
- rpm.RPMTAG_EPOCHNUM : 2,
- rpm.RPMTAG_LICENSE : 'GPL',
- rpm.RPMTAG_RELEASE : '2020',
- rpm.RPMTAG_SUMMARY : 'Summary',
- rpm.RPMTAG_URL : 'https://qubes-os.org',
- rpm.RPMTAG_VERSION : '4.1'
- }
- mock_dl_list.return_value = {}
- mock_time = mock.Mock(wraps=datetime.datetime)
- with mock.patch('builtins.open', mock.mock_open()) as mock_open, \
- mock.patch('datetime.datetime', new=mock_time), \
- mock.patch('tempfile.TemporaryDirectory') as mock_tmpdir, \
- mock.patch('sys.stderr', new=io.StringIO()) as mock_err, \
- tempfile.NamedTemporaryFile(suffix='.rpm') as template_file:
- path = template_file.name
- args = argparse.Namespace(
- templates=[path],
- keyring='/usr/share/qubes/repo-templates/keys',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- yes=False,
- allow_pv=False,
- pool=None
- )
- mock_tmpdir.return_value.__enter__.return_value = \
- '/var/tmp/qvm-template-tmpdir'
- qubesadmin.tools.qvm_template.install(args, self.app)
- # Lock file created
- self.assertEqual(mock_open.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck', 'x'),
- mock.call().__enter__(),
- mock.call().__exit__(None, None, None)
- ])
- # Check warning message
- self.assertTrue('already installed' in mock_err.getvalue())
- # Keyring created
- self.assertEqual(mock_ts.mock_calls, [
- mock.call('/usr/share/qubes/repo-templates/keys')
- ])
- # Package verified
- self.assertEqual(mock_verify.mock_calls, [
- mock.call(path, mock_ts('/usr/share/qubes/repo-templates/keys'),
- False)
- ])
- # Attempt to get download list
- selector = qubesadmin.tools.qvm_template.VersionSelector.LATEST
- self.assertEqual(mock_dl_list.mock_calls, [
- mock.call(args, self.app, version_selector=selector)
- ])
- # Nothing downloaded
- self.assertEqual(mock_dl.mock_calls, [
- mock.call(args, self.app, path_override='/var/cache/qvm-template',
- dl_list={}, suffix='.unverified', version_selector=selector)
- ])
- # Should not be executed:
- self.assertEqual(mock_extract.mock_calls, [])
- self.assertEqual(mock_confirm.mock_calls, [])
- self.assertEqual(mock_call.mock_calls, [])
- self.assertEqual(mock_rename.mock_calls, [])
- # Lock file removed
- self.assertEqual(mock_remove.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck')
- ])
- self.assertAllCalled()
- @mock.patch('os.remove')
- @mock.patch('os.rename')
- @mock.patch('os.makedirs')
- @mock.patch('subprocess.check_call')
- @mock.patch('qubesadmin.tools.qvm_template.confirm_action')
- @mock.patch('qubesadmin.tools.qvm_template.extract_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.download')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.rpm_transactionset')
- def test_104_install_local_badpkgname_fail(
- self,
- mock_ts,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename,
- mock_remove):
- mock_verify.return_value = {
- rpm.RPMTAG_NAME : 'Xqubes-template-test-vm',
- rpm.RPMTAG_BUILDTIME : 1598970600,
- rpm.RPMTAG_DESCRIPTION : 'Desc\ndesc',
- rpm.RPMTAG_EPOCHNUM : 2,
- rpm.RPMTAG_LICENSE : 'GPL',
- rpm.RPMTAG_RELEASE : '2020',
- rpm.RPMTAG_SUMMARY : 'Summary',
- rpm.RPMTAG_URL : 'https://qubes-os.org',
- rpm.RPMTAG_VERSION : '4.1'
- }
- mock_time = mock.Mock(wraps=datetime.datetime)
- with mock.patch('builtins.open', mock.mock_open()) as mock_open, \
- mock.patch('datetime.datetime', new=mock_time), \
- mock.patch('tempfile.TemporaryDirectory') as mock_tmpdir, \
- mock.patch('sys.stderr', new=io.StringIO()) as mock_err, \
- tempfile.NamedTemporaryFile(suffix='.rpm') as template_file:
- path = template_file.name
- args = argparse.Namespace(
- templates=[path],
- keyring='/usr/share/qubes/repo-templates/keys',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- yes=False,
- allow_pv=False,
- pool=None
- )
- mock_tmpdir.return_value.__enter__.return_value = \
- '/var/tmp/qvm-template-tmpdir'
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.install(args, self.app)
- # Lock file created
- self.assertEqual(mock_open.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck', 'x'),
- mock.call().__enter__(),
- mock.call().__exit__(None, None, None)
- ])
- # Check error message
- self.assertTrue('Illegal package name' in mock_err.getvalue())
- # Keyring created
- self.assertEqual(mock_ts.mock_calls, [
- mock.call('/usr/share/qubes/repo-templates/keys')
- ])
- # Package verified
- self.assertEqual(mock_verify.mock_calls, [
- mock.call(path, mock_ts('/usr/share/qubes/repo-templates/keys'),
- False)
- ])
- # Should not be executed:
- self.assertEqual(mock_dl_list.mock_calls, [])
- self.assertEqual(mock_dl.mock_calls, [])
- self.assertEqual(mock_extract.mock_calls, [])
- self.assertEqual(mock_confirm.mock_calls, [])
- self.assertEqual(mock_call.mock_calls, [])
- self.assertEqual(mock_rename.mock_calls, [])
- # Lock file removed
- self.assertEqual(mock_remove.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck')
- ])
- self.assertAllCalled()
- @mock.patch('os.rename')
- @mock.patch('os.makedirs')
- @mock.patch('subprocess.check_call')
- @mock.patch('qubesadmin.tools.qvm_template.confirm_action')
- @mock.patch('qubesadmin.tools.qvm_template.extract_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.download')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.rpm_transactionset')
- def test_105_install_local_existinginstance_fail(
- self,
- mock_ts,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename):
- mock_time = mock.Mock(wraps=datetime.datetime)
- with mock.patch('datetime.datetime', new=mock_time), \
- mock.patch('tempfile.TemporaryDirectory') as mock_tmpdir, \
- mock.patch('sys.stderr', new=io.StringIO()) as mock_err, \
- tempfile.NamedTemporaryFile(suffix='.rpm') as template_file:
- path = template_file.name
- args = argparse.Namespace(
- templates=[path],
- keyring='/usr/share/qubes/repo-templates/keys',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- yes=False,
- allow_pv=False,
- pool=None
- )
- mock_tmpdir.return_value.__enter__.return_value = \
- '/var/tmp/qvm-template-tmpdir'
- pathlib.Path('/var/tmp/qvm-template.lck').touch()
- try:
- with self.assertRaises(SystemExit), \
- mock.patch('os.remove') as mock_remove:
- qubesadmin.tools.qvm_template.install(args, self.app)
- self.assertEqual(mock_remove.mock_calls, [])
- finally:
- # Lock file not removed
- self.assertTrue(os.path.exists('/var/tmp/qvm-template.lck'))
- os.remove('/var/tmp/qvm-template.lck')
- # Check error message
- self.assertTrue('another instance of qvm-template is running' \
- in mock_err.getvalue())
- # Should not be executed:
- self.assertEqual(mock_ts.mock_calls, [])
- self.assertEqual(mock_verify.mock_calls, [])
- self.assertEqual(mock_dl_list.mock_calls, [])
- self.assertEqual(mock_dl.mock_calls, [])
- self.assertEqual(mock_extract.mock_calls, [])
- self.assertEqual(mock_confirm.mock_calls, [])
- self.assertEqual(mock_call.mock_calls, [])
- self.assertEqual(mock_rename.mock_calls, [])
- self.assertAllCalled()
- @mock.patch('os.remove')
- @mock.patch('os.rename')
- @mock.patch('os.makedirs')
- @mock.patch('subprocess.check_call')
- @mock.patch('qubesadmin.tools.qvm_template.confirm_action')
- @mock.patch('qubesadmin.tools.qvm_template.extract_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.download')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.rpm_transactionset')
- def test_106_install_local_badpath_fail(
- self,
- mock_ts,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename,
- mock_remove):
- mock_time = mock.Mock(wraps=datetime.datetime)
- with mock.patch('builtins.open', mock.mock_open()) as mock_open, \
- mock.patch('datetime.datetime', new=mock_time), \
- mock.patch('tempfile.TemporaryDirectory') as mock_tmpdir, \
- mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- path = '/var/tmp/ShOulD-NoT-ExIsT.rpm'
- args = argparse.Namespace(
- templates=[path],
- keyring='/usr/share/qubes/repo-templates/keys',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- yes=False,
- allow_pv=False,
- pool=None
- )
- mock_tmpdir.return_value.__enter__.return_value = \
- '/var/tmp/qvm-template-tmpdir'
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.install(args, self.app)
- # Lock file created
- self.assertEqual(mock_open.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck', 'x'),
- mock.call().__enter__(),
- mock.call().__exit__(None, None, None)
- ])
- # Check error message
- self.assertTrue(f"RPM file '{path}' not found" \
- in mock_err.getvalue())
- # Keyring created
- self.assertEqual(mock_ts.mock_calls, [
- mock.call('/usr/share/qubes/repo-templates/keys')
- ])
- # Should not be executed:
- self.assertEqual(mock_verify.mock_calls, [])
- self.assertEqual(mock_dl_list.mock_calls, [])
- self.assertEqual(mock_dl.mock_calls, [])
- self.assertEqual(mock_extract.mock_calls, [])
- self.assertEqual(mock_confirm.mock_calls, [])
- self.assertEqual(mock_call.mock_calls, [])
- self.assertEqual(mock_rename.mock_calls, [])
- # Lock file removed
- self.assertEqual(mock_remove.mock_calls, [
- mock.call('/var/tmp/qvm-template.lck')
- ])
- self.assertAllCalled()
|