dispvm.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #!/usr/bin/python2 -O
  2. # vim: fileencoding=utf-8
  3. import qubes.vm.qubesvm
  4. import qubes.vm.appvm
  5. import qubes.config
  6. class DispVM(qubes.vm.qubesvm.QubesVM):
  7. '''Disposable VM'''
  8. template = qubes.VMProperty('template',
  9. load_stage=4,
  10. vmclass=qubes.vm.appvm.AppVM,
  11. ls_width=31,
  12. doc='AppVM, on which this DispVM is based.')
  13. dispid = qubes.property('dispid', type=int, write_once=True,
  14. clone=False,
  15. ls_width=3,
  16. doc='''Internal, persistent identifier of particular DispVM.''')
  17. def __init__(self, *args, **kwargs):
  18. self.volume_config = {
  19. 'root': {
  20. 'name': 'root',
  21. 'pool': 'default',
  22. 'volume_type': 'snapshot',
  23. },
  24. 'private': {
  25. 'name': 'private',
  26. 'pool': 'default',
  27. 'volume_type': 'snapshot',
  28. },
  29. 'volatile': {
  30. 'name': 'volatile',
  31. 'pool': 'default',
  32. 'volume_type': 'volatile',
  33. 'size': qubes.config.defaults['root_img_size'] +
  34. qubes.config.defaults['private_img_size'],
  35. },
  36. 'kernel': {
  37. 'name': 'kernel',
  38. 'pool': 'linux-kernel',
  39. 'volume_type': 'read-only',
  40. }
  41. }
  42. super(DispVM, self).__init__(*args, **kwargs)
  43. @qubes.events.handler('domain-load')
  44. def on_domain_loaded(self, event):
  45. # pylint: disable=unused-argument
  46. # Some additional checks for template based VM
  47. assert self.template
  48. # self.template.appvms.add(self) # XXX
  49. @classmethod
  50. def from_appvm(cls, appvm, **kwargs):
  51. '''Create a new instance from given AppVM
  52. :param qubes.vm.appvm.AppVM appvm: template from which the VM should \
  53. be created (could also be name or qid)
  54. :returns: new disposable vm
  55. *kwargs* are passed to the newly created VM
  56. >>> import qubes.vm.dispvm.DispVM
  57. >>> dispvm = qubes.vm.dispvm.DispVM.from_appvm(appvm).start()
  58. >>> dispvm.run_service('qubes.VMShell', input='firefox')
  59. >>> dispvm.cleanup()
  60. This method modifies :file:`qubes.xml` file. In fact, the newly created
  61. vm belongs to other :py:class:`qubes.Qubes` instance than the *app*.
  62. The qube returned is not started.
  63. '''
  64. store = appvm.app.store if isinstance(appvm, qubes.vm.BaseVM) else None
  65. app = qubes.Qubes(store)
  66. dispvm = app.add_new_vm(
  67. cls,
  68. dispid=app.domains.get_new_unused_dispid(),
  69. template=app.domains[appvm],
  70. **kwargs)
  71. dispvm.create_on_disk()
  72. app.save()
  73. return dispvm
  74. def cleanup(self):
  75. '''Clean up after the DispVM
  76. This stops the disposable qube and removes it from the store.
  77. This method modifies :file:`qubes.xml` file.
  78. '''
  79. app = qubes.Qubes(self.app.store)
  80. self = app.domains[self.uuid]
  81. self.force_shutdown()
  82. self.remove_from_disk()
  83. del app.domains[self]
  84. app.save()