base.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. # Copyright 2016 Cloudbase Solutions Srl
  2. # All Rights Reserved.
  3. import abc
  4. import itertools
  5. import os
  6. import re
  7. import uuid
  8. from coriolis import utils
  9. class BaseOSMorphingTools(object):
  10. __metaclass__ = abc.ABCMeta
  11. def __init__(
  12. self, conn, os_root_dir, os_root_device, hypervisor,
  13. event_manager):
  14. self._conn = conn
  15. self._os_root_dir = os_root_dir
  16. self._os_root_device = os_root_device
  17. self._distro = None
  18. self._version = None
  19. self._hypervisor = hypervisor
  20. self._event_manager = event_manager
  21. def check_os(self):
  22. if not self._distro:
  23. os_info = self._check_os()
  24. if os_info:
  25. self._distro, self._version = os_info
  26. if self._distro:
  27. return self._distro, self._version
  28. @abc.abstractmethod
  29. def _check_os(self):
  30. pass
  31. @abc.abstractmethod
  32. def set_net_config(self, nics_info, dhcp):
  33. pass
  34. def get_packages(self):
  35. return [], []
  36. def pre_packages_install(self, package_names):
  37. pass
  38. def install_packages(self, package_names):
  39. pass
  40. def post_packages_install(self, package_names):
  41. pass
  42. def pre_packages_uninstall(self, package_names):
  43. pass
  44. def uninstall_packages(self, package_names):
  45. pass
  46. def post_packages_uninstall(self, package_names):
  47. pass
  48. class BaseLinuxOSMorphingTools(BaseOSMorphingTools):
  49. __metaclass__ = abc.ABCMeta
  50. _packages = {}
  51. def __init__(self, conn, os_root_dir, os_root_dev, hypervisor,
  52. event_manager):
  53. super(BaseLinuxOSMorphingTools, self).__init__(
  54. conn, os_root_dir, os_root_dev, hypervisor, event_manager)
  55. self._ssh = conn
  56. def get_packages(self):
  57. k_add = [h for h in self._packages.keys() if
  58. h is None or h == self._hypervisor]
  59. add = [p[0] for p in itertools.chain.from_iterable(
  60. [l for k, l in self._packages.items() if k in k_add])]
  61. # If the second value in the tuple is True, the package must
  62. # be uninstalled on export
  63. remove = [p[0] for p in itertools.chain.from_iterable(
  64. [l for k, l in self._packages.items()])
  65. if p[1]]
  66. return add, remove
  67. def pre_packages_install(self, package_names):
  68. self._copy_resolv_conf()
  69. def post_packages_install(self, package_names):
  70. self._restore_resolv_conf()
  71. def pre_packages_uninstall(self, package_names):
  72. self._copy_resolv_conf()
  73. def post_packages_uninstall(self, package_names):
  74. self._restore_resolv_conf()
  75. def _test_path(self, chroot_path):
  76. path = os.path.join(self._os_root_dir, chroot_path)
  77. return utils.test_ssh_path(self._ssh, path)
  78. def _read_file(self, chroot_path):
  79. path = os.path.join(self._os_root_dir, chroot_path)
  80. return utils.read_ssh_file(self._ssh, path)
  81. def _write_file(self, chroot_path, content):
  82. path = os.path.join(self._os_root_dir, chroot_path)
  83. utils.write_ssh_file(self._ssh, path, content)
  84. def _list_dir(self, chroot_path):
  85. path = os.path.join(self._os_root_dir, chroot_path)
  86. return utils.list_ssh_dir(self._ssh, path)
  87. def _exec_cmd(self, cmd):
  88. return utils.exec_ssh_cmd(self._ssh, cmd)
  89. def _exec_cmd_chroot(self, cmd):
  90. return utils.exec_ssh_cmd_chroot(self._ssh, self._os_root_dir, cmd)
  91. def _check_user_exists(self, username):
  92. try:
  93. self._exec_cmd_chroot("id -u %s" % username)
  94. return True
  95. except:
  96. return False
  97. def _write_file_sudo(self, chroot_path, content):
  98. # NOTE: writes the file to a temp location due to permission issues
  99. tmp_file = 'tmp/%s' % str(uuid.uuid4())
  100. self._write_file(tmp_file, content)
  101. self._exec_cmd_chroot("cp /%s /%s" % (tmp_file, chroot_path))
  102. self._exec_cmd_chroot("rm /%s" % tmp_file)
  103. def _enable_systemd_service(self, service_name):
  104. self._exec_cmd_chroot("systemctl enable %s.service" % service_name)
  105. def _get_os_release(self):
  106. return self._read_config_file("etc/os-release", check_exists=True)
  107. def _read_config_file(self, chroot_path, check_exists=False):
  108. if not check_exists or self._test_path(chroot_path):
  109. content = self._read_file(chroot_path).decode()
  110. return self._get_config(content)
  111. else:
  112. return {}
  113. def _get_config(self, config_content):
  114. config = {}
  115. for config_line in config_content.split('\n'):
  116. m = re.match('(.*)=(?:"|\')?([^"\']*)(?:"|\')?', config_line)
  117. if m:
  118. name, value = m.groups()
  119. config[name] = value
  120. return config
  121. def _copy_resolv_conf(self):
  122. resolv_conf_path = os.path.join(self._os_root_dir, "etc/resolv.conf")
  123. resolv_conf_path_old = "%s.old" % resolv_conf_path
  124. if self._test_path(resolv_conf_path):
  125. self._exec_cmd(
  126. "sudo mv -f %s %s" % (resolv_conf_path, resolv_conf_path_old))
  127. self._exec_cmd('sudo cp --remove-destination /etc/resolv.conf %s' %
  128. resolv_conf_path)
  129. def _restore_resolv_conf(self):
  130. resolv_conf_path = os.path.join(self._os_root_dir, "etc/resolv.conf")
  131. resolv_conf_path_old = "%s.old" % resolv_conf_path
  132. if self._test_path(resolv_conf_path_old):
  133. self._exec_cmd(
  134. "sudo mv -f %s %s" % (resolv_conf_path_old, resolv_conf_path))