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
This commit is contained in:
Monty Taylor 2016-03-09 11:04:02 -06:00
parent e14471dcc6
commit f94594a98e
5 changed files with 129 additions and 532 deletions

View File

@ -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:

View File

@ -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()

268
launch/launch-node.py Executable file → Normal file
View File

@ -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'):

View File

@ -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()

View File

@ -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"):