kernels.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #
  2. # The Qubes OS Project, http://www.qubes-os.org
  3. #
  4. # Copyright (C) 2010-2015 Joanna Rutkowska <joanna@invisiblethingslab.com>
  5. # Copyright (C) 2015 Wojtek Porczyk <woju@invisiblethingslab.com>
  6. # Copyright (C) 2016 Bahtiar `kalkin-` Gadimov <bahtiar@gadimov.de>
  7. #
  8. # This library is free software; you can redistribute it and/or
  9. # modify it under the terms of the GNU Lesser General Public
  10. # License as published by the Free Software Foundation; either
  11. # version 2.1 of the License, or (at your option) any later version.
  12. #
  13. # This library 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 GNU
  16. # Lesser General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Lesser General Public
  19. # License along with this library; if not, see <https://www.gnu.org/licenses/>.
  20. #
  21. ''' This module contains pool implementations for different OS kernels. '''
  22. import os
  23. from qubes.storage import Pool, StoragePoolException, Volume
  24. class LinuxModules(Volume):
  25. ''' A volume representing a ro linux kernel '''
  26. rw = False
  27. def __init__(self, target_dir, kernel_version, **kwargs):
  28. kwargs['vid'] = ''
  29. super(LinuxModules, self).__init__(**kwargs)
  30. self._kernel_version = kernel_version
  31. self.target_dir = target_dir
  32. @property
  33. def vid(self):
  34. if callable(self._kernel_version):
  35. return self._kernel_version()
  36. return self._kernel_version
  37. @vid.setter
  38. def vid(self, value):
  39. # ignore
  40. pass
  41. @property
  42. def kernels_dir(self):
  43. kernel_version = self.vid
  44. if not kernel_version:
  45. return None
  46. return os.path.join(self.target_dir, kernel_version)
  47. @property
  48. def path(self):
  49. kernels_dir = self.kernels_dir
  50. if not kernels_dir:
  51. return None
  52. return os.path.join(kernels_dir, 'modules.img')
  53. @property
  54. def vmlinuz(self):
  55. kernels_dir = self.kernels_dir
  56. if not kernels_dir:
  57. return None
  58. return os.path.join(kernels_dir, 'vmlinuz')
  59. @property
  60. def initramfs(self):
  61. kernels_dir = self.kernels_dir
  62. if not kernels_dir:
  63. return None
  64. return os.path.join(kernels_dir, 'initramfs')
  65. @property
  66. def revisions(self):
  67. return {}
  68. def is_dirty(self):
  69. return False
  70. def import_volume(self, src_volume):
  71. if isinstance(src_volume, LinuxModules):
  72. # do nothing
  73. return self
  74. raise StoragePoolException('clone of LinuxModules volume from '
  75. 'different volume type is not supported')
  76. def create(self):
  77. return self
  78. def remove(self):
  79. pass
  80. def commit(self):
  81. return self
  82. def export(self):
  83. return self.path
  84. def is_outdated(self):
  85. return False
  86. def start(self):
  87. path = self.path
  88. if path and not os.path.exists(path):
  89. raise StoragePoolException('Missing kernel modules: %s' % path)
  90. return self
  91. def stop(self):
  92. pass
  93. def verify(self):
  94. if self.vid:
  95. _check_path(self.path)
  96. _check_path(self.vmlinuz)
  97. _check_path(self.initramfs)
  98. def block_device(self):
  99. if self.vid:
  100. return super().block_device()
  101. class LinuxKernel(Pool):
  102. ''' Provides linux kernels '''
  103. driver = 'linux-kernel'
  104. def __init__(self, name=None, dir_path=None):
  105. assert dir_path, 'Missing dir_path'
  106. super(LinuxKernel, self).__init__(name=name)
  107. self.dir_path = dir_path
  108. def init_volume(self, vm, volume_config):
  109. assert not volume_config['rw']
  110. # migrate old config
  111. if volume_config.get('snap_on_start', False) and not \
  112. volume_config.get('source', None):
  113. volume_config['snap_on_start'] = False
  114. if volume_config.get('save_on_stop', False):
  115. raise NotImplementedError(
  116. 'LinuxKernel pool does not support save_on_stop=True')
  117. volume_config['pool'] = self
  118. volume = LinuxModules(self.dir_path, lambda: vm.kernel, **volume_config)
  119. return volume
  120. @property
  121. def config(self):
  122. return {
  123. 'name': self.name,
  124. 'dir_path': self.dir_path,
  125. 'driver': LinuxKernel.driver,
  126. }
  127. def destroy(self):
  128. pass
  129. def import_volume(self, dst_pool, dst_volume, src_pool, src_volume):
  130. pass
  131. def setup(self):
  132. pass
  133. @property
  134. def volumes(self):
  135. ''' Return all known kernel volumes '''
  136. return [LinuxModules(self.dir_path,
  137. kernel_version,
  138. pool=self,
  139. name=kernel_version,
  140. rw=False
  141. )
  142. for kernel_version in os.listdir(self.dir_path)]
  143. def _check_path(path):
  144. ''' Raise an :py:class:`qubes.storage.StoragePoolException` if ``path`` does
  145. not exist.
  146. '''
  147. if not os.path.exists(path):
  148. raise StoragePoolException('Missing file: %s' % path)