From f94594a98eefdd5fc47b870f69818f1a4a6eeb9f Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Wed, 9 Mar 2016 11:04:02 -0600 Subject: [PATCH] Retire old launch-node.py It has served us well, but it's time for the new world order to take over. Change-Id: I72a9f1b1c0f1bd331b5f862f5f69966950ffe963 --- launch/README | 31 ++--- launch/dns.py | 69 +--------- launch/launch-node.py | 268 +++++++++++++++--------------------- launch/shade-launch-node.py | 266 ----------------------------------- launch/utils.py | 27 ---- 5 files changed, 129 insertions(+), 532 deletions(-) mode change 100755 => 100644 launch/launch-node.py delete mode 100644 launch/shade-launch-node.py diff --git a/launch/README b/launch/README index 1236fb36dc..f67fcba467 100644 --- a/launch/README +++ b/launch/README @@ -14,42 +14,31 @@ to a group.) To launch a node in the OpenStack CI account (production servers):: - . ~root/ci-launch/openstackci-rs-nova.sh + export OS_CLOUD=openstackci-rax + export OS_REGION=DFW export FLAVOR="8 GB Performance" export FQDN=servername.openstack.org - sudo puppet cert generate $FQDN cd /opt/system-config/production/launch/ - ./launch-node.py $FQDN --flavor "$FLAVOR" + ./launch-node.py $FQDN --flavor "$FLAVOR" \ + --cloud=$OS_CLOUD --region=$OS_REGION To launch a node in the OpenStack Jenkins account (slave nodes):: - . ~root/ci-launch/openstackjenkins-rs-nova.sh + export OS_CLOUD=openstackjenkins-rax + export OS_REGION=DFW export FQDN=slavename.slave.openstack.org - nova image-list + openstack image list export IMAGE='Ubuntu 12.04 LTS (Precise Pangolin) (PVHVM)' - nova flavor-list + openstack flavor list export FLAVOR="8 GB Performance" - sudo puppet cert generate $FQDN - ./launch-node.py $FQDN --image "$IMAGE" --flavor "$FLAVOR" - -If you are launching a replacement server, you may skip the generate -step and specify the name of an existing puppet cert (as long as the -private key is on this host). - -The server name and cert names may be different and the latter can be -specified with --cert if needed, but launch-node.py will assume they -are the same unless specified. + ./launch-node.py $FQDN --image "$IMAGE" --flavor "$FLAVOR" \ + --cloud=$OS_CLOUD --region=$OS_REGION Manually add the hostname to DNS (the launch script does not do so automatically). Note that this example assumes you've already exported a relevant FQDN and sourced the appropriate API credentials above. -When running outside the official OpenStack CI infrastructure, you -will want to pass --server puppetmaster.example.com otherwise the -new node wil try to register with puppetmaster.openstack.org - and -fail hilariously. - In order for Ansible to be able to send out the Puppet updates, you also need the puppetmaster to accept the root SSH key for the new server. So as root on the puppetmaster: diff --git a/launch/dns.py b/launch/dns.py index a35ceca935..99772cf3f8 100755 --- a/launch/dns.py +++ b/launch/dns.py @@ -18,68 +18,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import argparse -import utils - - -def get_client(): - #TODO use shade - NOVA_USERNAME = os.environ['OS_USERNAME'] - NOVA_PASSWORD = os.environ['OS_PASSWORD'] - NOVA_URL = os.environ['OS_AUTH_URL'] - NOVA_PROJECT_ID = os.environ['OS_TENANT_NAME'] - NOVA_REGION_NAME = os.environ['OS_REGION_NAME'] - - args = [NOVA_USERNAME, NOVA_PASSWORD, NOVA_PROJECT_ID, NOVA_URL] - kwargs = {} - kwargs['region_name'] = NOVA_REGION_NAME - kwargs['service_type'] = 'compute' - from novaclient.v1_1.client import Client - client = Client(*args, **kwargs) - return client - - -def print_dns(client, name): - for server in client.servers.list(): - if server.name != name: - continue - ip4 = utils.get_public_ip(server) - ip6 = utils.get_public_ip(server, 6) - href = utils.get_href(server) - - print - print "Run the following commands to set up DNS:" - print - print ". ~root/rackdns-venv/bin/activate" - print - print ( - "rackdns rdns-create --name %s \\\n" - " --data %s \\\n" - " --server-href %s \\\n" - " --ttl 3600" % ( - server.name, ip6, href)) - print - print ( - "rackdns rdns-create --name %s \\\n" - " --data %s \\\n" - " --server-href %s \\\n" - " --ttl 3600" % ( - server.name, ip4, href)) - print - print ". ~root/ci-launch/openstack-rs-nova.sh" - print - print ( - "rackdns record-create --name %s \\\n" - " --type AAAA --data %s \\\n" - " --ttl 3600 openstack.org" % ( - server.name, ip6)) - print - print ( - "rackdns record-create --name %s \\\n" - " --type A --data %s \\\n" - " --ttl 3600 openstack.org" % ( - server.name, ip4)) def get_href(server): @@ -90,7 +29,7 @@ def get_href(server): return link['href'] -def shade_print_dns(cloud, server): +def print_dns(cloud, server): ip4 = server.public_v4 ip6 = server.public_v6 @@ -137,8 +76,10 @@ def main(): parser.add_argument("name", help="server name") options = parser.parse_args() - client = get_client() - print_dns(client, options.name) + import shade + cloud = shade.openstack_cloud() + server = cloud.get_server(options.name) + print_dns(cloud, server) if __name__ == '__main__': main() diff --git a/launch/launch-node.py b/launch/launch-node.py old mode 100755 new mode 100644 index d162a6ceba..fd84aa89b2 --- a/launch/launch-node.py +++ b/launch/launch-node.py @@ -18,55 +18,37 @@ # See the License for the specific language governing permissions and # limitations under the License. -import sys +import argparse import os +import subprocess +import sys +import tempfile import time import traceback -import argparse import dns import utils -NOVA_USERNAME = os.environ['OS_USERNAME'] -NOVA_PASSWORD = os.environ['OS_PASSWORD'] -NOVA_URL = os.environ['OS_AUTH_URL'] -NOVA_PROJECT_ID = os.environ['OS_TENANT_NAME'] -NOVA_REGION_NAME = os.environ['OS_REGION_NAME'] -NOVA_SERVICE_NAME = os.environ.get('OS_SERVICE_NAME') -NOVACLIENT_INSECURE = os.getenv('NOVACLIENT_INSECURE', None) -IPV6 = os.environ.get('IPV6', '0') is 1 +import os_client_config +import paramiko +import shade SCRIPT_DIR = os.path.dirname(sys.argv[0]) - -def get_client(): - args = [NOVA_USERNAME, NOVA_PASSWORD, NOVA_PROJECT_ID, NOVA_URL] - kwargs = {} - kwargs['region_name'] = NOVA_REGION_NAME - kwargs['service_type'] = 'compute' - if NOVA_SERVICE_NAME: - kwargs['service_name'] = NOVA_SERVICE_NAME - - if NOVACLIENT_INSECURE: - kwargs['insecure'] = True - - from novaclient.v1_1.client import Client - client = Client(*args, **kwargs) - return client +try: + # This unactionable warning does not need to be printed over and over. + import requests.packages.urllib3 + requests.packages.urllib3.disable_warnings() +except: + pass -def bootstrap_server(server, admin_pass, key, cert, environment, name, - puppetmaster, volume, floating_ip_pool): - ip = utils.get_public_ip(server, floating_ip_pool=floating_ip_pool) - if not ip: - raise Exception("Unable to find public ip of server") +def bootstrap_server(server, key, name, volume, keep): - ssh_kwargs = {} - if key: - ssh_kwargs['pkey'] = key - else: - ssh_kwargs['password'] = admin_pass + ip = server.public_v4 + ssh_kwargs = dict(pkey=key) + print 'Public IP', ip for username in ['root', 'ubuntu', 'centos', 'admin']: ssh_client = utils.ssh_connect(ip, username, ssh_kwargs, timeout=600) if ssh_client: @@ -86,7 +68,7 @@ def bootstrap_server(server, admin_pass, key, cert, environment, name, ssh_client = utils.ssh_connect(ip, 'root', ssh_kwargs, timeout=600) - if IPV6: + if server.public_v6: ssh_client.ssh('ping6 -c5 -Q 0x10 review.openstack.org ' '|| ping6 -c5 -Q 0x10 wiki.openstack.org') @@ -99,40 +81,50 @@ def bootstrap_server(server, admin_pass, key, cert, environment, name, 'mount_volume.sh') ssh_client.ssh('bash -x mount_volume.sh') + # This next chunk should really exist as a playbook, but whatev ssh_client.scp(os.path.join(SCRIPT_DIR, '..', 'install_puppet.sh'), 'install_puppet.sh') ssh_client.ssh('bash -x install_puppet.sh') - certname = cert[:(0 - len('.pem'))] - ssh_client.ssh("mkdir -p /var/lib/puppet/ssl/certs") - ssh_client.ssh("mkdir -p /var/lib/puppet/ssl/private_keys") - ssh_client.ssh("mkdir -p /var/lib/puppet/ssl/public_keys") - ssh_client.ssh("chown -R puppet:root /var/lib/puppet/ssl") - ssh_client.ssh("chown -R puppet:puppet /var/lib/puppet/ssl/private_keys") - ssh_client.ssh("chmod 0771 /var/lib/puppet/ssl") - ssh_client.ssh("chmod 0755 /var/lib/puppet/ssl/certs") - ssh_client.ssh("chmod 0750 /var/lib/puppet/ssl/private_keys") - ssh_client.ssh("chmod 0755 /var/lib/puppet/ssl/public_keys") + shortname = name.split('.')[0] + with ssh_client.open('/etc/hosts', 'w') as f: + f.write('127.0.0.1 localhost\n') + f.write('127.0.1.1 %s %s\n' % (name, shortname)) + with ssh_client.open('/etc/hostname', 'w') as f: + f.write('%s\n' % (shortname,)) + ssh_client.ssh("hostname %s" % (name,)) - for ssldir in ['/var/lib/puppet/ssl/certs/', - '/var/lib/puppet/ssl/private_keys/', - '/var/lib/puppet/ssl/public_keys/']: - ssh_client.scp(os.path.join(ssldir, cert), - os.path.join(ssldir, cert)) + # Write out the private SSH key we generated + key_file = tempfile.NamedTemporaryFile(delete=not keep) + key.write_private_key(key_file) + key_file.flush() - ssh_client.scp("/var/lib/puppet/ssl/crl.pem", - "/var/lib/puppet/ssl/crl.pem") - ssh_client.scp("/var/lib/puppet/ssl/certs/ca.pem", - "/var/lib/puppet/ssl/certs/ca.pem") + # Write out inventory + inventory_file = tempfile.NamedTemporaryFile(delete=not keep) + inventory_file.write("{host} ansible_host={ip} ansible_user=root".format( + host=server.id, ip=server.interface_ip)) + inventory_file.flush() - (rc, output) = ssh_client.ssh( - "puppet agent " - "--environment %s " - "--server %s " - "--detailed-exitcodes " - "--no-daemonize --verbose --onetime --pluginsync true " - "--certname %s" % (environment, puppetmaster, certname), error_ok=True) - utils.interpret_puppet_exitcodes(rc, output) + ansible_cmd = [ + 'ansible-playbook', + '-i', inventory_file.name, '-l', server.id, + '--private-key={key}'.format(key=key_file.name), + "--ssh-common-args='-o StrictHostKeyChecking=no'", + ] + + # Run the remote puppet apply playbook limited to just this server + # we just created + try: + print subprocess.check_output( + ansible_cmd + [ + os.path.join( + SCRIPT_DIR, '..', 'playbooks', + 'remote_puppet_adhoc.yaml')], + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + print "Subprocess failed" + print e.output + raise try: ssh_client.ssh("reboot") @@ -145,94 +137,70 @@ def bootstrap_server(server, admin_pass, key, cert, environment, name, raise -def build_server( - client, name, image, flavor, cert, environment, puppetmaster, volume, - keep, net_label, floating_ip_pool, boot_from_volume): +def build_server(cloud, name, image, flavor, + volume, keep, network, boot_from_volume, config_drive): key = None server = None - create_kwargs = dict(image=image, flavor=flavor, name=name) + create_kwargs = dict(image=image, flavor=flavor, name=name, + reuse_ips=False, wait=True, + boot_from_volume=boot_from_volume, + network=network, + config_drive=config_drive) - if boot_from_volume: - block_mapping = [{ - 'boot_index': '0', - 'delete_on_termination': True, - 'destination_type': 'volume', - 'uuid': image.id, - 'source_type': 'image', - 'volume_size': '50', - }] - create_kwargs['image'] = None - create_kwargs['block_device_mapping_v2'] = block_mapping - - if net_label: - nics = [] - for net in client.networks.list(): - if net.label == net_label: - nics.append({'net-id': net.id}) - create_kwargs['nics'] = nics + if volume: + create_kwargs['volumes'] = [volume] key_name = 'launch-%i' % (time.time()) - if 'os-keypairs' in utils.get_extensions(client): - print "Adding keypair" - key, kp = utils.add_keypair(client, key_name) - create_kwargs['key_name'] = key_name + key = paramiko.RSAKey.generate(2048) + public_key = key.get_name() + ' ' + key.get_base64() + cloud.create_keypair(key_name, public_key) + create_kwargs['key_name'] = key_name try: - server = client.servers.create(**create_kwargs) + server = cloud.create_server(**create_kwargs) except Exception: try: - kp.delete() + cloud.delete_keypair(key_name) except Exception: print "Exception encountered deleting keypair:" traceback.print_exc() raise try: - admin_pass = server.adminPass - server = utils.wait_for_resource(server) - if volume: - vobj = client.volumes.create_server_volume( - server.id, volume, None) - if not vobj: - raise Exception("Couldn't attach volume") + cloud.delete_keypair(key_name) - bootstrap_server(server, admin_pass, key, cert, environment, name, - puppetmaster, volume, floating_ip_pool) - print('UUID=%s\nIPV4=%s\nIPV6=%s\n' % (server.id, - server.accessIPv4, - server.accessIPv6)) - if key: - kp.delete() + server = cloud.get_openstack_vars(server) + bootstrap_server(server, key, name, volume, keep) + print('UUID=%s\nIPV4=%s\nIPV6=%s\n' % ( + server.id, server.public_v4, server.public_v6)) except Exception: try: if keep: print "Server failed to build, keeping as requested." else: - utils.delete_server(server) + cloud.delete_server(server.id, delete_ips=True) except Exception: print "Exception encountered deleting server:" traceback.print_exc() # Raise the important exception that started this raise + return server + def main(): parser = argparse.ArgumentParser() parser.add_argument("name", help="server name") + parser.add_argument("--cloud", dest="cloud", required=True, + help="cloud name") + parser.add_argument("--region", dest="region", + help="cloud region") parser.add_argument("--flavor", dest="flavor", default='1GB', help="name (or substring) of flavor") parser.add_argument("--image", dest="image", default="Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)", help="image name") - parser.add_argument("--environment", dest="environment", - default="production", - help="puppet environment name") - parser.add_argument("--cert", dest="cert", - help="name of signed puppet certificate file (e.g., " - "hostname.example.com.pem)") - parser.add_argument("--server", dest="server", help="Puppetmaster to use.", - default="puppetmaster.openstack.org") parser.add_argument("--volume", dest="volume", help="UUID of volume to attach to the new server.", default=None) @@ -244,58 +212,50 @@ def main(): help="Don't clean up or delete the server on error.", action='store_true', default=False) - parser.add_argument("--net-label", dest="net_label", default='', + parser.add_argument("--verbose", dest="verbose", default=False, + action='store_true', + help="Be verbose about logging cloud actions") + parser.add_argument("--network", dest="network", default=None, help="network label to attach instance to") - parser.add_argument("--fip-pool", dest="floating_ip_pool", default=None, - help="pool to assign floating IP from") + parser.add_argument("--config-drive", dest="config_drive", + help="Boot with config_drive attached.", + action='store_true', + default=True) options = parser.parse_args() - client = get_client() + shade.simple_logging(debug=options.verbose) - if options.cert: - cert = options.cert + cloud_kwargs = {} + if options.region: + cloud_kwargs['region_name'] = options.region + cloud_config = os_client_config.OpenStackConfig().get_one_cloud( + options.cloud, **cloud_kwargs) + + cloud = shade.OpenStackCloud(cloud_config) + + flavor = cloud.get_flavor(options.flavor) + if flavor: + print "Found flavor", flavor.name else: - cert = options.name + ".pem" - - if not os.path.exists(os.path.join("/var/lib/puppet/ssl/private_keys", - cert)): - raise Exception("Please specify the name of a signed puppet cert.") - - flavors = [f for f in client.flavors.list() - if options.flavor in (f.name, f.id)] - flavor = flavors[0] - print "Found flavor", flavor - - images = [i for i in client.images.list() - if (options.image.lower() in (i.id, i.name.lower()) and - not i.name.endswith('(Kernel)') and - not i.name.endswith('(Ramdisk)'))] - - if len(images) > 1: - print "Ambiguous image name; matches:" - for i in images: + print "Unable to find matching flavor; flavor list:" + for i in cloud.list_flavors(): print i.name sys.exit(1) - if len(images) == 0: + image = cloud.get_image_exclude(options.image, 'deprecated') + if image: + print "Found image", image.name + else: print "Unable to find matching image; image list:" - for i in client.images.list(): + for i in cloud.list_images(): print i.name sys.exit(1) - image = images[0] - print "Found image", image - - if options.volume: - print "The --volume option does not support cinder; until it does" - print "it should not be used." - sys.exit(1) - - build_server(client, options.name, image, flavor, cert, - options.environment, options.server, options.volume, - options.keep, options.net_label, options.floating_ip_pool, - options.boot_from_volume) - dns.print_dns(client, options.name) + server = build_server(cloud, options.name, image, flavor, + options.volume, options.keep, + options.network, options.boot_from_volume, + options.config_drive) + dns.print_dns(cloud, server) # Remove the ansible inventory cache so that next run finds the new # server if os.path.exists('/var/cache/ansible-inventory/ansible-inventory.cache'): diff --git a/launch/shade-launch-node.py b/launch/shade-launch-node.py deleted file mode 100644 index 6a7d13ba85..0000000000 --- a/launch/shade-launch-node.py +++ /dev/null @@ -1,266 +0,0 @@ -#!/usr/bin/env python - -# Launch a new OpenStack project infrastructure node. - -# Copyright (C) 2011-2012 OpenStack LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import os -import subprocess -import sys -import tempfile -import time -import traceback - -import dns -import utils - -import os_client_config -import paramiko -import shade - -SCRIPT_DIR = os.path.dirname(sys.argv[0]) - -try: - # This unactionable warning does not need to be printed over and over. - import requests.packages.urllib3 - requests.packages.urllib3.disable_warnings() -except: - pass - - -def bootstrap_server(server, key, name, volume, keep): - - ip = server.public_v4 - ssh_kwargs = dict(pkey=key) - - print 'Public IP', ip - for username in ['root', 'ubuntu', 'centos', 'admin']: - ssh_client = utils.ssh_connect(ip, username, ssh_kwargs, timeout=600) - if ssh_client: - break - - if not ssh_client: - raise Exception("Unable to log in via SSH") - - # cloud-init puts the "please log in as user foo" message and - # subsequent exit() in root's authorized_keys -- overwrite it with - # a normal version to get root login working again. - if username != 'root': - ssh_client.ssh("sudo cp ~/.ssh/authorized_keys" - " ~root/.ssh/authorized_keys") - ssh_client.ssh("sudo chmod 644 ~root/.ssh/authorized_keys") - ssh_client.ssh("sudo chown root.root ~root/.ssh/authorized_keys") - - ssh_client = utils.ssh_connect(ip, 'root', ssh_kwargs, timeout=600) - - if server.public_v6: - ssh_client.ssh('ping6 -c5 -Q 0x10 review.openstack.org ' - '|| ping6 -c5 -Q 0x10 wiki.openstack.org') - - ssh_client.scp(os.path.join(SCRIPT_DIR, '..', 'make_swap.sh'), - 'make_swap.sh') - ssh_client.ssh('bash -x make_swap.sh') - - if volume: - ssh_client.scp(os.path.join(SCRIPT_DIR, '..', 'mount_volume.sh'), - 'mount_volume.sh') - ssh_client.ssh('bash -x mount_volume.sh') - - # This next chunk should really exist as a playbook, but whatev - ssh_client.scp(os.path.join(SCRIPT_DIR, '..', 'install_puppet.sh'), - 'install_puppet.sh') - ssh_client.ssh('bash -x install_puppet.sh') - - shortname = name.split('.')[0] - with ssh_client.open('/etc/hosts', 'w') as f: - f.write('127.0.0.1 localhost\n') - f.write('127.0.1.1 %s %s\n' % (name, shortname)) - with ssh_client.open('/etc/hostname', 'w') as f: - f.write('%s\n' % (shortname,)) - ssh_client.ssh("hostname %s" % (name,)) - - # Write out the private SSH key we generated - key_file = tempfile.NamedTemporaryFile(delete=not keep) - key.write_private_key(key_file) - key_file.flush() - - # Write out inventory - inventory_file = tempfile.NamedTemporaryFile(delete=not keep) - inventory_file.write("{host} ansible_host={ip} ansible_user=root".format( - host=server.id, ip=server.interface_ip)) - inventory_file.flush() - - ansible_cmd = [ - 'ansible-playbook', - '-i', inventory_file.name, '-l', server.id, - '--private-key={key}'.format(key=key_file.name), - "--ssh-common-args='-o StrictHostKeyChecking=no'", - ] - - # Run the remote puppet apply playbook limited to just this server - # we just created - try: - print subprocess.check_output( - ansible_cmd + [ - os.path.join( - SCRIPT_DIR, '..', 'playbooks', - 'remote_puppet_adhoc.yaml')], - stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: - print "Subprocess failed" - print e.output - raise - - try: - ssh_client.ssh("reboot") - except Exception as e: - # Some init system kill the connection too fast after reboot. - # Deal with it by ignoring ssh errors when rebooting. - if e.rc == -1: - pass - else: - raise - - -def build_server(cloud, name, image, flavor, - volume, keep, network, boot_from_volume, config_drive): - key = None - server = None - - create_kwargs = dict(image=image, flavor=flavor, name=name, - reuse_ips=False, wait=True, - boot_from_volume=boot_from_volume, - network=network, - config_drive=config_drive) - - if volume: - create_kwargs['volumes'] = [volume] - - key_name = 'launch-%i' % (time.time()) - key = paramiko.RSAKey.generate(2048) - public_key = key.get_name() + ' ' + key.get_base64() - cloud.create_keypair(key_name, public_key) - create_kwargs['key_name'] = key_name - - try: - server = cloud.create_server(**create_kwargs) - except Exception: - try: - cloud.delete_keypair(key_name) - except Exception: - print "Exception encountered deleting keypair:" - traceback.print_exc() - raise - - try: - cloud.delete_keypair(key_name) - - server = cloud.get_openstack_vars(server) - bootstrap_server(server, key, name, volume, keep) - print('UUID=%s\nIPV4=%s\nIPV6=%s\n' % ( - server.id, server.public_v4, server.public_v6)) - except Exception: - try: - if keep: - print "Server failed to build, keeping as requested." - else: - cloud.delete_server(server.id, delete_ips=True) - except Exception: - print "Exception encountered deleting server:" - traceback.print_exc() - # Raise the important exception that started this - raise - - return server - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument("name", help="server name") - parser.add_argument("--cloud", dest="cloud", required=True, - help="cloud name") - parser.add_argument("--region", dest="region", - help="cloud region") - parser.add_argument("--flavor", dest="flavor", default='1GB', - help="name (or substring) of flavor") - parser.add_argument("--image", dest="image", - default="Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)", - help="image name") - parser.add_argument("--volume", dest="volume", - help="UUID of volume to attach to the new server.", - default=None) - parser.add_argument("--boot-from-volume", dest="boot_from_volume", - help="Create a boot volume for the server and use it.", - action='store_true', - default=False) - parser.add_argument("--keep", dest="keep", - help="Don't clean up or delete the server on error.", - action='store_true', - default=False) - parser.add_argument("--verbose", dest="verbose", default=False, - action='store_true', - help="Be verbose about logging cloud actions") - parser.add_argument("--network", dest="network", default=None, - help="network label to attach instance to") - parser.add_argument("--config-drive", dest="config_drive", - help="Boot with config_drive attached.", - action='store_true', - default=True) - options = parser.parse_args() - - shade.simple_logging(debug=options.verbose) - - cloud_kwargs = {} - if options.region: - cloud_kwargs['region_name'] = options.region - cloud_config = os_client_config.OpenStackConfig().get_one_cloud( - options.cloud, **cloud_kwargs) - - cloud = shade.OpenStackCloud(cloud_config) - - flavor = cloud.get_flavor(options.flavor) - if flavor: - print "Found flavor", flavor.name - else: - print "Unable to find matching flavor; flavor list:" - for i in cloud.list_flavors(): - print i.name - sys.exit(1) - - image = cloud.get_image_exclude(options.image, 'deprecated') - if image: - print "Found image", image.name - else: - print "Unable to find matching image; image list:" - for i in cloud.list_images(): - print i.name - sys.exit(1) - - server = build_server(cloud, options.name, image, flavor, - options.volume, options.keep, - options.network, options.boot_from_volume, - options.config_drive) - dns.shade_print_dns(cloud, server) - # Remove the ansible inventory cache so that next run finds the new - # server - if os.path.exists('/var/cache/ansible-inventory/ansible-inventory.cache'): - os.unlink('/var/cache/ansible-inventory/ansible-inventory.cache') - os.system('/usr/local/bin/expand-groups.sh') - -if __name__ == '__main__': - main() diff --git a/launch/utils.py b/launch/utils.py index 401b19c2d9..ef2c097a7c 100644 --- a/launch/utils.py +++ b/launch/utils.py @@ -19,7 +19,6 @@ # limitations under the License. import time -import traceback import socket import paramiko @@ -37,32 +36,6 @@ def iterate_timeout(max_seconds, purpose): raise Exception("Timeout waiting for %s" % purpose) -def wait_for_resource(wait_resource): - last_progress = None - last_status = None - # It can take a _very_ long time for Rackspace 1.0 to save an image - for count in iterate_timeout(21600, "waiting for %s" % wait_resource): - try: - resource = wait_resource.manager.get(wait_resource.id) - except: - print "Unable to list resources, will retry" - traceback.print_exc() - time.sleep(5) - continue - - # In Rackspace v1.0, there is no progress attribute while queued - if hasattr(resource, 'progress'): - if (last_progress != resource.progress - or last_status != resource.status): - print resource.status, resource.progress - last_progress = resource.progress - elif last_status != resource.status: - print resource.status - last_status = resource.status - if resource.status == 'ACTIVE': - return resource - - def ssh_connect(ip, username, connect_kwargs={}, timeout=60): # HPcloud may return errno 111 for about 30 seconds after adding the IP for count in iterate_timeout(timeout, "ssh access"):