12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097 |
- import re
- from unittest import mock
- import argparse
- import asyncio
- import datetime
- import io
- import os
- import pathlib
- import subprocess
- import tempfile
- import fcntl
- import rpm
- import qubesadmin.tests
- import qubesadmin.tools.qvm_template
- class re_str(str):
- def __eq__(self, other):
- return bool(re.match(self, other))
- def __hash__(self):
- return super().__hash__()
- class TC_00_qvm_template(qubesadmin.tests.QubesTestCase):
- def setUp(self):
- # Print str(list) directly so that the output is consistent no matter
- # which implementation of `column` we use
- self.mock_table = mock.patch('qubesadmin.tools.print_table')
- mock_table = self.mock_table.start()
- def print_table(table, *args):
- print(str(table))
- mock_table.side_effect = print_table
- super().setUp()
- def tearDown(self):
- self.mock_table.stop()
- super().tearDown()
- @mock.patch('rpm.TransactionSet')
- @mock.patch('subprocess.check_call')
- @mock.patch('subprocess.check_output')
- def test_000_verify_rpm_success(self, mock_proc, mock_call, mock_ts):
- # Just return a dict instead of rpm.hdr
- hdr = {
- rpm.RPMTAG_SIGPGP: 'xxx', # non-empty
- rpm.RPMTAG_SIGGPG: 'xxx', # non-empty
- rpm.RPMTAG_NAME: 'qubes-template-test-vm',
- }
- mock_ts.return_value.hdrFromFdno.return_value = hdr
- mock_proc.return_value = b'dummy.rpm: digests signatures OK\n'
- ret = qubesadmin.tools.qvm_template.verify_rpm('/dev/null',
- '/path/to/key', template_name='test-vm')
- mock_call.assert_called_once()
- mock_proc.assert_called_once()
- self.assertEqual(hdr, ret)
- self.assertAllCalled()
- @mock.patch('rpm.TransactionSet')
- @mock.patch('subprocess.check_call')
- @mock.patch('subprocess.check_output')
- def test_001_verify_rpm_nosig_fail(self, mock_proc, mock_call, mock_ts):
- # Just return a dict instead of rpm.hdr
- hdr = {
- rpm.RPMTAG_SIGPGP: None, # empty
- rpm.RPMTAG_SIGGPG: None, # empty
- }
- mock_ts.return_value.hdrFromFdno.return_value = hdr
- mock_proc.return_value = b'dummy.rpm: digests OK\n'
- with self.assertRaises(Exception) as e:
- qubesadmin.tools.qvm_template.verify_rpm('/dev/null',
- '/path/to/key')
- mock_call.assert_called_once()
- mock_proc.assert_called_once()
- self.assertIn('Signature verification failed', e.exception.args[0])
- mock_ts.assert_not_called()
- self.assertAllCalled()
- @mock.patch('rpm.TransactionSet')
- @mock.patch('subprocess.check_call')
- @mock.patch('subprocess.check_output')
- def test_002_verify_rpm_nosig_success(self, mock_proc, mock_call, mock_ts):
- # Just return a dict instead of rpm.hdr
- hdr = {
- rpm.RPMTAG_SIGPGP: None, # empty
- rpm.RPMTAG_SIGGPG: None, # empty
- }
- mock_ts.return_value.hdrFromFdno.return_value = hdr
- mock_proc.return_value = b'dummy.rpm: digests OK\n'
- ret = qubesadmin.tools.qvm_template.verify_rpm('/dev/null',
- '/path/to/key', True)
- mock_proc.assert_not_called()
- mock_call.assert_not_called()
- self.assertEqual(ret, hdr)
- self.assertAllCalled()
- @mock.patch('rpm.TransactionSet')
- @mock.patch('subprocess.check_call')
- @mock.patch('subprocess.check_output')
- def test_003_verify_rpm_badsig_fail(self, mock_proc, mock_call, mock_ts):
- mock_proc.side_effect = subprocess.CalledProcessError(1,
- ['rpmkeys', '--checksig'], b'/dev/null: digests SIGNATURES NOT OK\n')
- with self.assertRaises(Exception) as e:
- qubesadmin.tools.qvm_template.verify_rpm('/dev/null',
- '/path/to/key')
- mock_call.assert_called_once()
- mock_proc.assert_called_once()
- self.assertIn('Signature verification failed', e.exception.args[0])
- mock_ts.assert_not_called()
- self.assertAllCalled()
- @mock.patch('rpm.TransactionSet')
- @mock.patch('subprocess.check_call')
- @mock.patch('subprocess.check_output')
- def test_004_verify_rpm_badname(self, mock_proc, mock_call, mock_ts):
- mock_proc.return_value = b'/dev/null: digests signatures OK\n'
- hdr = {
- rpm.RPMTAG_SIGPGP: 'xxx', # non-empty
- rpm.RPMTAG_SIGGPG: 'xxx', # non-empty
- rpm.RPMTAG_NAME: 'qubes-template-unexpected',
- }
- mock_ts.return_value.hdrFromFdno.return_value = hdr
- with self.assertRaises(
- qubesadmin.tools.qvm_template.SignatureVerificationError) as e:
- qubesadmin.tools.qvm_template.verify_rpm('/dev/null',
- '/path/to/key', template_name='test-vm')
- mock_call.assert_called_once()
- mock_proc.assert_called_once()
- self.assertIn('package does not match expected template name',
- e.exception.args[0])
- mock_ts.assert_called_once()
- 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()
- @mock.patch('qubesadmin.tools.qvm_template.get_keys_for_repos')
- def test_090_install_lock(self, mock_get_keys):
- class SuccessError(Exception):
- pass
- mock_get_keys.side_effect = SuccessError
- with mock.patch('qubesadmin.tools.qvm_template.LOCK_FILE', '/tmp/test.lock'):
- with self.subTest('not locked'):
- with self.assertRaises(SuccessError):
- # args don't matter
- qubesadmin.tools.qvm_template.install(mock.MagicMock(), None)
- self.assertFalse(os.path.exists('/tmp/test.lock'))
- with self.subTest('lock exists but unlocked'):
- with open('/tmp/test.lock', 'w') as f:
- with self.assertRaises(SuccessError):
- # args don't matter
- qubesadmin.tools.qvm_template.install(mock.MagicMock(), None)
- self.assertFalse(os.path.exists('/tmp/test.lock'))
- with self.subTest('locked'):
- with open('/tmp/test.lock', 'w') as f:
- fcntl.flock(f, fcntl.LOCK_EX)
- with self.assertRaises(
- qubesadmin.tools.qvm_template.AlreadyRunning):
- # args don't matter
- qubesadmin.tools.qvm_template.install(mock.MagicMock(), None)
- # and not cleaned up then
- self.assertTrue(os.path.exists('/tmp/test.lock'))
- 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.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')
- def test_100_install_local_success(
- self,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = b'0\0'
- build_time = '2020-09-01 14:30:00' # 1598970600
- install_time = '2020-09-01 15:30:00'
- 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.now.return_value = \
- datetime.datetime(2020, 9, 1, 15, 30, tzinfo=datetime.timezone.utc)
- with mock.patch('qubesadmin.tools.qvm_template.LOCK_FILE', '/tmp/test.lock'), \
- 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='/tmp/keyring.gpg',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- repo_files=[],
- releasever='4.1',
- 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)
- # 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
- mock_dl.assert_called_with(args, self.app,
- dl_list={}, version_selector=selector)
- mock_verify.assert_called_once_with(template_file.name, '/tmp/keyring.gpg',
- nogpgcheck=False)
- # Package is extracted
- mock_extract.assert_called_with('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, [])
- 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')
- def test_101_install_local_postprocargs_success(
- self,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = b'0\0'
- build_time = '2020-09-01 14:30:00' # 1598970600
- install_time = '2020-09-01 15:30:00'
- 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.now.return_value = \
- datetime.datetime(2020, 9, 1, 15, 30, tzinfo=datetime.timezone.utc)
- with mock.patch('qubesadmin.tools.qvm_template.LOCK_FILE', '/tmp/test.lock'), \
- 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='/tmp',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- repo_files=[],
- releasever='4.1',
- 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)
- # 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
- mock_dl.assert_called_with(args, self.app,
- dl_list={}, version_selector=selector)
- # Package is extracted
- mock_extract.assert_called_with('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, [])
- 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')
- def test_102_install_local_badsig_fail(
- self,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename):
- mock_verify.return_value = None
- mock_time = mock.Mock(wraps=datetime.datetime)
- with mock.patch('qubesadmin.tools.qvm_template.LOCK_FILE', '/tmp/test.lock'), \
- 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='/tmp',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- repo_files=[],
- releasever='4.1',
- 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)
- # Check error message
- self.assertTrue('verification failed' in mock_err.getvalue())
- # 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, [])
- 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')
- def test_103_install_local_exists_fail(
- self,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename):
- 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('qubesadmin.tools.qvm_template.LOCK_FILE', '/tmp/test.lock'), \
- 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='/tmp',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- repo_files=[],
- releasever='4.1',
- 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)
- # Check warning message
- self.assertTrue('already installed' in mock_err.getvalue())
- # 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,
- dl_list={}, 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, [])
- 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')
- def test_104_install_local_badpkgname_fail(
- self,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename):
- 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('qubesadmin.tools.qvm_template.LOCK_FILE', '/tmp/test.lock'), \
- 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='/tmp',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- repo_files=[],
- releasever='4.1',
- 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)
- # Check error message
- self.assertTrue('Illegal package name' in mock_err.getvalue())
- # 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, [])
- 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')
- def test_106_install_local_badpath_fail(
- self,
- 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('qubesadmin.tools.qvm_template.LOCK_FILE', '/tmp/test.lock'), \
- 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='/tmp',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- repo_files=[],
- releasever='4.1',
- 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)
- # Check error message
- self.assertTrue(f"RPM file '{path}' not found" \
- in mock_err.getvalue())
- # 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, [])
- 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')
- def test_107_install_download_success(
- self,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = b'0\0'
- build_time = '2020-09-01 14:30:00' # 1598970600
- install_time = '2020-09-01 15:30:00'
- for key, val in [
- ('name', 'test-vm'),
- ('epoch', '2'),
- ('version', '4.1'),
- ('release', '2020'),
- ('reponame', 'qubes-templates-itl'),
- ('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_dl.return_value = {'test-vm': {
- 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'
- }}
- dl_list = {
- 'test-vm': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '4.1', '20200101'), 'qubes-templates-itl', 1048576)
- }
- mock_dl_list.return_value = dl_list
- mock_call.side_effect = self.add_new_vm_side_effect
- mock_time = mock.Mock(wraps=datetime.datetime)
- mock_time.now.return_value = \
- datetime.datetime(2020, 9, 1, 15, 30, tzinfo=datetime.timezone.utc)
- with mock.patch('qubesadmin.tools.qvm_template.LOCK_FILE', '/tmp/test.lock'), \
- mock.patch('datetime.datetime', new=mock_time), \
- mock.patch('tempfile.TemporaryDirectory') as mock_tmpdir, \
- mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- args = argparse.Namespace(
- templates='test-vm',
- keyring='/tmp/keyring.gpg',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- repo_files=[],
- releasever='4.1',
- yes=False,
- keep_cache=True,
- 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)
- # 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
- mock_dl.assert_called_with(args, self.app,
- dl_list=dl_list, version_selector=selector)
- # download already verify the package internally
- self.assertEqual(mock_verify.mock_calls, [])
- # Package is extracted
- mock_extract.assert_called_with('test-vm',
- '/var/cache/qvm-template/qubes-template-test-vm-1:4.1-20200101.rpm',
- '/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, [])
- self.assertAllCalled()
- def test_110_qrexec_payload_refresh_success(self):
- with tempfile.NamedTemporaryFile() as repo_conf1, \
- tempfile.NamedTemporaryFile() as repo_conf2:
- repo_str1 = \
- '''[qubes-templates-itl]
- name = Qubes Templates repository
- #baseurl = https://yum.qubes-os.org/r$releasever/templates-itl
- #baseurl = http://yum.qubesosfasa4zl44o4tws22di6kepyzfeqv3tg4e3ztknltfxqrymdad.onion/r$releasever/templates-itl
- metalink = https://yum.qubes-os.org/r$releasever/templates-itl/repodata/repomd.xml.metalink
- enabled = 1
- fastestmirror = 1
- metadata_expire = 7d
- gpgcheck = 1
- gpgkey = file:///etc/qubes/repo-templates/keys/RPM-GPG-KEY-qubes-$releasever-primary
- '''
- repo_str2 = \
- '''[qubes-templates-itl-testing]
- name = Qubes Templates repository
- #baseurl = https://yum.qubes-os.org/r$releasever/templates-itl-testing
- #baseurl = http://yum.qubesosfasa4zl44o4tws22di6kepyzfeqv3tg4e3ztknltfxqrymdad.onion/r$releasever/templates-itl-testing
- metalink = https://yum.qubes-os.org/r$releasever/templates-itl-testing/repodata/repomd.xml.metalink
- enabled = 0
- fastestmirror = 1
- gpgcheck = 1
- gpgkey = file:///etc/qubes/repo-templates/keys/RPM-GPG-KEY-qubes-$releasever-primary
- '''
- repo_conf1.write(repo_str1.encode())
- repo_conf1.flush()
- repo_conf2.write(repo_str2.encode())
- repo_conf2.flush()
- args = argparse.Namespace(
- enablerepo=['repo1', 'repo2'],
- disablerepo=['repo3', 'repo4', 'repo5'],
- repoid=[],
- releasever='4.1',
- repo_files=[repo_conf1.name, repo_conf2.name]
- )
- res = qubesadmin.tools.qvm_template.qrexec_payload(args, self.app,
- 'qubes-template-fedora-32', True)
- self.assertEqual(res,
- '''--enablerepo=repo1
- --enablerepo=repo2
- --disablerepo=repo3
- --disablerepo=repo4
- --disablerepo=repo5
- --refresh
- --releasever=4.1
- qubes-template-fedora-32
- ---
- ''' + repo_str1 + '\n' + repo_str2 + '\n')
- self.assertAllCalled()
- def test_111_qrexec_payload_norefresh_success(self):
- with tempfile.NamedTemporaryFile() as repo_conf1:
- repo_str1 = \
- '''[qubes-templates-itl]
- name = Qubes Templates repository
- #baseurl = https://yum.qubes-os.org/r$releasever/templates-itl
- #baseurl = http://yum.qubesosfasa4zl44o4tws22di6kepyzfeqv3tg4e3ztknltfxqrymdad.onion/r$releasever/templates-itl
- metalink = https://yum.qubes-os.org/r$releasever/templates-itl/repodata/repomd.xml.metalink
- enabled = 1
- fastestmirror = 1
- metadata_expire = 7d
- gpgcheck = 1
- gpgkey = file:///etc/qubes/repo-templates/keys/RPM-GPG-KEY-qubes-$releasever-primary
- '''
- repo_conf1.write(repo_str1.encode())
- repo_conf1.flush()
- args = argparse.Namespace(
- enablerepo=[],
- disablerepo=[],
- repoid=['repo1', 'repo2'],
- releasever='4.1',
- repo_files=[repo_conf1.name]
- )
- res = qubesadmin.tools.qvm_template.qrexec_payload(args, self.app,
- 'qubes-template-fedora-32', False)
- self.assertEqual(res,
- '''--repoid=repo1
- --repoid=repo2
- --releasever=4.1
- qubes-template-fedora-32
- ---
- ''' + repo_str1 + '\n')
- self.assertAllCalled()
- def test_112_qrexec_payload_specnewline_fail(self):
- with tempfile.NamedTemporaryFile() as repo_conf1:
- repo_str1 = \
- '''[qubes-templates-itl]
- name = Qubes Templates repository
- #baseurl = https://yum.qubes-os.org/r$releasever/templates-itl
- #baseurl = http://yum.qubesosfasa4zl44o4tws22di6kepyzfeqv3tg4e3ztknltfxqrymdad.onion/r$releasever/templates-itl
- metalink = https://yum.qubes-os.org/r$releasever/templates-itl/repodata/repomd.xml.metalink
- enabled = 1
- fastestmirror = 1
- metadata_expire = 7d
- gpgcheck = 1
- gpgkey = file:///etc/qubes/repo-templates/keys/RPM-GPG-KEY-qubes-$releasever-primary
- '''
- repo_conf1.write(repo_str1.encode())
- repo_conf1.flush()
- args = argparse.Namespace(
- enablerepo=[],
- disablerepo=[],
- repoid=['repo1', 'repo2'],
- releasever='4.1',
- repo_files=[repo_conf1.name]
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.qrexec_payload(args,
- self.app, 'qubes-template-fedora\n-32', False)
- # Check error message
- self.assertTrue('Malformed template name'
- in mock_err.getvalue())
- self.assertTrue("argument should not contain '\\n'"
- in mock_err.getvalue())
- self.assertAllCalled()
- def test_113_qrexec_payload_enablereponewline_fail(self):
- with tempfile.NamedTemporaryFile() as repo_conf1:
- repo_str1 = \
- '''[qubes-templates-itl]
- name = Qubes Templates repository
- #baseurl = https://yum.qubes-os.org/r$releasever/templates-itl
- #baseurl = http://yum.qubesosfasa4zl44o4tws22di6kepyzfeqv3tg4e3ztknltfxqrymdad.onion/r$releasever/templates-itl
- metalink = https://yum.qubes-os.org/r$releasever/templates-itl/repodata/repomd.xml.metalink
- enabled = 1
- fastestmirror = 1
- metadata_expire = 7d
- gpgcheck = 1
- gpgkey = file:///etc/qubes/repo-templates/keys/RPM-GPG-KEY-qubes-$releasever-primary
- '''
- repo_conf1.write(repo_str1.encode())
- repo_conf1.flush()
- args = argparse.Namespace(
- enablerepo=['repo\n0'],
- disablerepo=[],
- repoid=['repo1', 'repo2'],
- releasever='4.1',
- repo_files=[repo_conf1.name]
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.qrexec_payload(args,
- self.app, 'qubes-template-fedora-32', False)
- # Check error message
- self.assertTrue('Malformed --enablerepo'
- in mock_err.getvalue())
- self.assertTrue("argument should not contain '\\n'"
- in mock_err.getvalue())
- self.assertAllCalled()
- def test_114_qrexec_payload_disablereponewline_fail(self):
- with tempfile.NamedTemporaryFile() as repo_conf1:
- repo_str1 = \
- '''[qubes-templates-itl]
- name = Qubes Templates repository
- #baseurl = https://yum.qubes-os.org/r$releasever/templates-itl
- #baseurl = http://yum.qubesosfasa4zl44o4tws22di6kepyzfeqv3tg4e3ztknltfxqrymdad.onion/r$releasever/templates-itl
- metalink = https://yum.qubes-os.org/r$releasever/templates-itl/repodata/repomd.xml.metalink
- enabled = 1
- fastestmirror = 1
- metadata_expire = 7d
- gpgcheck = 1
- gpgkey = file:///etc/qubes/repo-templates/keys/RPM-GPG-KEY-qubes-$releasever-primary
- '''
- repo_conf1.write(repo_str1.encode())
- repo_conf1.flush()
- args = argparse.Namespace(
- enablerepo=[],
- disablerepo=['repo\n0'],
- repoid=['repo1', 'repo2'],
- releasever='4.1',
- repo_files=[repo_conf1.name]
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.qrexec_payload(args,
- self.app, 'qubes-template-fedora-32', False)
- # Check error message
- self.assertTrue('Malformed --disablerepo'
- in mock_err.getvalue())
- self.assertTrue("argument should not contain '\\n'"
- in mock_err.getvalue())
- self.assertAllCalled()
- def test_115_qrexec_payload_repoidnewline_fail(self):
- with tempfile.NamedTemporaryFile() as repo_conf1:
- repo_str1 = \
- '''[qubes-templates-itl]
- name = Qubes Templates repository
- #baseurl = https://yum.qubes-os.org/r$releasever/templates-itl
- #baseurl = http://yum.qubesosfasa4zl44o4tws22di6kepyzfeqv3tg4e3ztknltfxqrymdad.onion/r$releasever/templates-itl
- metalink = https://yum.qubes-os.org/r$releasever/templates-itl/repodata/repomd.xml.metalink
- enabled = 1
- fastestmirror = 1
- metadata_expire = 7d
- gpgcheck = 1
- gpgkey = file:///etc/qubes/repo-templates/keys/RPM-GPG-KEY-qubes-$releasever-primary
- '''
- repo_conf1.write(repo_str1.encode())
- repo_conf1.flush()
- args = argparse.Namespace(
- enablerepo=[],
- disablerepo=[],
- repoid=['repo\n1', 'repo2'],
- releasever='4.1',
- repo_files=[repo_conf1.name]
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.qrexec_payload(args,
- self.app, 'qubes-template-fedora-32', False)
- # Check error message
- self.assertTrue('Malformed --repoid'
- in mock_err.getvalue())
- self.assertTrue("argument should not contain '\\n'"
- in mock_err.getvalue())
- self.assertAllCalled()
- def test_116_qrexec_payload_releasevernewline_fail(self):
- with tempfile.NamedTemporaryFile() as repo_conf1:
- repo_str1 = \
- '''[qubes-templates-itl]
- name = Qubes Templates repository
- #baseurl = https://yum.qubes-os.org/r$releasever/templates-itl
- #baseurl = http://yum.qubesosfasa4zl44o4tws22di6kepyzfeqv3tg4e3ztknltfxqrymdad.onion/r$releasever/templates-itl
- metalink = https://yum.qubes-os.org/r$releasever/templates-itl/repodata/repomd.xml.metalink
- enabled = 1
- fastestmirror = 1
- metadata_expire = 7d
- gpgcheck = 1
- gpgkey = file:///etc/qubes/repo-templates/keys/RPM-GPG-KEY-qubes-$releasever-primary
- '''
- repo_conf1.write(repo_str1.encode())
- repo_conf1.flush()
- args = argparse.Namespace(
- enablerepo=[],
- disablerepo=[],
- repoid=['repo1', 'repo2'],
- releasever='4\n.1',
- repo_files=[repo_conf1.name]
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.qrexec_payload(args,
- self.app, 'qubes-template-fedora-32', False)
- # Check error message
- self.assertTrue('Malformed --releasever'
- in mock_err.getvalue())
- self.assertTrue("argument should not contain '\\n'"
- in mock_err.getvalue())
- self.assertAllCalled()
- def test_117_qrexec_payload_specdash_fail(self):
- with tempfile.NamedTemporaryFile() as repo_conf1:
- repo_str1 = \
- '''[qubes-templates-itl]
- name = Qubes Templates repository
- #baseurl = https://yum.qubes-os.org/r$releasever/templates-itl
- #baseurl = http://yum.qubesosfasa4zl44o4tws22di6kepyzfeqv3tg4e3ztknltfxqrymdad.onion/r$releasever/templates-itl
- metalink = https://yum.qubes-os.org/r$releasever/templates-itl/repodata/repomd.xml.metalink
- enabled = 1
- fastestmirror = 1
- metadata_expire = 7d
- gpgcheck = 1
- gpgkey = file:///etc/qubes/repo-templates/keys/RPM-GPG-KEY-qubes-$releasever-primary
- '''
- repo_conf1.write(repo_str1.encode())
- repo_conf1.flush()
- args = argparse.Namespace(
- enablerepo=[],
- disablerepo=[],
- repoid=['repo1', 'repo2'],
- releasever='4.1',
- repo_files=[repo_conf1.name]
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.qrexec_payload(args,
- self.app, '---', False)
- # Check error message
- self.assertTrue('Malformed template name'
- in mock_err.getvalue())
- self.assertTrue("argument should not be '---'"
- in mock_err.getvalue())
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_120_qrexec_repoquery_success(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template\n for fedora-32\n|
- qubes-template-fedora-32|1|4.2|20200201|qubes-templates-itl-testing|2048576|2020-02-23 04:56|GPLv2|https://qubes-os.org/?|Qubes template for fedora-32 v2|Qubes template\n for fedora-32 v2\n|
- '''
- res = qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(res, [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '0',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-32',
- 'Qubes template\n for fedora-32\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '1',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for fedora-32 v2',
- 'Qubes template\n for fedora-32 v2\n'
- )
- ])
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_121_qrexec_repoquery_refresh_success(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template\n for fedora-32\n|
- qubes-template-fedora-32|1|4.2|20200201|qubes-templates-itl-testing|2048576|2020-02-23 04:56|GPLv2|https://qubes-os.org/?|Qubes template for fedora-32 v2|Qubes template\n for fedora-32 v2\n|
- '''
- res = qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32', True)
- self.assertEqual(res, [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '0',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-32',
- 'Qubes template\n for fedora-32\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '1',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for fedora-32 v2',
- 'Qubes template\n for fedora-32 v2\n'
- )
- ])
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', True)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_122_qrexec_repoquery_ignorenonspec_success(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-debian-10|1|4.2|20200201|qubes-templates-itl-testing|2048576|2020-02-23 04:56|GPLv2|https://qubes-os.org/?|Qubes template for debian-10|Qubes template for debian-10\n|
- qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template for fedora-32\n|
- '''
- res = qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(res, [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '0',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-32',
- 'Qubes template for fedora-32\n'
- )
- ])
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_123_qrexec_repoquery_ignorebadname_success(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''template-fedora-32|1|4.2|20200201|qubes-templates-itl-testing|2048576|2020-02-23 04:56|GPLv2|https://qubes-os.org/?|Qubes template for fedora-32 v2|Qubes template\n for fedora-32 v2\n|
- qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template for fedora-32\n|
- '''
- res = qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(res, [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '0',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-32',
- 'Qubes template for fedora-32\n'
- )
- ])
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_124_qrexec_repoquery_searchfail_fail(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- with mock.patch('qubesadmin.tests.TestProcess.wait') \
- as mock_wait:
- mock_wait.return_value = 1
- with self.assertRaises(ConnectionError):
- qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_125_qrexec_repoquery_extrafield_fail(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-fedora-32|1|4.2|20200201|qubes-templates-itl-testing|2048576|2020-02-23 04:56|GPLv2|https://qubes-os.org/?|Qubes template for fedora-32 v2|Extra field|Qubes template\n for fedora-32 v2\n|
- qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template for fedora-32\n|
- '''
- with self.assertRaisesRegex(ConnectionError,
- "unexpected data format"):
- qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_125_qrexec_repoquery_missingfield_fail(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-fedora-32|1|4.2|20200201|qubes-templates-itl-testing|2048576|2020-02-23 04:56|GPLv2|Qubes template for fedora-32 v2|Qubes template\n for fedora-32 v2\n|
- qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template for fedora-32\n|
- '''
- with self.assertRaisesRegex(ConnectionError,
- "unexpected data format"):
- qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_126_qrexec_repoquery_badfieldname_fail(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-fedora-(32)|1|4.2|20200201|qubes-templates-itl-testing|2048576|2020-02-23 04:56|GPLv2|https://qubes-os.org/?|Qubes template for fedora-32 v2|Qubes template\n for fedora-32 v2\n|
- qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template for fedora-32\n|
- '''
- with self.assertRaisesRegex(ConnectionError,
- "unexpected data format"):
- qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_126_qrexec_repoquery_badfieldepoch_fail(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-fedora-32|!1|4.2|20200201|qubes-templates-itl-testing|2048576|2020-02-23 04:56|GPLv2|https://qubes-os.org/?|Qubes template for fedora-32 v2|Qubes template\n for fedora-32 v2\n|
- qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template for fedora-32\n|
- '''
- with self.assertRaisesRegex(ConnectionError,
- "unexpected data format"):
- qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_126_qrexec_repoquery_badfieldreponame_fail(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-fedora-32|1|4.2|20200201|qubes-templates-itl-<testing>|2048576|2020-02-23 04:56|GPLv2|https://qubes-os.org/?|Qubes template for fedora-32 v2|Qubes template\n for fedora-32 v2\n|
- qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template for fedora-32\n|
- '''
- with self.assertRaisesRegex(ConnectionError,
- "unexpected data format"):
- qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_126_qrexec_repoquery_badfielddlsize_fail(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-fedora-32|1|4.2|20200201|qubes-templates-itl-testing|2048a576|2020-02-23 04:56|GPLv2|https://qubes-os.org/?|Qubes template for fedora-32 v2|Qubes template\n for fedora-32 v2\n|
- qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template for fedora-32\n|
- '''
- with self.assertRaisesRegex(ConnectionError,
- "unexpected data format"):
- qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_126_qrexec_repoquery_badfielddate_fail(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-fedora-32|1|4.2|20200201|qubes-templates-itl-testing|2048576|2020-02-23|GPLv2|https://qubes-os.org/?|Qubes template for fedora-32 v2|Qubes template\n for fedora-32 v2\n|
- qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template for fedora-32\n|
- '''
- with self.assertRaisesRegex(ConnectionError,
- "unexpected data format"):
- qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_payload')
- def test_126_qrexec_repoquery_license_fail(self, mock_payload):
- args = argparse.Namespace(updatevm='test-vm')
- mock_payload.return_value = 'str1\nstr2'
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_service_calls[
- ('test-vm', 'qubes.TemplateSearch')] = \
- b'''qubes-template-fedora-32|1|4.2|20200201|qubes-templates-itl-testing|2048576|2020-02-23 04:56|GPLv2:)|https://qubes-os.org/?|Qubes template for fedora-32 v2|Qubes template\n for fedora-32 v2\n|
- qubes-template-fedora-32|0|4.1|20200101|qubes-templates-itl|1048576|2020-01-23 04:56|GPL|https://qubes-os.org|Qubes template for fedora-32|Qubes template for fedora-32\n|
- '''
- with self.assertRaisesRegex(ConnectionError,
- "unexpected data format"):
- qubesadmin.tools.qvm_template.qrexec_repoquery(args, self.app,
- 'qubes-template-fedora-32')
- self.assertEqual(self.app.service_calls, [
- ('test-vm', 'qubes.TemplateSearch',
- {'filter_esc': True, 'stdout': subprocess.PIPE}),
- ('test-vm', 'qubes.TemplateSearch', b'str1\nstr2')
- ])
- self.assertEqual(mock_payload.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32', False)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_130_get_dl_list_latest_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-32',
- 'Qubes template\n for fedora-32\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '0',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for fedora-32 v2',
- 'Qubes template\n for fedora-32 v2\n'
- )
- ]
- args = argparse.Namespace(
- templates=['some.local.file.rpm', 'fedora-32']
- )
- ret = qubesadmin.tools.qvm_template.get_dl_list(args, self.app)
- self.assertEqual(ret, {
- 'fedora-32': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '4.1', '20200101'), 'qubes-templates-itl', 1048576)
- })
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_131_get_dl_list_latest_notfound_fail(self, mock_query):
- mock_query.return_value = []
- args = argparse.Namespace(
- templates=['some.local.file.rpm', 'fedora-31']
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.get_dl_list(args, self.app)
- self.assertTrue('not found' in mock_err.getvalue())
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-31')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_132_get_dl_list_multimerge0_success(self, mock_query):
- counter = 0
- def f(*args):
- nonlocal counter
- counter += 1
- if counter == 1:
- return [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '0',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for fedora-32 v2',
- 'Qubes template\n for fedora-32 v2\n'
- )
- ]
- return [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-32',
- 'Qubes template\n for fedora-32\n'
- )
- ]
- mock_query.side_effect = f
- args = argparse.Namespace(
- templates=['some.local.file.rpm', 'fedora-32:0', 'fedora-32:1']
- )
- ret = qubesadmin.tools.qvm_template.get_dl_list(args, self.app)
- self.assertEqual(ret, {
- 'fedora-32': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '4.1', '20200101'), 'qubes-templates-itl', 1048576)
- })
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32:0'),
- mock.call(args, self.app, 'qubes-template-fedora-32:1')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_132_get_dl_list_multimerge1_success(self, mock_query):
- counter = 0
- def f(*args):
- nonlocal counter
- counter += 1
- if counter == 1:
- return [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '2',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for fedora-32 v2',
- 'Qubes template\n for fedora-32 v2\n'
- )
- ]
- return [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-32',
- 'Qubes template\n for fedora-32\n'
- )
- ]
- mock_query.side_effect = f
- args = argparse.Namespace(
- templates=['some.local.file.rpm', 'fedora-32:2', 'fedora-32:1']
- )
- ret = qubesadmin.tools.qvm_template.get_dl_list(args, self.app)
- self.assertEqual(ret, {
- 'fedora-32': qubesadmin.tools.qvm_template.DlEntry(
- ('2', '4.2', '20200201'),
- 'qubes-templates-itl-testing',
- 2048576)
- })
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32:2'),
- mock.call(args, self.app, 'qubes-template-fedora-32:1')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_133_get_dl_list_reinstall_success(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-name',
- None)] = b'0\0test-vm'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-epoch',
- None)] = b'0\x000'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-version',
- None)] = b'0\x004.2'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-release',
- None)] = b'0\x0020200201'
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for test-vm v2',
- 'Qubes template\n for test-vm v2\n'
- )
- ]
- args = argparse.Namespace(
- templates=['some.local.file.rpm', 'test-vm']
- )
- ret = qubesadmin.tools.qvm_template.get_dl_list(args, self.app,
- qubesadmin.tools.qvm_template.VersionSelector.REINSTALL)
- self.assertEqual(ret, {
- 'test-vm': qubesadmin.tools.qvm_template.DlEntry(
- ('0', '4.2', '20200201'),
- 'qubes-templates-itl-testing',
- 2048576
- )
- })
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-test-vm')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_134_get_dl_list_reinstall_nolocal_fail(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00'
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for test-vm v2',
- 'Qubes template\n for test-vm v2\n'
- )
- ]
- args = argparse.Namespace(templates=['test-vm'])
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.get_dl_list(args, self.app,
- qubesadmin.tools.qvm_template.VersionSelector.REINSTALL)
- self.assertTrue('not already installed' in mock_err.getvalue())
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-test-vm')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_135_get_dl_list_reinstall_nonmanaged_fail(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for test-vm v2',
- 'Qubes template\n for test-vm v2\n'
- )
- ]
- args = argparse.Namespace(templates=['test-vm'])
- def qubesd_call(dest, method,
- arg=None, payload=None, payload_stream=None,
- orig_func=self.app.qubesd_call):
- if method == 'admin.vm.feature.Get':
- raise KeyError
- return orig_func(dest, method, arg, payload, payload_stream)
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err, \
- mock.patch.object(self.app, 'qubesd_call') as mock_call:
- mock_call.side_effect = qubesd_call
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.get_dl_list(args, self.app,
- qubesadmin.tools.qvm_template.VersionSelector.REINSTALL)
- self.assertTrue('not managed' in mock_err.getvalue())
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-test-vm')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_135_get_dl_list_reinstall_nonmanagednoname_fail(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-name',
- None)] = b'0\0test-vm-2'
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for test-vm v2',
- 'Qubes template\n for test-vm v2\n'
- )
- ]
- args = argparse.Namespace(templates=['test-vm'])
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.get_dl_list(args, self.app,
- qubesadmin.tools.qvm_template.VersionSelector.REINSTALL)
- self.assertTrue('not managed' in mock_err.getvalue())
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-test-vm')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_136_get_dl_list_downgrade_success(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-name',
- None)] = b'0\0test-vm'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-epoch',
- None)] = b'0\x000'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-version',
- None)] = b'0\x004.3'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-release',
- None)] = b'0\x0020200201'
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for test-vm v2',
- 'Qubes template\n for test-vm v2\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- )
- ]
- args = argparse.Namespace(templates=['test-vm'])
- ret = qubesadmin.tools.qvm_template.get_dl_list(args, self.app,
- qubesadmin.tools.qvm_template.VersionSelector.LATEST_LOWER)
- self.assertEqual(ret, {
- 'test-vm': qubesadmin.tools.qvm_template.DlEntry(
- ('0', '4.2', '20200201'),
- 'qubes-templates-itl-testing',
- 2048576
- )
- })
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-test-vm')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_137_get_dl_list_downgrade_nonmanaged_fail(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-name',
- None)] = b'0\0test-vm-2'
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for test-vm v2',
- 'Qubes template\n for test-vm v2\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- )
- ]
- args = argparse.Namespace(templates=['test-vm'])
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.get_dl_list(args, self.app,
- qubesadmin.tools.qvm_template.VersionSelector.REINSTALL)
- self.assertTrue('not managed' in mock_err.getvalue())
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-test-vm')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_138_get_dl_list_downgrade_notfound_skip(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-name',
- None)] = b'0\0test-vm'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-epoch',
- None)] = b'0\x000'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-version',
- None)] = b'0\x004.3'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-release',
- None)] = b'0\x0020200201'
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- )
- ]
- args = argparse.Namespace(templates=['test-vm'])
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- ret = qubesadmin.tools.qvm_template.get_dl_list(args, self.app,
- qubesadmin.tools.qvm_template.VersionSelector.LATEST_LOWER)
- self.assertTrue('lowest version' in mock_err.getvalue())
- self.assertEqual(ret, {})
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-test-vm')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_139_get_dl_list_upgrade_success(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-name',
- None)] = b'0\0test-vm'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-epoch',
- None)] = b'0\x000'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-version',
- None)] = b'0\x004.3'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-release',
- None)] = b'0\x0020200201'
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- )
- ]
- args = argparse.Namespace(templates=['test-vm'])
- ret = qubesadmin.tools.qvm_template.get_dl_list(args, self.app,
- qubesadmin.tools.qvm_template.VersionSelector.LATEST_HIGHER)
- self.assertEqual(ret, {
- 'test-vm': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '4.1', '20200101'), 'qubes-templates-itl', 1048576
- )
- })
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-test-vm')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_140_get_dl_list_downgrade_notfound_skip(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-name',
- None)] = b'0\0test-vm'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-epoch',
- None)] = b'0\x000'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-version',
- None)] = b'0\x004.3'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-release',
- None)] = b'0\x0020200201'
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- )
- ]
- args = argparse.Namespace(templates=['test-vm'])
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- ret = qubesadmin.tools.qvm_template.get_dl_list(args, self.app,
- qubesadmin.tools.qvm_template.VersionSelector.LATEST_HIGHER)
- self.assertTrue('highest version' in mock_err.getvalue())
- self.assertEqual(ret, {})
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-test-vm')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_141_get_dl_list_reinstall_notfound_fail(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-name',
- None)] = b'0\0test-vm'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-epoch',
- None)] = b'0\x000'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-version',
- None)] = b'0\x004.3'
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-release',
- None)] = b'0\x0020200201'
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for test-vm\n'
- )
- ]
- args = argparse.Namespace(templates=['test-vm'])
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.get_dl_list(args, self.app,
- qubesadmin.tools.qvm_template.VersionSelector.REINSTALL)
- self.assertTrue('Same version' in mock_err.getvalue())
- self.assertTrue('not found' in mock_err.getvalue())
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'qubes-template-test-vm')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_150_list_templates_installed_success(self, mock_query):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n' \
- b'test-vm-2 class=TemplateVM state=Halted\n' \
- b'non-spec class=TemplateVM state=Halted\n'
- build_time = '2020-09-01 14:30:00' # 1598970600
- install_time = '2020-09-01 15:30:00'
- 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.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- for key, val in [('name', 'test-vm-2-not-managed')]:
- self.app.expected_calls[(
- 'test-vm-2',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- for key, val in [
- ('name', 'non-spec'),
- ('epoch', '0'),
- ('version', '4.3'),
- ('release', '20200201')]:
- self.app.expected_calls[(
- 'non-spec',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- args = argparse.Namespace(
- all=False,
- installed=True,
- available=False,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=False,
- templates=['test-vm*']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out, \
- mock.patch.object(self.app.domains['test-vm'],
- 'get_disk_utilization') as mock_disk:
- mock_disk.return_value = 1234321
- qubesadmin.tools.qvm_template.list_templates(
- args, self.app, 'list')
- self.assertEqual(mock_out.getvalue(),
- '''Installed Templates
- [('test-vm', '2:4.1-2020', '@commandline')]
- ''')
- self.assertEqual(mock_disk.mock_calls, [mock.call()])
- self.assertEqual(mock_query.mock_calls, [])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_151_list_templates_available_success(self, mock_query):
- counter = 0
- def f(*args):
- nonlocal counter
- counter += 1
- if counter == 1:
- return [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-32',
- '0',
- '4.2',
- '20200201',
- 'qubes-templates-itl-testing',
- 2048576,
- datetime.datetime(2020, 2, 23, 4, 56),
- 'GPLv2',
- 'https://qubes-os.org/?',
- 'Qubes template for fedora-32 v2',
- 'Qubes template\n for fedora-32 v2\n'
- )
- ]
- return [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-31',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- )
- ]
- mock_query.side_effect = f
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=True,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=False,
- templates=['fedora-32', 'fedora-31']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out:
- qubesadmin.tools.qvm_template.list_templates(
- args, self.app, 'list')
- # Order not determinstic because of sets
- expected = [
- ('fedora-31', '1:4.1-20200101', 'qubes-templates-itl'),
- ('fedora-32', '0:4.2-20200201', 'qubes-templates-itl-testing')
- ]
- self.assertTrue(mock_out.getvalue() == \
- f'''Available Templates
- {str([expected[1], expected[0]])}
- ''' \
- or mock_out.getvalue() == \
- f'''Available Templates
- {str([expected[0], expected[1]])}
- ''')
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'fedora-32'),
- mock.call(args, self.app, 'fedora-31')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_151_list_templates_available_all_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-31',
- '1',
- '4.1',
- '20190101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2019, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'fedora-31',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- ),
- ]
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=True,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=False,
- templates=[]
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out:
- qubesadmin.tools.qvm_template.list_templates(
- args, self.app, 'list')
- self.assertEqual(mock_out.getvalue(),
- '''Available Templates
- [('fedora-31', '1:4.1-20190101', 'qubes-templates-itl'), ('fedora-31', '1:4.1-20200101', 'qubes-templates-itl')]
- ''')
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_151_list_templates_available_only_latest_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'fedora-31',
- '1',
- '4.1',
- '20190101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2019, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'fedora-31',
- '1',
- '4.1',
- '20200101',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 1, 23, 4, 56),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- ),
- ]
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=True,
- extras=False,
- upgrades=False,
- all_versions=False,
- machine_readable=False,
- machine_readable_json=False,
- templates=[]
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out:
- qubesadmin.tools.qvm_template.list_templates(
- args, self.app, 'list')
- self.assertEqual(mock_out.getvalue(),
- '''Available Templates
- [('fedora-31', '1:4.1-20200101', 'qubes-templates-itl')]
- ''')
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_152_list_templates_extras_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- )
- ]
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n' \
- b'test-vm-2 class=TemplateVM state=Halted\n' \
- b'test-vm-3 class=TemplateVM state=Halted\n' \
- b'non-spec class=TemplateVM state=Halted\n'
- for key, val in [('name', 'test-vm')]:
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- for key, val in [
- ('name', 'test-vm-2'),
- ('epoch', '1'),
- ('version', '4.0'),
- ('release', '2019'),
- ('reponame', 'qubes-template-itl'),
- ('buildtime', '2020-09-02 14:30:00'),
- ('installtime', '2020-09-02 15:30:00'),
- ('license', 'GPLv2'),
- ('url', 'https://qubes-os.org/?'),
- ('summary', 'Summary2'),
- ('description', 'Desc|desc|2')]:
- self.app.expected_calls[(
- 'test-vm-2',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- for key, val in [('name', 'test-vm-3-non-managed')]:
- self.app.expected_calls[(
- 'test-vm-3',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- for key, val in [
- ('name', 'non-spec'),
- ('epoch', '1'),
- ('version', '4.0'),
- ('release', '2019')]:
- self.app.expected_calls[(
- 'non-spec',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=False,
- extras=True,
- upgrades=False,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=False,
- templates=['test-vm*']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out, \
- mock.patch.object(self.app.domains['test-vm-2'],
- 'get_disk_utilization') as mock_disk:
- mock_disk.return_value = 1234321
- qubesadmin.tools.qvm_template.list_templates(
- args, self.app, 'list')
- self.assertEqual(mock_out.getvalue(),
- '''Extra Templates
- [('test-vm-2', '1:4.0-2019', 'qubes-template-itl')]
- ''')
- self.assertEqual(mock_disk.mock_calls, [mock.call()])
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'test-vm*')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_153_list_templates_upgrades_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm-3',
- '0',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- )
- ]
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n' \
- b'test-vm-2 class=TemplateVM state=Halted\n' \
- b'test-vm-3 class=TemplateVM state=Halted\n'
- for key, val in [
- ('name', 'test-vm'),
- ('epoch', '1'),
- ('version', '4.0'),
- ('release', '2019')]:
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- for key, val in [
- ('name', 'test-vm-2'),
- ('epoch', '1'),
- ('version', '4.0'),
- ('release', '2019')]:
- self.app.expected_calls[(
- 'test-vm-2',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- for key, val in [('name', 'test-vm-3-non-managed')]:
- self.app.expected_calls[(
- 'test-vm-3',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=False,
- extras=False,
- upgrades=True,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=False,
- templates=['test-vm*']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out, \
- mock.patch.object(self.app.domains['test-vm-2'],
- 'get_disk_utilization') as mock_disk:
- mock_disk.return_value = 1234321
- qubesadmin.tools.qvm_template.list_templates(
- args, self.app, 'list')
- self.assertEqual(mock_out.getvalue(),
- '''Available Upgrades
- [('test-vm', '2:4.1-2020', 'qubes-templates-itl')]
- ''')
- self.assertEqual(mock_disk.mock_calls, [])
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'test-vm*')
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def __test_list_templates_all_success(self, operation,
- args, expected, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- )
- ]
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm-2 class=TemplateVM state=Halted\n'
- for key, val in [
- ('name', 'test-vm-2'),
- ('epoch', '1'),
- ('version', '4.0'),
- ('release', '2019'),
- ('reponame', '@commandline'),
- ('buildtime', '2020-09-02 14:30:00'),
- ('installtime', '2020-09-02 15:30:00'),
- ('license', 'GPL'),
- ('url', 'https://qubes-os.org'),
- ('summary', 'Summary'),
- ('description', 'Desc|desc')]:
- self.app.expected_calls[(
- 'test-vm-2',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out, \
- mock.patch.object(self.app.domains['test-vm-2'],
- 'get_disk_utilization') as mock_disk:
- mock_disk.return_value = 1234321
- qubesadmin.tools.qvm_template.list_templates(
- args, self.app, operation)
- self.assertEqual(mock_out.getvalue(), expected)
- self.assertEqual(mock_disk.mock_calls, [mock.call()])
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app, 'test-vm*')
- ])
- self.assertAllCalled()
- def test_154_list_templates_all_success(self):
- args = argparse.Namespace(
- all=True,
- installed=False,
- available=False,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=False,
- templates=['test-vm*']
- )
- expected = \
- '''Installed Templates
- [('test-vm-2', '1:4.0-2019', '@commandline')]
- Available Templates
- [('test-vm', '2:4.1-2020', 'qubes-templates-itl')]
- '''
- self.__test_list_templates_all_success('list', args, expected)
- def test_155_list_templates_all_implicit_success(self):
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=False,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=False,
- templates=['test-vm*']
- )
- expected = \
- '''Installed Templates
- [('test-vm-2', '1:4.0-2019', '@commandline')]
- Available Templates
- [('test-vm', '2:4.1-2020', 'qubes-templates-itl')]
- '''
- self.__test_list_templates_all_success('list', args, expected)
- def test_156_list_templates_info_all_success(self):
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=False,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=False,
- templates=['test-vm*']
- )
- expected = \
- '''Installed Templates
- [('Name', ':', 'test-vm-2'), ('Epoch', ':', '1'), ('Version', ':', '4.0'), ('Release', ':', '2019'), ('Size', ':', '1.2 MiB'), ('Repository', ':', '@commandline'), ('Buildtime', ':', '2020-09-02 14:30:00'), ('Install time', ':', '2020-09-02 15:30:00'), ('URL', ':', 'https://qubes-os.org'), ('License', ':', 'GPL'), ('Summary', ':', 'Summary'), ('Description', ':', 'Desc'), ('', ':', 'desc'), (' ', ' ', ' ')]
- Available Templates
- [('Name', ':', 'test-vm'), ('Epoch', ':', '2'), ('Version', ':', '4.1'), ('Release', ':', '2020'), ('Size', ':', '1.0 MiB'), ('Repository', ':', 'qubes-templates-itl'), ('Buildtime', ':', '2020-09-01 14:30:00+00:00'), ('URL', ':', 'https://qubes-os.org'), ('License', ':', 'GPL'), ('Summary', ':', 'Qubes template for fedora-31'), ('Description', ':', 'Qubes template'), ('', ':', ' for fedora-31'), (' ', ' ', ' ')]
- '''
- self.__test_list_templates_all_success('info', args, expected)
- def test_157_list_templates_list_all_machinereadable_success(self):
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=False,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=True,
- machine_readable_json=False,
- templates=['test-vm*']
- )
- expected = \
- '''installed|test-vm-2|1:4.0-2019|@commandline
- available|test-vm|2:4.1-2020|qubes-templates-itl
- '''
- self.__test_list_templates_all_success('list', args, expected)
- def test_158_list_templates_info_all_machinereadable_success(self):
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=False,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=True,
- machine_readable_json=False,
- templates=['test-vm*']
- )
- expected = \
- '''installed|test-vm-2|1|4.0|2019|@commandline|1234321|2020-09-02 14:30:00|2020-09-02 15:30:00|GPL|https://qubes-os.org|Summary|Desc|desc
- available|test-vm|2|4.1|2020|qubes-templates-itl|1048576|2020-09-01 14:30:00||GPL|https://qubes-os.org|Qubes template for fedora-31|Qubes template| for fedora-31|
- '''
- self.__test_list_templates_all_success('info', args, expected)
- def test_159_list_templates_list_all_machinereadablejson_success(self):
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=False,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=True,
- templates=['test-vm*']
- )
- expected = \
- '''{"installed": [{"name": "test-vm-2", "evr": "1:4.0-2019", "reponame": "@commandline"}], "available": [{"name": "test-vm", "evr": "2:4.1-2020", "reponame": "qubes-templates-itl"}]}
- '''
- self.__test_list_templates_all_success('list', args, expected)
- def test_160_list_templates_info_all_machinereadablejson_success(self):
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=False,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=True,
- templates=['test-vm*']
- )
- expected = \
- r'''{"installed": [{"name": "test-vm-2", "epoch": "1", "version": "4.0", "release": "2019", "reponame": "@commandline", "size": "1234321", "buildtime": "2020-09-02 14:30:00", "installtime": "2020-09-02 15:30:00", "license": "GPL", "url": "https://qubes-os.org", "summary": "Summary", "description": "Desc\ndesc"}], "available": [{"name": "test-vm", "epoch": "2", "version": "4.1", "release": "2020", "reponame": "qubes-templates-itl", "size": "1048576", "buildtime": "2020-09-01 14:30:00", "installtime": "", "license": "GPL", "url": "https://qubes-os.org", "summary": "Qubes template for fedora-31", "description": "Qubes template\n for fedora-31\n"}]}
- '''
- self.__test_list_templates_all_success('info', args, expected)
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_161_list_templates_noresults_fail(self, mock_query):
- mock_query.return_value = []
- args = argparse.Namespace(
- all=False,
- installed=False,
- available=True,
- extras=False,
- upgrades=False,
- all_versions=True,
- machine_readable=False,
- machine_readable_json=False,
- templates=[]
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.list_templates(
- args, self.app, 'list')
- self.assertTrue('No matching templates' in mock_err.getvalue())
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_170_search_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '0',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Older Qubes template for fedora-31',
- 'Older Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'should-not-match-3',
- '0',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org/test-vm',
- 'Qubes template for fedora-31',
- 'test-vm Qubes template\n for fedora-31\n'
- )
- ]
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm-2 class=TemplateVM state=Halted\n'
- for key, val in [
- ('name', 'test-vm-2'),
- ('epoch', '1'),
- ('version', '4.0'),
- ('release', '2019'),
- ('reponame', '@commandline'),
- ('buildtime', '2020-09-02 14:30:00'),
- ('license', 'GPL'),
- ('url', 'https://qubes-os.org'),
- ('summary', 'Summary'),
- ('description', 'Desc|desc')]:
- self.app.expected_calls[(
- 'test-vm-2',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- args = argparse.Namespace(
- all=False,
- templates=['test-vm']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out, \
- mock.patch.object(self.app.domains['test-vm-2'],
- 'get_disk_utilization') as mock_disk:
- mock_disk.return_value = 1234321
- qubesadmin.tools.qvm_template.search(args, self.app)
- self.assertEqual(mock_out.getvalue(),
- '''=== Name Exactly Matched: test-vm ===
- test-vm : Qubes template for fedora-31
- === Name Matched: test-vm ===
- test-vm-2 : Summary
- ''')
- self.assertEqual(mock_disk.mock_calls, [mock.call()])
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_171_search_summary_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-template',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm :)',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-template-exact',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'test-vm',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm-2',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for test-vm-2',
- 'Qubes template\n for fedora-31\n'
- ),
- ]
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00'
- args = argparse.Namespace(
- all=False,
- templates=['test-vm']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out:
- qubesadmin.tools.qvm_template.search(args, self.app)
- self.assertEqual(mock_out.getvalue(),
- '''=== Name & Summary Matched: test-vm ===
- test-vm : Qubes template for test-vm
- test-vm-2 : Qubes template for test-vm-2
- === Summary Matched: test-vm ===
- test-template : Qubes template for test-vm :)
- === Summary Exactly Matched: test-vm ===
- test-template-exact : test-vm
- ''')
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_172_search_namesummaryexact_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-template-exact',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'test-vm',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'test-vm',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm-2',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'test-vm',
- 'Qubes template\n for fedora-31\n'
- )
- ]
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00'
- args = argparse.Namespace(
- all=False,
- templates=['test-vm']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out:
- qubesadmin.tools.qvm_template.search(args, self.app)
- self.assertEqual(mock_out.getvalue(),
- '''=== Name & Summary Exactly Matched: test-vm ===
- test-vm : test-vm
- === Name & Summary Matched: test-vm ===
- test-vm-2 : test-vm
- === Summary Exactly Matched: test-vm ===
- test-template-exact : test-vm
- ''')
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_173_search_multiquery_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-template-exact',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'test-vm',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'test-vm',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'should-not-match',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Summary',
- 'test-vm Qubes template\n for fedora-31\n'
- )
- ]
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00'
- args = argparse.Namespace(
- all=False,
- templates=['test-vm', 'test-template']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out:
- qubesadmin.tools.qvm_template.search(args, self.app)
- self.assertEqual(mock_out.getvalue(),
- '''=== Name & Summary Matched: test-template, test-vm ===
- test-template-exact : test-vm
- ''')
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_174_search_multiquery_exact_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'summary',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'summary',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'test-vm Summary',
- 'Qubes template\n for fedora-31\n'
- )
- ]
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00'
- args = argparse.Namespace(
- all=False,
- templates=['test-vm', 'summary']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out:
- qubesadmin.tools.qvm_template.search(args, self.app)
- self.assertEqual(mock_out.getvalue(),
- '''=== Name & Summary Matched: summary, test-vm ===
- summary : test-vm Summary
- === Name & Summary Exactly Matched: summary, test-vm ===
- test-vm : summary
- ''')
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_175_search_all_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org/keyword-url',
- 'summary',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm-exact',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'test-vm Summary',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm-exac2',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'test-vm-exac2',
- 'test-vm Summary',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'test-vm-2',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'test-vm Summary',
- 'keyword-desc'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'should-not-match',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Summary',
- 'Description'
- )
- ]
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00'
- args = argparse.Namespace(
- all=True,
- templates=['test-vm-exact', 'test-vm-exac2',
- 'keyword-url', 'keyword-desc']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out:
- qubesadmin.tools.qvm_template.search(args, self.app)
- self.assertEqual(mock_out.getvalue(),
- '''=== Name & URL Exactly Matched: test-vm-exac2 ===
- test-vm-exac2 : test-vm Summary
- === Name Exactly Matched: test-vm-exact ===
- test-vm-exact : test-vm Summary
- === Description Exactly Matched: keyword-desc ===
- test-vm-2 : test-vm Summary
- === URL Matched: keyword-url ===
- test-vm : summary
- ''')
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_repoquery')
- def test_176_search_wildcard_success(self, mock_query):
- mock_query.return_value = [
- qubesadmin.tools.qvm_template.Template(
- 'test-vm',
- '2',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org',
- 'Qubes template for fedora-31',
- 'Qubes template\n for fedora-31\n'
- ),
- qubesadmin.tools.qvm_template.Template(
- 'should-not-match-3',
- '0',
- '4.1',
- '2020',
- 'qubes-templates-itl',
- 1048576,
- datetime.datetime(2020, 9, 1, 14, 30,
- tzinfo=datetime.timezone.utc),
- 'GPL',
- 'https://qubes-os.org/test-vm',
- 'Qubes template for fedora-31',
- 'test-vm Qubes template\n for fedora-31\n'
- )
- ]
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00'
- args = argparse.Namespace(
- all=False,
- templates=['t?st-vm']
- )
- with mock.patch('sys.stdout', new=io.StringIO()) as mock_out:
- qubesadmin.tools.qvm_template.search(args, self.app)
- self.assertEqual(mock_out.getvalue(),
- '''=== Name Matched: t?st-vm ===
- test-vm : Qubes template for fedora-31
- ''')
- self.assertEqual(mock_query.mock_calls, [
- mock.call(args, self.app)
- ])
- self.assertAllCalled()
- def _mock_qrexec_download(self, args, app, spec, path,
- dlsize=None, refresh=False):
- self.assertFalse(os.path.exists(path),
- '{} should not exist before'.format(path))
- # just create an empty file
- with open(path, 'wb') as f:
- if f is not None:
- f.truncate(dlsize)
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_180_download_success(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- mock_qrexec.side_effect = self._mock_qrexec_download
- with tempfile.TemporaryDirectory() as dir:
- args = argparse.Namespace(
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- retries=1
- )
- qubesadmin.tools.qvm_template.download(args, self.app, dir, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576),
- 'fedora-32': qubesadmin.tools.qvm_template.DlEntry(
- ('0', '1', '2'),
- 'qubes-templates-itl-testing',
- 2048576)
- })
- self.assertEqual(mock_qrexec.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- 1048576),
- mock.call(args, self.app, 'qubes-template-fedora-32-0:1-2',
- re_str(dir + '/.*/qubes-template-fedora-32-0:1-2.rpm.UNTRUSTED'),
- 2048576)
- ])
- self.assertEqual(mock_dllist.mock_calls, [])
- self.assertEqual(mock_verify_rpm.mock_calls, [
- mock.call(re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- '/tmp/keyring.gpg', template_name='fedora-31'),
- mock.call(re_str(dir + '/.*/qubes-template-fedora-32-0:1-2.rpm.UNTRUSTED'),
- '/tmp/keyring.gpg', template_name='fedora-32'),
- ])
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_181_download_success_nosuffix(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- mock_qrexec.side_effect = self._mock_qrexec_download
- with tempfile.TemporaryDirectory() as dir:
- args = argparse.Namespace(
- retries=1,
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- downloaddir=dir
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- qubesadmin.tools.qvm_template.download(args, self.app, None, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576)
- })
- self.assertEqual(mock_qrexec.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- 1048576)
- ])
- self.assertEqual(mock_dllist.mock_calls, [])
- self.assertEqual(mock_verify_rpm.mock_calls, [
- mock.call(re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- '/tmp/keyring.gpg', template_name='fedora-31'),
- ])
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_182_download_success_getdllist(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- mock_qrexec.side_effect = self._mock_qrexec_download
- mock_dllist.return_value = {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576)
- }
- with tempfile.TemporaryDirectory() as dir:
- args = argparse.Namespace(
- retries=1,
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- )
- qubesadmin.tools.qvm_template.download(args, self.app,
- dir, None,
- qubesadmin.tools.qvm_template.VersionSelector.LATEST_LOWER)
- self.assertEqual(mock_qrexec.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- 1048576)
- ])
- self.assertEqual(mock_dllist.mock_calls, [
- mock.call(args, self.app,
- version_selector=\
- qubesadmin.tools.qvm_template.\
- VersionSelector.LATEST_LOWER)
- ])
- self.assertEqual(mock_verify_rpm.mock_calls, [
- mock.call(re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- '/tmp/keyring.gpg', template_name='fedora-31'),
- ])
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_183_download_success_downloaddir(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- mock_qrexec.side_effect = self._mock_qrexec_download
- with tempfile.TemporaryDirectory() as dir:
- args = argparse.Namespace(
- retries=1,
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- downloaddir=dir
- )
- qubesadmin.tools.qvm_template.download(args, self.app, None, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576)
- })
- self.assertEqual(mock_qrexec.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- 1048576)
- ])
- self.assertEqual(mock_dllist.mock_calls, [])
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_184_download_success_exists(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- mock_qrexec.side_effect = self._mock_qrexec_download
- with tempfile.TemporaryDirectory() as dir:
- with open(os.path.join(
- dir, 'qubes-template-fedora-31-1:2-3.rpm'),
- 'w') as _:
- pass
- args = argparse.Namespace(
- retries=1,
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- downloaddir=dir
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- qubesadmin.tools.qvm_template.download(args, self.app, None, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576),
- 'fedora-32': qubesadmin.tools.qvm_template.DlEntry(
- ('0', '1', '2'),
- 'qubes-templates-itl-testing',
- 2048576)
- })
- self.assertTrue('already exists, skipping'
- in mock_err.getvalue())
- self.assertEqual(mock_qrexec.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-32-0:1-2',
- re_str(dir + '/.*/qubes-template-fedora-32-0:1-2.rpm.UNTRUSTED'),
- 2048576)
- ])
- self.assertEqual(mock_dllist.mock_calls, [])
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_185_download_success_existsmove(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- mock_qrexec.side_effect = self._mock_qrexec_download
- with tempfile.TemporaryDirectory() as dir:
- with open(os.path.join(
- dir, 'qubes-template-fedora-31-1:2-3.rpm'),
- 'w') as _:
- pass
- args = argparse.Namespace(
- retries=1,
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- downloaddir=dir
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- qubesadmin.tools.qvm_template.download(args, self.app, None, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576)
- })
- self.assertTrue('already exists, skipping'
- in mock_err.getvalue())
- self.assertEqual(mock_qrexec.mock_calls, [])
- self.assertEqual(mock_dllist.mock_calls, [])
- self.assertTrue(os.path.exists(
- dir + '/qubes-template-fedora-31-1:2-3.rpm'))
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_186_download_success_existsnosuffix(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- mock_qrexec.side_effect = self._mock_qrexec_download
- with tempfile.TemporaryDirectory() as dir:
- with open(os.path.join(
- dir, 'qubes-template-fedora-31-1:2-3.rpm'),
- 'w') as _:
- pass
- args = argparse.Namespace(
- retries=1,
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- downloaddir=dir
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- qubesadmin.tools.qvm_template.download(args, self.app, None, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576)
- })
- self.assertTrue('already exists, skipping'
- in mock_err.getvalue())
- self.assertEqual(mock_qrexec.mock_calls, [])
- self.assertEqual(mock_dllist.mock_calls, [])
- self.assertTrue(os.path.exists(
- dir + '/qubes-template-fedora-31-1:2-3.rpm'))
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_187_download_success_retry(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- counter = 0
- def f(*args, **kwargs):
- nonlocal counter
- counter += 1
- if counter == 1:
- raise ConnectionError
- self._mock_qrexec_download(*args, **kwargs)
- mock_qrexec.side_effect = f
- with tempfile.TemporaryDirectory() as dir:
- args = argparse.Namespace(
- retries=2,
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- downloaddir=dir
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err, \
- mock.patch('os.remove') as mock_rm:
- qubesadmin.tools.qvm_template.download(args, self.app, None, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576)
- })
- self.assertTrue('retrying...' in mock_err.getvalue())
- self.assertEqual(mock_rm.mock_calls, [
- mock.call(re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'))
- ])
- self.assertEqual(mock_qrexec.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- 1048576),
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- 1048576)
- ])
- self.assertEqual(mock_dllist.mock_calls, [])
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_188_download_fail_retry(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- mock_qrexec.side_effect = self._mock_qrexec_download
- counter = 0
- def f(*args, **kwargs):
- nonlocal counter
- counter += 1
- if counter <= 3:
- raise ConnectionError
- self._mock_qrexec_download(*args, **kwargs)
- mock_qrexec.side_effect = f
- with tempfile.TemporaryDirectory() as dir:
- args = argparse.Namespace(
- retries=3,
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- downloaddir=dir
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err, \
- mock.patch('os.remove') as mock_rm:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.download(
- args, self.app, None, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576)
- })
- self.assertEqual(mock_err.getvalue().count('retrying...'), 2)
- self.assertTrue('download failed' in mock_err.getvalue())
- self.assertEqual(mock_rm.mock_calls, [
- mock.call(re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED')),
- mock.call(re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED')),
- mock.call(re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'))
- ])
- self.assertEqual(mock_qrexec.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- 1048576),
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- 1048576),
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- 1048576)
- ])
- self.assertEqual(mock_dllist.mock_calls, [])
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_189_download_fail_interrupt(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- def f(*args):
- raise RuntimeError
- mock_qrexec.side_effect = f
- with tempfile.TemporaryDirectory() as dir:
- args = argparse.Namespace(
- retries=3,
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- downloaddir=dir
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err, \
- mock.patch('os.remove') as mock_rm:
- with self.assertRaises(RuntimeError):
- qubesadmin.tools.qvm_template.download(
- args, self.app, None, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576)
- })
- self.assertEqual(mock_qrexec.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm'),
- 1048576)
- ])
- self.assertEqual(mock_dllist.mock_calls, [])
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_190_download_fail_verify(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- mock_qrexec.side_effect = self._mock_qrexec_download
- mock_verify_rpm.side_effect = \
- qubesadmin.tools.qvm_template.SignatureVerificationError
- with tempfile.TemporaryDirectory() as dir:
- args = argparse.Namespace(
- retries=3,
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=True, # make sure it gets ignored
- downloaddir=dir
- )
- with self.assertRaises(qubesadmin.tools.qvm_template.SignatureVerificationError):
- qubesadmin.tools.qvm_template.download(
- args, self.app, None, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576)
- })
- self.assertEqual(mock_qrexec.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm'),
- 1048576)
- ])
- self.assertEqual(mock_dllist.mock_calls, [])
- self.assertEqual(os.listdir(dir), [])
- self.assertEqual(mock_verify_rpm.mock_calls, [
- mock.call(re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- '/tmp/keyring.gpg', template_name='fedora-31'),
- ])
- def _mock_qrexec_download_short(self, args, app, spec, path,
- dlsize=None, refresh=False):
- self.assertFalse(os.path.exists(path),
- '{} should not exist before'.format(path))
- # just create an empty file
- with open(path, 'wb') as f:
- if f is not None:
- f.truncate(dlsize // 2)
- @mock.patch('qubesadmin.tools.qvm_template.verify_rpm')
- @mock.patch('qubesadmin.tools.qvm_template.get_dl_list')
- @mock.patch('qubesadmin.tools.qvm_template.qrexec_download')
- def test_191_download_fail_short(self, mock_qrexec, mock_dllist,
- mock_verify_rpm):
- mock_qrexec.side_effect = self._mock_qrexec_download_short
- with tempfile.TemporaryDirectory() as dir, \
- self.assertRaises(SystemExit):
- args = argparse.Namespace(
- repo_files=[],
- keyring='/tmp/keyring.gpg',
- releasever='4.1',
- nogpgcheck=False,
- retries=1
- )
- qubesadmin.tools.qvm_template.download(args, self.app, dir, {
- 'fedora-31': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '2', '3'), 'qubes-templates-itl', 1048576),
- })
- self.assertEqual(mock_qrexec.mock_calls, [
- mock.call(args, self.app, 'qubes-template-fedora-31-1:2-3',
- re_str(dir + '/.*/qubes-template-fedora-31-1:2-3.rpm.UNTRUSTED'),
- 1048576),
- ])
- self.assertEqual(mock_dllist.mock_calls, [])
- self.assertEqual(mock_verify_rpm.mock_calls, [])
- @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')
- def test_200_reinstall_success(
- self,
- mock_verify,
- mock_dl_list,
- mock_dl,
- mock_extract,
- mock_confirm,
- mock_call,
- mock_mkdirs,
- mock_rename):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00test-vm class=TemplateVM state=Halted\n'
- build_time = '2020-09-01 14:30:00' # 1598970600
- install_time = '2020-09-01 15:30:00'
- for key, val in [
- ('name', 'test-vm'),
- ('epoch', '2'),
- ('version', '4.1'),
- ('release', '2020')]:
- self.app.expected_calls[(
- 'test-vm',
- 'admin.vm.feature.Get',
- f'template-{key}',
- None)] = b'0\0' + val.encode()
- for key, val in [
- ('name', 'test-vm'),
- ('epoch', '2'),
- ('version', '4.1'),
- ('release', '2020'),
- ('reponame', 'qubes-templates-itl'),
- ('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'
- rpm_hdr = {
- 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.return_value = {'test-vm': rpm_hdr}
- dl_list = {
- 'test-vm': qubesadmin.tools.qvm_template.DlEntry(
- ('1', '4.1', '20200101'), 'qubes-templates-itl', 1048576)
- }
- mock_dl_list.return_value = dl_list
- mock_call.side_effect = self.add_new_vm_side_effect
- mock_time = mock.Mock(wraps=datetime.datetime)
- mock_time.now.return_value = \
- datetime.datetime(2020, 9, 1, 15, 30, tzinfo=datetime.timezone.utc)
- selector = qubesadmin.tools.qvm_template.VersionSelector.REINSTALL
- with mock.patch('qubesadmin.tools.qvm_template.LOCK_FILE', '/tmp/test.lock'), \
- mock.patch('datetime.datetime', new=mock_time), \
- mock.patch('tempfile.TemporaryDirectory') as mock_tmpdir:
- args = argparse.Namespace(
- templates=['test-vm'],
- keyring='/tmp/keyring.gpg',
- nogpgcheck=False,
- cachedir='/var/cache/qvm-template',
- repo_files=[],
- releasever='4.1',
- yes=False,
- keep_cache=True,
- 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,
- version_selector=selector,
- override_existing=True)
- # Attempt to get download list
- self.assertEqual(mock_dl_list.mock_calls, [
- mock.call(args, self.app, version_selector=selector)
- ])
- mock_dl.assert_called_with(args, self.app,
- dl_list=dl_list, version_selector=selector)
- # already verified by download()
- self.assertEqual(mock_verify.mock_calls, [])
- # Package is extracted
- mock_extract.assert_called_with('test-vm',
- '/var/cache/qvm-template/qubes-template-test-vm-1:4.1-20200101.rpm',
- '/var/tmp/qvm-template-tmpdir')
- # Expect override confirmation
- self.assertEqual(mock_confirm.mock_calls,
- [mock.call(re_str(r'.*override changes.*:'), ['test-vm'])])
- # 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)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_remove.main')
- @mock.patch('qubesadmin.tools.qvm_template.confirm_action')
- def test_210_remove_success(self, mock_confirm, mock_remove):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = (
- b'0\x00vm1 class=TemplateVM state=Halted\n'
- b'vm2 class=TemplateVM state=Halted\n'
- )
- args = argparse.Namespace(
- templates=['vm1', 'vm2'],
- yes=False
- )
- qubesadmin.tools.qvm_template.remove(args, self.app)
- self.assertEqual(mock_confirm.mock_calls,
- [mock.call(re_str(r'.*completely remove.*'), ['vm1', 'vm2'])])
- self.assertEqual(mock_remove.mock_calls, [
- mock.call(['--force', '--', 'vm1', 'vm2'], self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_kill.main')
- @mock.patch('qubesadmin.tools.qvm_remove.main')
- @mock.patch('qubesadmin.tools.qvm_template.confirm_action')
- def test_211_remove_purge_disassoc_success(
- self,
- mock_confirm,
- mock_remove,
- mock_kill):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = (
- b'0\x00vm1 class=TemplateVM state=Halted\n'
- b'vm2 class=TemplateVM state=Halted\n'
- b'vm3 class=TemplateVM state=Halted\n'
- b'vm4 class=TemplateVM state=Halted\n'
- b'dummy class=TemplateVM state=Halted\n'
- b'dummy-1 class=TemplateVM state=Halted\n'
- )
- self.app.expected_calls[
- ('dummy', 'admin.vm.feature.Get', 'template-dummy', None)] = \
- b'0\x000'
- self.app.expected_calls[
- ('dummy-1', 'admin.vm.feature.Get',
- 'template-dummy', None)] = \
- b'0\x001'
- self.app.expected_calls[
- ('vm2', 'admin.vm.property.Set',
- 'default_template', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('vm2', 'admin.vm.property.Set', 'template', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('vm3', 'admin.vm.property.Set', 'netvm', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('vm3', 'admin.vm.property.Set', 'template', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('vm4', 'admin.vm.property.Set', 'netvm', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('vm4', 'admin.vm.property.Set', 'template', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('dom0', 'admin.property.Set', 'updatevm', b'')] = \
- b'0\x00'
- args = argparse.Namespace(
- templates=['vm1'],
- yes=False
- )
- def deps(app, vm):
- if vm == 'vm1':
- return [(self.app.domains['vm2'], 'default_template'),
- (self.app.domains['vm3'], 'netvm')]
- if vm == 'vm2' or vm == 'vm3':
- return [(self.app.domains['vm4'], 'netvm')]
- if vm == 'vm4':
- return [(None, 'updatevm')]
- return []
- with mock.patch('qubesadmin.utils.vm_dependencies') as mock_deps:
- mock_deps.side_effect = deps
- qubesadmin.tools.qvm_template.remove(args, self.app, purge=True)
- # Once for purge (dependency detection) and
- # one for disassoc (actually disassociating the dependencies
- self.assertEqual(mock_deps.mock_calls, [
- mock.call(self.app, self.app.domains['vm1']),
- mock.call(self.app, self.app.domains['vm2']),
- mock.call(self.app, self.app.domains['vm3']),
- mock.call(self.app, self.app.domains['vm4']),
- mock.call(self.app, self.app.domains['vm1']),
- mock.call(self.app, self.app.domains['vm2']),
- mock.call(self.app, self.app.domains['vm3']),
- mock.call(self.app, self.app.domains['vm4'])
- ])
- self.assertEqual(mock_confirm.mock_calls, [
- mock.call(re_str(r'.*completely remove.*'),
- ['vm1', 'vm2', 'vm3', 'vm4']),
- mock.call(re_str(r'.*completely remove.*'),
- ['vm1', 'vm2', 'vm3', 'vm4']),
- mock.call(re_str(r'.*completely remove.*'),
- ['vm1', 'vm2', 'vm3', 'vm4'])
- ])
- self.assertEqual(mock_remove.mock_calls, [
- mock.call(['--force', '--', 'vm1', 'vm2', 'vm3', 'vm4', 'dummy-1'],
- self.app)
- ])
- self.assertEqual(mock_kill.mock_calls, [
- mock.call(['--', 'vm1', 'vm2', 'vm3', 'vm4', 'dummy-1'], self.app)
- ])
- self.assertAllCalled()
- @mock.patch('qubesadmin.tools.qvm_kill.main')
- @mock.patch('qubesadmin.tools.qvm_remove.main')
- @mock.patch('qubesadmin.tools.qvm_template.confirm_action')
- def test_212_remove_disassoc_success(
- self,
- mock_confirm,
- mock_remove,
- mock_kill):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = (
- b'0\x00vm1 class=TemplateVM state=Halted\n'
- b'vm2 class=TemplateVM state=Halted\n'
- b'vm3 class=TemplateVM state=Halted\n'
- b'vm4 class=TemplateVM state=Halted\n'
- b'dummy class=TemplateVM state=Halted\n'
- b'dummy-1 class=TemplateVM state=Halted\n'
- )
- self.app.expected_calls[
- ('dummy', 'admin.vm.feature.Get', 'template-dummy', None)] = \
- b'0\x000'
- self.app.expected_calls[
- ('dummy-1', 'admin.vm.feature.Get',
- 'template-dummy', None)] = \
- b'0\x001'
- self.app.expected_calls[
- ('vm2', 'admin.vm.property.Set',
- 'default_template', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('vm2', 'admin.vm.property.Set', 'template', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('vm3', 'admin.vm.property.Set', 'netvm', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('vm3', 'admin.vm.property.Set', 'template', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('vm4', 'admin.vm.property.Set', 'netvm', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('vm4', 'admin.vm.property.Set', 'template', b'dummy-1')] = \
- b'0\x00'
- self.app.expected_calls[
- ('dom0', 'admin.property.Set', 'updatevm', b'')] = \
- b'0\x00'
- args = argparse.Namespace(
- templates=['vm1', 'vm2', 'vm3', 'vm4'],
- yes=False
- )
- def deps(app, vm):
- if vm == 'vm1':
- return [(self.app.domains['vm2'], 'default_template'),
- (self.app.domains['vm3'], 'netvm')]
- if vm == 'vm2' or vm == 'vm3':
- return [(self.app.domains['vm4'], 'netvm')]
- if vm == 'vm4':
- return [(None, 'updatevm')]
- return []
- with mock.patch('qubesadmin.utils.vm_dependencies') as mock_deps:
- mock_deps.side_effect = deps
- qubesadmin.tools.qvm_template.remove(args, self.app, disassoc=True)
- self.assertEqual(mock_deps.mock_calls, [
- mock.call(self.app, self.app.domains['vm1']),
- mock.call(self.app, self.app.domains['vm2']),
- mock.call(self.app, self.app.domains['vm3']),
- mock.call(self.app, self.app.domains['vm4'])
- ])
- self.assertEqual(mock_confirm.mock_calls, [
- mock.call(re_str(r'.*completely remove.*'),
- ['vm1', 'vm2', 'vm3', 'vm4'])
- ])
- self.assertEqual(mock_remove.mock_calls, [
- mock.call(['--force', '--', 'vm1', 'vm2', 'vm3', 'vm4'],
- self.app)
- ])
- self.assertEqual(mock_kill.mock_calls, [
- mock.call(['--', 'vm1', 'vm2', 'vm3', 'vm4'], self.app)
- ])
- self.assertAllCalled()
- def test_213_remove_fail_nodomain(self):
- self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
- b'0\x00vm1 class=TemplateVM state=Halted\n'
- args = argparse.Namespace(
- templates=['vm0'],
- yes=False
- )
- with mock.patch('sys.stderr', new=io.StringIO()) as mock_err:
- with self.assertRaises(SystemExit):
- qubesadmin.tools.qvm_template.remove(args, self.app)
- self.assertTrue('no such domain:' in mock_err.getvalue())
- self.assertAllCalled()
|