1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-28 03:08:14 +00:00
gns3-server/cloud-image/create_image.py
Kieron Bulloch 8b3c5c54a4 Adding GNS3-server code source info to default image name.
Fixing spacing, etc before pull request.
2014-06-17 00:02:17 -04:00

267 lines
7.6 KiB
Python

""" Create a new GNS3 Server Rackspace image with the provided options. """
import argparse
import getpass
import os
import sys
import uuid
from fabric.api import env
from fabric.contrib.files import exists
from github import Github
from novaclient.v1_1 import client
from time import sleep
POLL_SEC = 30
GNS3_REPO = 'gns3/gns3-server'
PLANC_REPO = 'planctechnologies/gns3-server'
OS_AUTH_URL = 'https://identity.api.rackspacecloud.com/v2.0/'
UBUNTU_BASE_ID = '5cc098a5-7286-4b96-b3a2-49f4c4f82537'
def main():
"""
Get the user options and perform the image creation.
Creates a new instance, installs the required software, creates an image
from the instance, and then deletes the instance.
"""
g = Github()
args = get_cli_args()
if args.username:
username = args.username
else:
if 'OS_USERNAME' in os.environ:
username = os.environ.get('OS_USERNAME')
else:
username = raw_input('Enter Rackspace username: ')
if args.password:
password = args.password
else:
if 'OS_PASSWORD' in os.environ:
password = os.environ.get('OS_PASSWORD')
else:
password = getpass.getpass('Enter Rackspace password: ')
if args.tenant:
tenant = args.tenant
else:
if 'OS_TENANT_NAME' in os.environ:
tenant = os.environ.get('OS_TENANT_NAME')
else:
tenant = raw_input('Enter Rackspace Tenant ID: ')
if args.region:
region = args.region
else:
if 'OS_REGION_NAME' in os.environ:
region = os.environ.get('OS_REGION_NAME')
else:
region = raw_input('Enter Rackspace Region Name: ')
if args.source == 'release':
# get the list of releases, present them to the user, save the url
repo = g.get_repo('gns3/gns3-server')
keyword = "tag"
i = 1
branch_opts = {}
for tag in repo.get_tags():
branch_opts[i] = tag.name
i += 1
elif args.source == 'dev':
# get the list of dev branches, present them to the user, save the url
repo = g.get_repo('planctechnologies/gns3-server')
keyword = "branch"
i = 1
branch_opts = {}
for branch in repo.get_branches():
branch_opts[i] = branch.name
i += 1
prompt_text = "Select a %s" % keyword
selected_branch = prompt_user_select(branch_opts, prompt_text)
if args.image_name:
image_name = args.image_name
else:
image_name = "gns3-%s-%s-%s" % (args.source, selected_branch,
uuid.uuid4().hex[0:4])
if args.on_boot:
on_boot = True
else:
on_boot = False
startup_script = create_script(repo.svn_url, selected_branch, on_boot)
server_name = uuid.uuid4().hex
instance = create_instance(username, password, tenant, region, server_name,
startup_script)
passwd = uuid.uuid4().hex
instance.change_password(passwd)
# wait for the password change to be processed
sleep(10)
env.host_string = str(instance.accessIPv4)
env.user = "root"
env.password = passwd
sys.stdout.write("Installing software...")
sys.stdout.flush()
while 1:
if exists('/tmp/gns-install-complete'):
break
sleep(20)
sys.stdout.write(".")
sys.stdout.flush()
print("Done.")
image_id = create_image(username, password, tenant, region, instance,
image_name)
instance.delete()
def prompt_user_select(opts, text="Please select"):
""" Ask the user to select an option from the provided list. """
print("%s" % text)
print("=" * len(text))
for o in opts:
print("(%s)\t%s" % (o, opts[o]))
while 1:
selected = raw_input("Select: ")
try:
return opts[int(selected)]
except (KeyError, ValueError):
print("Invalid selection. Try again")
def create_instance(username, password, tenant, region, server_name, script,
auth_url=OS_AUTH_URL):
""" Create a new instance. """
sys.stdout.write("Creating instance...")
sys.stdout.flush()
nc = client.Client(username, password, tenant, auth_url,
region_name=region)
server = nc.servers.create(server_name, UBUNTU_BASE_ID, 2,
config_drive=True, userdata=script)
server_id = server.id
while 1:
server = nc.servers.get(server_id)
if server.status == 'ACTIVE':
break
sleep(20)
sys.stdout.write(".")
sys.stdout.flush()
print "Done."
return server
def create_script(git_url, git_branch, on_boot):
""" Create the start-up script. """
# Consider using jinja or similar if this becomes unwieldly
script = "#!/bin/bash\n\n"
script += "export DEBIAN_FRONTEND=noninteractive\n\n"
script += "apt-get -y update\n"
script += "apt-get -o Dpkg::Options::=\"--force-confnew\" --force-yes -fuy dist-upgrade\n\n"
reqs = ["git", "python3-setuptools", "python3-netifaces", "python3-pip"]
for r in reqs:
script += "apt-get -y install %s\n" % r
script += "\n"
script += "mkdir -p /opt/gns3\n"
script += "pushd /opt/gns3\n"
script += "git clone --branch %s %s\n" % (git_branch, git_url)
script += "cd gns3-server\n"
script += "pip3 install tornado\n"
script += "pip3 install pyzmq\n"
script += "pip3 install jsonschema\n"
script += "python3 ./setup.py install\n\n"
if on_boot:
script += "echo '/usr/local/bin/gns3-server' >> /etc/rc.local\n\n"
script += "touch /tmp/gns-install-complete\n\n"
return script
def create_image(username, password, tenant, region, server,
image_name, auth_url=OS_AUTH_URL):
""" Create a Rackspace image based on the server instance. """
nc = client.Client(username, password, tenant, auth_url,
region_name=region)
sys.stdout.write("Creating image %s..." % image_name)
sys.stdout.flush()
image_id = server.create_image(image_name)
while 1:
server = nc.servers.get(server.id)
if getattr(server, 'OS-EXT-STS:task_state') is None:
break
sleep(20)
sys.stdout.write(".")
sys.stdout.flush()
print("Done.")
return image_id
def get_cli_args():
""" Parse the CLI input. """
parser = argparse.ArgumentParser(
description='Create a new GNS3 image',
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument(
'--rackspace_username', dest='username', action='store'
)
parser.add_argument(
'--rackspace_password', dest='password', action='store'
)
parser.add_argument(
'--rackspace_tenant', dest='tenant', action='store'
)
parser.add_argument(
'--rackspace_region', dest='region', action='store'
)
parser.add_argument('--source', dest='source', action='store',
choices=['release', 'dev'], default='release',
help='specify the gns3-server source location')
parser.add_argument('--branch', dest='branch', action='store',
help='specify the branch/tag')
parser.add_argument('--start-on-boot', dest='on_boot', action='store_true',
help='start the GNS3-server when the image boots',
default=False)
parser.add_argument('--image-name', dest='image_name', action='store',
help='the name of the image to be created')
return parser.parse_args()
if __name__ == "__main__":
main()