OpenStack in a snap!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

132 lines
4.1 KiB

  1. import logging
  2. import json
  3. import unittest
  4. import os
  5. import subprocess
  6. from typing import List
  7. import petname
  8. # Setup logging
  9. log = logging.getLogger("microstack_test")
  10. log.setLevel(logging.DEBUG)
  11. stream = logging.StreamHandler()
  12. formatter = logging.Formatter(
  13. '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  14. stream.setFormatter(formatter)
  15. log.addHandler(stream)
  16. def check(*args: List[str]) -> int:
  17. """Execute a shell command, raising an error on failed excution.
  18. :param args: strings to be composed into the bash call.
  19. """
  20. return subprocess.check_call(args)
  21. def check_output(*args: List[str]) -> str:
  22. """Execute a shell command, returning the output of the command.
  23. :param args: strings to be composed into the bash call.
  24. Include our env; pass in any extra keyword args.
  25. """
  26. return subprocess.check_output(args, universal_newlines=True).strip()
  27. def call(*args: List[str]) -> bool:
  28. """Execute a shell command.
  29. Return True if the call executed successfully (returned 0), or
  30. False if it returned with an error code (return > 0)
  31. :param args: strings to be composed into the bash call.
  32. """
  33. return not subprocess.call(args)
  34. class Framework(unittest.TestCase):
  35. PREFIX = []
  36. DUMP_DIR = '/tmp'
  37. MACHINE = ''
  38. DISTRO = 'bionic'
  39. SNAP = 'microstack_stein_amd64.snap'
  40. HORIZON_IP = '10.20.20.1'
  41. INIT_FLAG = 'auto'
  42. def install_snap(self, channel='dangerous', snap=None):
  43. if snap is None:
  44. snap = self.SNAP
  45. check(*self.PREFIX, 'sudo', 'snap', 'install', '--classic',
  46. '--{}'.format(channel), snap)
  47. def init_snap(self, flag='auto'):
  48. check(*self.PREFIX, 'sudo', 'microstack.init', '--{}'.format(flag))
  49. def multipass(self):
  50. self.MACHINE = petname.generate()
  51. self.PREFIX = ['multipass', 'exec', self.MACHINE, '--']
  52. check('sudo', 'snap', 'install', '--classic', '--edge', 'multipass')
  53. check('multipass', 'launch', '--cpus', '2', '--mem', '8G', self.DISTRO,
  54. '--name', self.MACHINE)
  55. check('multipass', 'copy-files', self.SNAP, '{}:'.format(self.MACHINE))
  56. # Figure out machine's ip
  57. info = check_output('multipass', 'info', self.MACHINE, '--format',
  58. 'json')
  59. info = json.loads(info)
  60. self.HORIZON_IP = info['info'][self.MACHINE]['ipv4'][0]
  61. def dump_logs(self):
  62. if check_output('whoami') == 'zuul':
  63. self.DUMP_DIR = "/home/zuul/zuul-output/logs"
  64. check(*self.PREFIX,
  65. 'sudo', 'tar', 'cvzf',
  66. '{}/dump.tar.gz'.format(self.DUMP_DIR),
  67. '/var/snap/microstack/common/log',
  68. '/var/snap/microstack/common/etc',
  69. '/var/log/syslog')
  70. if 'multipass' in self.PREFIX:
  71. check('multipass', 'copy-files',
  72. '{}:/tmp/dump.tar.gz'.format(self.MACHINE), '.')
  73. print('Saved dump.tar.gz to local working dir.')
  74. def setUp(self):
  75. self.passed = False # HACK: trigger (or skip) cleanup.
  76. if os.environ.get('MULTIPASS'):
  77. print("Booting a Multipass VM ...")
  78. self.multipass()
  79. print("Installing {}".format(self.SNAP))
  80. self.install_snap()
  81. print("Initializing the snap with --{}".format(self.INIT_FLAG))
  82. self.init_snap(self.INIT_FLAG)
  83. def tearDown(self):
  84. """Either dump logs in the case of failure, or clean up."""
  85. if not self.passed:
  86. # Skip teardown in the case of failures, so that we can
  87. # inspect them.
  88. # TODO: I'd like to use the errors and failures list in
  89. # the test result, but I was having trouble getting to it
  90. # from this routine. Need to do more digging and possibly
  91. # elimiate the self.passed hack.
  92. print("Tests failed. Dumping logs and exiting.")
  93. return self.dump_logs()
  94. print("Tests complete. Tearing down.")
  95. if 'multipass' in self.PREFIX:
  96. check('sudo', 'multipass', 'delete', self.MACHINE)
  97. check('sudo', 'multipass', 'purge')
  98. else:
  99. check('sudo', 'snap', 'remove', '--purge', 'microstack')