parallel-vm.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #!/usr/bin/env python2
  2. #
  3. # Parallel VM test case executor
  4. # Copyright (c) 2014, Jouni Malinen <j@w1.fi>
  5. #
  6. # This software may be distributed under the terms of the BSD license.
  7. # See README for more details.
  8. import fcntl
  9. import os
  10. import subprocess
  11. import sys
  12. import time
  13. def main():
  14. if len(sys.argv) < 2:
  15. sys.exit("Usage: %s <number of VMs> [params..]" % sys.argv[0])
  16. num_servers = int(sys.argv[1])
  17. if num_servers < 1:
  18. sys.exit("Too small number of VMs")
  19. timestamp = int(time.time())
  20. vm = {}
  21. for i in range(0, num_servers):
  22. print("\rStarting virtual machine {}/{}".format(i + 1, num_servers)),
  23. cmd = ['./vm-run.sh', '--ext', 'srv.%d' % (i + 1),
  24. '--split', '%d/%d' % (i + 1, num_servers)] + sys.argv[2:]
  25. vm[i] = {}
  26. vm[i]['proc'] = subprocess.Popen(cmd,
  27. stdin=subprocess.PIPE,
  28. stdout=subprocess.PIPE,
  29. stderr=subprocess.PIPE)
  30. vm[i]['out'] = ""
  31. vm[i]['err'] = ""
  32. vm[i]['pos'] = ""
  33. for stream in [ vm[i]['proc'].stdout, vm[i]['proc'].stderr ]:
  34. fd = stream.fileno()
  35. fl = fcntl.fcntl(fd, fcntl.F_GETFL)
  36. fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
  37. print
  38. while True:
  39. running = False
  40. updated = False
  41. for i in range(0, num_servers):
  42. if not vm[i]['proc']:
  43. continue
  44. if vm[i]['proc'].poll() is not None:
  45. vm[i]['proc'] = None
  46. continue
  47. running = True
  48. try:
  49. err = vm[i]['proc'].stderr.read()
  50. vm[i]['err'] += err
  51. except:
  52. pass
  53. try:
  54. out = vm[i]['proc'].stdout.read()
  55. except:
  56. continue
  57. #print("VM {}: '{}'".format(i, out))
  58. vm[i]['out'] += out
  59. lines = vm[i]['out'].splitlines()
  60. last = [ l for l in lines if l.startswith('START ') ]
  61. if len(last) > 0:
  62. try:
  63. pos = last[-1].split(' ')[2]
  64. vm[i]['pos'] = pos
  65. updated = True
  66. except:
  67. pass
  68. else:
  69. vm[i]['pos'] = ''
  70. if not running:
  71. print("All VMs completed")
  72. break
  73. if updated:
  74. status = {}
  75. for i in range(0, num_servers):
  76. if not vm[i]['proc']:
  77. continue
  78. status[i] = vm[i]['pos']
  79. print status
  80. time.sleep(1)
  81. dir = '/tmp/hwsim-test-logs'
  82. try:
  83. os.mkdir(dir)
  84. except:
  85. pass
  86. with open('{}/{}-parallel.log'.format(dir, timestamp), 'w') as f:
  87. for i in range(0, num_servers):
  88. f.write('VM {}\n{}\n{}\n'.format(i, vm[i]['out'], vm[i]['err']))
  89. started = []
  90. passed = []
  91. failed = []
  92. skipped = []
  93. for i in range(0, num_servers):
  94. lines = vm[i]['out'].splitlines()
  95. started += [ l for l in lines if l.startswith('START ') ]
  96. passed += [ l for l in lines if l.startswith('PASS ') ]
  97. failed += [ l for l in lines if l.startswith('FAIL ') ]
  98. skipped += [ l for l in lines if l.startswith('SKIP ') ]
  99. if len(failed) > 0:
  100. print "Failed test cases:"
  101. for f in failed:
  102. print f.split(' ')[1],
  103. print
  104. print("TOTAL={} PASS={} FAIL={} SKIP={}".format(len(started), len(passed), len(failed), len(skipped)))
  105. if __name__ == "__main__":
  106. main()