Devuan deployment of britney2
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.
 
 
 

171 lines
5.8 KiB

  1. # Mock a Swift server with autopkgtest results
  2. # Author: Martin Pitt <martin.pitt@ubuntu.com>
  3. import os
  4. import tarfile
  5. import io
  6. import sys
  7. import socket
  8. import time
  9. import tempfile
  10. import json
  11. try:
  12. from http.server import HTTPServer, BaseHTTPRequestHandler
  13. from urllib.parse import urlparse, parse_qs
  14. except ImportError:
  15. # Python 2
  16. from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
  17. from urlparse import urlparse, parse_qs
  18. class SwiftHTTPRequestHandler(BaseHTTPRequestHandler):
  19. '''Mock swift container with autopkgtest results
  20. This accepts retrieving a particular result.tar (e. g.
  21. /container/path/result.tar) or listing the container contents
  22. (/container/?prefix=foo&delimiter=@&marker=foo/bar).
  23. '''
  24. # map container -> result.tar path -> (exitcode, testpkg-version[, testinfo])
  25. results = {}
  26. def do_GET(self):
  27. p = urlparse(self.path)
  28. path_comp = p.path.split('/')
  29. container = path_comp[1]
  30. path = '/'.join(path_comp[2:])
  31. if path:
  32. self.serve_file(container, path)
  33. else:
  34. self.list_container(container, parse_qs(p.query))
  35. def serve_file(self, container, path):
  36. if os.path.basename(path) != 'result.tar':
  37. self.send_error(404, 'File not found (only result.tar supported)')
  38. return
  39. try:
  40. fields = self.results[container][os.path.dirname(path)]
  41. try:
  42. (exitcode, pkgver, testinfo) = fields
  43. except ValueError:
  44. (exitcode, pkgver) = fields
  45. testinfo = None
  46. except KeyError:
  47. self.send_error(404, 'File not found')
  48. return
  49. self.send_response(200)
  50. self.send_header('Content-type', 'application/octet-stream')
  51. self.end_headers()
  52. tar = io.BytesIO()
  53. with tarfile.open('result.tar', 'w', tar) as results:
  54. # add exitcode
  55. contents = ('%i' % exitcode).encode()
  56. ti = tarfile.TarInfo('exitcode')
  57. ti.size = len(contents)
  58. results.addfile(ti, io.BytesIO(contents))
  59. # add testpkg-version
  60. if pkgver is not None:
  61. contents = pkgver.encode()
  62. ti = tarfile.TarInfo('testpkg-version')
  63. ti.size = len(contents)
  64. results.addfile(ti, io.BytesIO(contents))
  65. # add testinfo.json
  66. if testinfo:
  67. contents = json.dumps(testinfo).encode()
  68. ti = tarfile.TarInfo('testinfo.json')
  69. ti.size = len(contents)
  70. results.addfile(ti, io.BytesIO(contents))
  71. self.wfile.write(tar.getvalue())
  72. def list_container(self, container, query):
  73. try:
  74. objs = set(['%s/result.tar' % r for r in self.results[container]])
  75. except KeyError:
  76. self.send_error(401, 'Container does not exist')
  77. return
  78. if 'prefix' in query:
  79. p = query['prefix'][-1]
  80. objs = set([o for o in objs if o.startswith(p)])
  81. if 'delimiter' in query:
  82. d = query['delimiter'][-1]
  83. # if find() returns a value, we want to include the delimiter, thus
  84. # bump its result; for "not found" return None
  85. find_adapter = lambda i: (i >= 0) and (i + 1) or None
  86. objs = set([o[:find_adapter(o.find(d))] for o in objs])
  87. if 'marker' in query:
  88. m = query['marker'][-1]
  89. objs = set([o for o in objs if o > m])
  90. self.send_response(objs and 200 or 204) # 204: "No Content"
  91. self.send_header('Content-type', 'text/plain')
  92. self.end_headers()
  93. self.wfile.write(('\n'.join(sorted(objs)) + '\n').encode('UTF-8'))
  94. class AutoPkgTestSwiftServer:
  95. def __init__(self, port=8080):
  96. self.port = port
  97. self.server_pid = None
  98. self.log = None
  99. def __del__(self):
  100. if self.server_pid:
  101. self.stop()
  102. @classmethod
  103. def set_results(klass, results):
  104. '''Set served results.
  105. results is a map: container -> result.tar path ->
  106. (exitcode, testpkg-version, testinfo)
  107. '''
  108. SwiftHTTPRequestHandler.results = results
  109. def start(self):
  110. assert self.server_pid is None, 'already started'
  111. if self.log:
  112. self.log.close()
  113. self.log = tempfile.TemporaryFile()
  114. p = os.fork()
  115. if p:
  116. # parent: wait until server starts
  117. self.server_pid = p
  118. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  119. while True:
  120. if s.connect_ex(('127.0.0.1', self.port)) == 0:
  121. break
  122. time.sleep(0.1)
  123. s.close()
  124. return
  125. # child; quiesce logging on stderr
  126. os.dup2(self.log.fileno(), sys.stderr.fileno())
  127. srv = HTTPServer(('', self.port), SwiftHTTPRequestHandler)
  128. srv.serve_forever()
  129. sys.exit(0)
  130. def stop(self):
  131. assert self.server_pid, 'not running'
  132. os.kill(self.server_pid, 15)
  133. os.waitpid(self.server_pid, 0)
  134. self.server_pid = None
  135. self.log.close()
  136. if __name__ == '__main__':
  137. srv = AutoPkgTestSwiftServer()
  138. srv.set_results({'autopkgtest-testing': {
  139. 'testing/i386/d/darkgreen/20150101_100000@': (0, 'darkgreen 1'),
  140. 'testing/i386/g/green/20150101_100000@': (0, 'green 1', {'custom_environment': ['ADT_TEST_TRIGGERS=green']}),
  141. 'testing/i386/l/lightgreen/20150101_100000@': (0, 'lightgreen 1'),
  142. 'testing/i386/l/lightgreen/20150101_100101@': (4, 'lightgreen 2'),
  143. 'testing/i386/l/lightgreen/20150101_100102@': (0, 'lightgreen 3'),
  144. }})
  145. srv.start()
  146. print('Running on http://localhost:8080/autopkgtest-testing')
  147. print('Press Enter to quit.')
  148. sys.stdin.readline()
  149. srv.stop()