deployment.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #!/usr/bin/env python
  2. import os, sys, re, json, requests, base64
  3. from subprocess import call
  4. from fabric import api
  5. from fabric.api import cd, run, put, sudo
  6. from os import environ as env
  7. from datetime import datetime
  8. from time import sleep
  9. # Remove SSH private key as it needs more processing
  10. CONFIG = json.loads(re.sub(r'("DOCKER_CI_KEY".+?"(.+?)",)','',
  11. env['CONFIG_JSON'], flags=re.DOTALL))
  12. # Populate environment variables
  13. for key in CONFIG:
  14. env[key] = CONFIG[key]
  15. # Load SSH private key
  16. env['DOCKER_CI_KEY'] = re.sub('^.+"DOCKER_CI_KEY".+?"(.+?)".+','\\1',
  17. env['CONFIG_JSON'],flags=re.DOTALL)
  18. DROPLET_NAME = env.get('DROPLET_NAME','docker-ci')
  19. TIMEOUT = 120 # Seconds before timeout droplet creation
  20. IMAGE_ID = 1004145 # Docker on Ubuntu 13.04
  21. REGION_ID = 4 # New York 2
  22. SIZE_ID = 62 # memory 2GB
  23. DO_IMAGE_USER = 'root' # Image user on Digital Ocean
  24. API_URL = 'https://api.digitalocean.com/'
  25. DOCKER_PATH = '/go/src/github.com/dotcloud/docker'
  26. DOCKER_CI_PATH = '/docker-ci'
  27. CFG_PATH = '{}/buildbot'.format(DOCKER_CI_PATH)
  28. class DigitalOcean():
  29. def __init__(self, key, client):
  30. '''Set default API parameters'''
  31. self.key = key
  32. self.client = client
  33. self.api_url = API_URL
  34. def api(self, cmd_path, api_arg={}):
  35. '''Make api call'''
  36. api_arg.update({'api_key':self.key, 'client_id':self.client})
  37. resp = requests.get(self.api_url + cmd_path, params=api_arg).text
  38. resp = json.loads(resp)
  39. if resp['status'] != 'OK':
  40. raise Exception(resp['error_message'])
  41. return resp
  42. def droplet_data(self, name):
  43. '''Get droplet data'''
  44. data = self.api('droplets')
  45. data = [droplet for droplet in data['droplets']
  46. if droplet['name'] == name]
  47. return data[0] if data else {}
  48. def json_fmt(data):
  49. '''Format json output'''
  50. return json.dumps(data, sort_keys = True, indent = 2)
  51. do = DigitalOcean(env['DO_API_KEY'], env['DO_CLIENT_ID'])
  52. # Get DROPLET_NAME data
  53. data = do.droplet_data(DROPLET_NAME)
  54. # Stop processing if DROPLET_NAME exists on Digital Ocean
  55. if data:
  56. print ('Droplet: {} already deployed. Not further processing.'
  57. .format(DROPLET_NAME))
  58. exit(1)
  59. # Create droplet
  60. do.api('droplets/new', {'name':DROPLET_NAME, 'region_id':REGION_ID,
  61. 'image_id':IMAGE_ID, 'size_id':SIZE_ID,
  62. 'ssh_key_ids':[env['DOCKER_KEY_ID']]})
  63. # Wait for droplet to be created.
  64. start_time = datetime.now()
  65. while (data.get('status','') != 'active' and (
  66. datetime.now()-start_time).seconds < TIMEOUT):
  67. data = do.droplet_data(DROPLET_NAME)
  68. print data['status']
  69. sleep(3)
  70. # Wait for the machine to boot
  71. sleep(15)
  72. # Get droplet IP
  73. ip = str(data['ip_address'])
  74. print 'droplet: {} ip: {}'.format(DROPLET_NAME, ip)
  75. # Create docker-ci ssh private key so docker-ci docker container can communicate
  76. # with its EC2 instance
  77. os.makedirs('/root/.ssh')
  78. open('/root/.ssh/id_rsa','w').write(env['DOCKER_CI_KEY'])
  79. os.chmod('/root/.ssh/id_rsa',0600)
  80. open('/root/.ssh/config','w').write('StrictHostKeyChecking no\n')
  81. api.env.host_string = ip
  82. api.env.user = DO_IMAGE_USER
  83. api.env.key_filename = '/root/.ssh/id_rsa'
  84. # Correct timezone
  85. sudo('echo "America/Los_Angeles" >/etc/timezone')
  86. sudo('dpkg-reconfigure --frontend noninteractive tzdata')
  87. # Load public docker-ci key
  88. sudo("echo '{}' >> /root/.ssh/authorized_keys".format(env['DOCKER_CI_PUB']))
  89. # Create docker nightly release credentials file
  90. credentials = {
  91. 'AWS_ACCESS_KEY': env['PKG_ACCESS_KEY'],
  92. 'AWS_SECRET_KEY': env['PKG_SECRET_KEY'],
  93. 'GPG_PASSPHRASE': env['PKG_GPG_PASSPHRASE']}
  94. open(DOCKER_CI_PATH + '/nightlyrelease/release_credentials.json', 'w').write(
  95. base64.b64encode(json.dumps(credentials)))
  96. # Transfer docker
  97. sudo('mkdir -p ' + DOCKER_CI_PATH)
  98. sudo('chown {}.{} {}'.format(DO_IMAGE_USER, DO_IMAGE_USER, DOCKER_CI_PATH))
  99. call('/usr/bin/rsync -aH {} {}@{}:{}'.format(DOCKER_CI_PATH, DO_IMAGE_USER, ip,
  100. os.path.dirname(DOCKER_CI_PATH)), shell=True)
  101. # Install Docker and Buildbot dependencies
  102. sudo('mkdir /mnt/docker; ln -s /mnt/docker /var/lib/docker')
  103. sudo('apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9')
  104. sudo('echo deb https://get.docker.io/ubuntu docker main >'
  105. ' /etc/apt/sources.list.d/docker.list')
  106. sudo('echo -e "deb http://archive.ubuntu.com/ubuntu raring main universe\n'
  107. 'deb http://us.archive.ubuntu.com/ubuntu/ raring-security main universe\n"'
  108. ' > /etc/apt/sources.list; apt-get update')
  109. sudo('DEBIAN_FRONTEND=noninteractive apt-get install -q -y wget python-dev'
  110. ' python-pip supervisor git mercurial linux-image-extra-$(uname -r)'
  111. ' aufs-tools make libfontconfig libevent-dev libsqlite3-dev libssl-dev')
  112. sudo('wget -O - https://go.googlecode.com/files/go1.2.linux-amd64.tar.gz | '
  113. 'tar -v -C /usr/local -xz; ln -s /usr/local/go/bin/go /usr/bin/go')
  114. sudo('GOPATH=/go go get -d github.com/dotcloud/docker')
  115. sudo('pip install -r {}/requirements.txt'.format(CFG_PATH))
  116. # Install docker and testing dependencies
  117. sudo('apt-get install -y -q lxc-docker')
  118. sudo('curl -s https://phantomjs.googlecode.com/files/'
  119. 'phantomjs-1.9.1-linux-x86_64.tar.bz2 | tar jx -C /usr/bin'
  120. ' --strip-components=2 phantomjs-1.9.1-linux-x86_64/bin/phantomjs')
  121. # Build docker-ci containers
  122. sudo('cd {}; docker build -t docker .'.format(DOCKER_PATH))
  123. sudo('cd {}; docker build -t docker-ci .'.format(DOCKER_CI_PATH))
  124. sudo('cd {}/nightlyrelease; docker build -t dockerbuilder .'.format(
  125. DOCKER_CI_PATH))
  126. sudo('cd {}/registry-coverage; docker build -t registry_coverage .'.format(
  127. DOCKER_CI_PATH))
  128. # Download docker-ci testing container
  129. sudo('docker pull mzdaniel/test_docker')
  130. # Setup buildbot
  131. sudo('mkdir /data')
  132. sudo('{0}/setup.sh root {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10}'
  133. ' {11} {12}'.format(CFG_PATH, DOCKER_PATH, env['BUILDBOT_PWD'],
  134. env['IRC_PWD'], env['IRC_CHANNEL'], env['SMTP_USER'],
  135. env['SMTP_PWD'], env['EMAIL_RCP'], env['REGISTRY_USER'],
  136. env['REGISTRY_PWD'], env['REGISTRY_BUCKET'], env['REGISTRY_ACCESS_KEY'],
  137. env['REGISTRY_SECRET_KEY']))
  138. # Preventively reboot docker-ci daily
  139. sudo('ln -s /sbin/reboot /etc/cron.daily')