qvm_create.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. # -*- encoding: utf8 -*-
  2. #
  3. # The Qubes OS Project, http://www.qubes-os.org
  4. #
  5. # Copyright (C) 2017 Marek Marczykowski-Górecki
  6. # <marmarek@invisiblethingslab.com>
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU Lesser General Public License as published by
  10. # the Free Software Foundation; either version 2.1 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Lesser General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Lesser General Public License along
  19. # with this program; if not, see <http://www.gnu.org/licenses/>.
  20. import os
  21. import tempfile
  22. import qubesadmin.tests
  23. import qubesadmin.tests.tools
  24. import qubesadmin.tools.qvm_create
  25. class TC_00_qvm_create(qubesadmin.tests.QubesTestCase):
  26. def test_000_just_appvm(self):
  27. self.app.expected_calls[('dom0', 'admin.vm.Create.AppVM', None,
  28. b'name=new-vm label=red')] = b'0\x00'
  29. self.app.expected_calls[('dom0', 'admin.label.List', None, None)] = \
  30. b'0\x00red\nblue\n'
  31. self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
  32. b'0\x00new-vm class=AppVM state=Halted\n'
  33. qubesadmin.tools.qvm_create.main(['-l', 'red', 'new-vm'], app=self.app)
  34. self.assertAllCalled()
  35. def test_001_missing_vm(self):
  36. with self.assertRaises(SystemExit):
  37. with qubesadmin.tests.tools.StderrBuffer() as stderr:
  38. qubesadmin.tools.qvm_create.main(['-l', 'red'], app=self.app)
  39. self.assertIn('NAME', stderr.getvalue())
  40. self.assertAllCalled()
  41. def test_002_custom_template(self):
  42. self.app.expected_calls[('dom0', 'admin.vm.Create.AppVM',
  43. 'some-template', b'name=new-vm label=red')] = b'0\x00'
  44. self.app.expected_calls[('dom0', 'admin.label.List', None, None)] = \
  45. b'0\x00red\nblue\n'
  46. self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
  47. b'0\x00new-vm class=AppVM state=Halted\n'
  48. qubesadmin.tools.qvm_create.main(['-l', 'red', '-t',
  49. 'some-template', 'new-vm'], app=self.app)
  50. self.assertAllCalled()
  51. def test_003_properties(self):
  52. self.app.expected_calls[('dom0', 'admin.vm.Create.AppVM',
  53. None, b'name=new-vm label=red')] = b'0\x00'
  54. self.app.expected_calls[('dom0', 'admin.label.List', None, None)] = \
  55. b'0\x00red\nblue\n'
  56. self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
  57. b'0\x00new-vm class=AppVM state=Halted\n'
  58. self.app.expected_calls[('new-vm', 'admin.vm.property.Set',
  59. 'netvm', b'sys-whonix')] = b'0\x00'
  60. qubesadmin.tools.qvm_create.main(['-l', 'red', '--prop',
  61. 'netvm=sys-whonix', 'new-vm'],
  62. app=self.app)
  63. self.assertAllCalled()
  64. def test_004_pool(self):
  65. self.app.expected_calls[('dom0', 'admin.vm.CreateInPool.AppVM',
  66. None, b'name=new-vm label=red pool=some-pool')] = b'0\x00'
  67. self.app.expected_calls[('dom0', 'admin.label.List', None, None)] = \
  68. b'0\x00red\nblue\n'
  69. self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
  70. b'0\x00new-vm class=AppVM state=Halted\n'
  71. qubesadmin.tools.qvm_create.main(['-l', 'red', '-P', 'some-pool',
  72. 'new-vm'],
  73. app=self.app)
  74. self.assertAllCalled()
  75. def test_005_pools(self):
  76. self.app.expected_calls[('dom0', 'admin.vm.CreateInPool.AppVM',
  77. None, b'name=new-vm label=red pool:private=some-pool '
  78. b'pool:volatile=other-pool')] = b'0\x00'
  79. self.app.expected_calls[('dom0', 'admin.label.List', None, None)] = \
  80. b'0\x00red\nblue\n'
  81. self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
  82. b'0\x00new-vm class=AppVM state=Halted\n'
  83. qubesadmin.tools.qvm_create.main(['-l', 'red', '--pool',
  84. 'private=some-pool', '--pool', 'volatile=other-pool', 'new-vm'],
  85. app=self.app)
  86. self.assertAllCalled()
  87. def test_005_root_copy_from(self):
  88. with tempfile.NamedTemporaryFile() as root_file:
  89. root_file.file.write(b'root data')
  90. root_file.file.flush()
  91. self.app.expected_calls[('dom0', 'admin.vm.Create.AppVM',
  92. None, b'name=new-vm label=red')] = b'0\x00'
  93. self.app.expected_calls[('dom0', 'admin.label.List', None, None)] = \
  94. b'0\x00red\nblue\n'
  95. self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
  96. b'0\x00new-vm class=AppVM state=Halted\n'
  97. self.app.expected_calls[
  98. ('new-vm', 'admin.vm.volume.List', None, None)] = \
  99. b'0\x00root\nprivate\nvolatile\nkernel\n'
  100. self.app.expected_calls[
  101. ('new-vm', 'admin.vm.volume.Import', 'root', b'root data')] = \
  102. b'0\0'
  103. qubesadmin.tools.qvm_create.main(['-l', 'red',
  104. '--root-copy-from=' + root_file.name, 'new-vm'],
  105. app=self.app)
  106. self.assertAllCalled()
  107. self.assertTrue(os.path.exists(root_file.name))
  108. def test_006_root_move_from(self):
  109. with tempfile.NamedTemporaryFile(delete=False) as root_file:
  110. root_file.file.write(b'root data')
  111. root_file.file.flush()
  112. self.app.expected_calls[('dom0', 'admin.vm.Create.AppVM',
  113. None, b'name=new-vm label=red')] = b'0\x00'
  114. self.app.expected_calls[('dom0', 'admin.label.List', None, None)] = \
  115. b'0\x00red\nblue\n'
  116. self.app.expected_calls[('dom0', 'admin.vm.List', None, None)] = \
  117. b'0\x00new-vm class=AppVM state=Halted\n'
  118. self.app.expected_calls[
  119. ('new-vm', 'admin.vm.volume.List', None, None)] = \
  120. b'0\x00root\nprivate\nvolatile\nkernel\n'
  121. self.app.expected_calls[
  122. ('new-vm', 'admin.vm.volume.Import', 'root', b'root data')] = \
  123. b'0\0'
  124. qubesadmin.tools.qvm_create.main(['-l', 'red',
  125. '--root-move-from=' + root_file.name, 'new-vm'],
  126. app=self.app)
  127. self.assertAllCalled()
  128. self.assertFalse(os.path.exists(root_file.name))
  129. def test_007_root_move_copy_both(self):
  130. with tempfile.NamedTemporaryFile() as root_file:
  131. root_file.file.write(b'root data')
  132. root_file.file.flush()
  133. with self.assertRaises(SystemExit):
  134. qubesadmin.tools.qvm_create.main(['-l', 'red',
  135. '--root-copy-from=' + root_file.name,
  136. '--root-move-from=' + root_file.name,
  137. 'new-vm'],
  138. app=self.app)
  139. self.assertAllCalled()
  140. self.assertTrue(os.path.exists(root_file.name))
  141. def test_008_root_invalid_path(self):
  142. with self.assertRaises(SystemExit):
  143. qubesadmin.tools.qvm_create.main(['-l', 'red',
  144. '--root-copy-from=/invalid', 'new-vm'],
  145. app=self.app)
  146. self.assertAllCalled()
  147. def test_009_help_classes(self):
  148. self.app.expected_calls[('dom0', 'admin.vmclass.List',
  149. None, None)] = b'0\x00StandaloneVM\nAppVM\nTemplateVM\nDispVM\n'
  150. with qubesadmin.tests.tools.StdoutBuffer() as stdout:
  151. qubesadmin.tools.qvm_create.main(['--help-classes'],
  152. app=self.app)
  153. self.assertEqual(stdout.getvalue(),
  154. 'AppVM\nDispVM\nStandaloneVM\nTemplateVM\n')
  155. self.assertAllCalled()