Merge pull request #12749 from gtmanfred/nova

Split request_instance into it's own function for nova and openstack drivers
This commit is contained in:
Joseph Hall 2014-05-13 17:05:14 -06:00
commit b5754dc147
2 changed files with 161 additions and 374 deletions

View File

@ -49,12 +49,6 @@ examples could be set up in the cloud configuration at
config_profile: my_openstack_profile
ssh_key_name: mykey
# The OpenStack Nova network UUIDs
networks:
- fixed:
- 4402cd51-37ee-435e-a966-8245956dc0e6
- floating:
- Ext-Net
provider: nova
userdata_file: /tmp/userdata.txt
@ -96,7 +90,6 @@ accept them
# Import python libs
import os
import copy
import logging
import socket
import pprint
@ -104,6 +97,7 @@ import pprint
# Import generic libcloud functions
from salt.cloud.libcloudfuncs import * # pylint: disable=W0614,W0401
from salt.utils.openstack import nova
import salt.utils.cloud
# Import nova libs
try:
@ -396,41 +390,19 @@ def destroy(name, conn=None, call=None):
return False
def create(vm_):
def request_instance(vm_=None, call=None):
'''
Create a single VM from a data dict
'''
deploy = config.get_cloud_config_value('deploy', vm_, __opts__)
key_filename = config.get_cloud_config_value(
'ssh_key_file', vm_, __opts__, search_global=False, default=None
)
if key_filename is not None and not os.path.isfile(key_filename):
raise SaltCloudConfigError(
'The defined ssh_key_file {0!r} does not exist'.format(
key_filename
)
)
Put together all of the information necessary to request an instance
through Novaclient and then fire off the request the instance.
if deploy is True and key_filename is None and \
salt.utils.which('sshpass') is None:
Returns data about the instance
'''
if call == 'function':
# Technically this function may be called other ways too, but it
# definitely cannot be called with --function.
raise SaltCloudSystemExit(
'Cannot deploy salt in a VM if the \'ssh_key_file\' setting '
'is not set and \'sshpass\' binary is not present on the '
'system for the password.'
'The request_instance action must be called with -a or --action.'
)
salt.utils.cloud.fire_event(
'event',
'starting create',
'salt/cloud/{0}/creating'.format(vm_['name']),
{
'name': vm_['name'],
'profile': vm_['profile'],
'provider': vm_['provider'],
},
transport=__opts__['transport']
)
log.info('Creating Cloud VM {0}'.format(vm_['name']))
salt.utils.cloud.check_name(vm_['name'], 'a-zA-Z0-9._-')
conn = get_conn()
@ -441,28 +413,22 @@ def create(vm_):
try:
kwargs['image_id'] = get_image(conn, vm_)
except Exception as exc:
log.error(
raise SaltCloudSystemExit(
'Error creating {0} on OPENSTACK\n\n'
'Could not find image {1}: {2}\n'.format(
vm_['name'], vm_['image'], exc
),
# Show the traceback if the debug logging level is enabled
exc_info=log.isEnabledFor(logging.DEBUG)
)
)
return False
try:
kwargs['flavor_id'] = get_size(conn, vm_)
except Exception as exc:
log.error(
raise SaltCloudSystemExit(
'Error creating {0} on OPENSTACK\n\n'
'Could not find size {1}: {2}\n'.format(
vm_['name'], vm_['size'], exc
),
# Show the traceback if the debug logging level is enabled
exc_info=log.isEnabledFor(logging.DEBUG)
)
)
return False
kwargs['key_name'] = config.get_cloud_config_value(
'ssh_key_name', vm_, __opts__, search_global=False
@ -492,8 +458,6 @@ def create(vm_):
'networks', vm_, __opts__, search_global=False
)
floating = []
files = config.get_cloud_config_value(
'files', vm_, __opts__, search_global=False
)
@ -532,9 +496,70 @@ def create(vm_):
# Show the traceback if the debug logging level is enabled
exc_info=log.isEnabledFor(logging.DEBUG)
)
return False
return False, vm_
def __query_node_data(vm_, data, floating):
return data, vm_
def create(vm_):
'''
Create a single VM from a data dict
'''
deploy = config.get_cloud_config_value('deploy', vm_, __opts__)
key_filename = config.get_cloud_config_value(
'ssh_key_file', vm_, __opts__, search_global=False, default=None
)
if key_filename is not None and not os.path.isfile(key_filename):
raise SaltCloudConfigError(
'The defined ssh_key_file {0!r} does not exist'.format(
key_filename
)
)
if deploy is True and key_filename is None and \
salt.utils.which('sshpass') is None:
raise SaltCloudSystemExit(
'Cannot deploy salt in a VM if the \'ssh_key_file\' setting '
'is not set and \'sshpass\' binary is not present on the '
'system for the password.'
)
vm_['key_filename'] = key_filename
salt.utils.cloud.fire_event(
'event',
'starting create',
'salt/cloud/{0}/creating'.format(vm_['name']),
{
'name': vm_['name'],
'profile': vm_['profile'],
'provider': vm_['provider'],
},
transport=__opts__['transport']
)
conn = get_conn()
if 'instance_id' in vm_:
# This was probably created via another process, and doesn't have
# things like salt keys created yet, so let's create them now.
if 'pub_key' not in vm_ and 'priv_key' not in vm_:
log.debug('Generating minion keys for {0[name]!r}'.format(vm_))
vm_['priv_key'], vm_['pub_key'] = salt.utils.cloud.gen_keys(
salt.config.get_cloud_config_value(
'keysize',
vm_,
__opts__
)
)
else:
# Put together all of the information required to request the instance,
# and then fire off the request for it
data, vm_ = request_instance(vm_)
# Pull the instance ID, valid for both spot and normal instances
vm_['instance_id'] = data.id
def __query_node_data(vm_, data):
try:
nodelist = list_nodes_full()
log.debug(
@ -582,23 +607,6 @@ def create(vm_):
log.debug('Waiting for managed cloud automation to complete')
return
if floating:
try:
name = data.name
ip = floating[0].ip_address
conn.ex_attach_floating_ip_to_node(data, ip)
log.info(
(
'Attaching floating IP "{0}"'
' to node "{1}"'
).format(ip, name)
)
except Exception as e:
# Note(pabelanger): Because we loop, we only want to attach the
# floating IP address one. So, expect failures if the IP is
# already attached.
pass
result = []
private = nodelist[vm_['name']].private_ips
public = nodelist[vm_['name']].public_ips
@ -644,7 +652,7 @@ def create(vm_):
try:
data = salt.utils.cloud.wait_for_ip(
__query_node_data,
update_args=(vm_, data, floating),
update_args=(vm_, data),
timeout=config.get_cloud_config_value(
'wait_for_ip_timeout', vm_, __opts__, default=10 * 60),
interval=config.get_cloud_config_value(
@ -672,134 +680,8 @@ def create(vm_):
if not ip_address:
raise SaltCloudSystemExit('A valid IP address was not found')
ssh_username = config.get_cloud_config_value(
'ssh_username', vm_, __opts__, default='root'
)
deploy_kwargs = {
'opts': __opts__,
'host': ip_address,
'name': vm_['name'],
'sock_dir': __opts__['sock_dir'],
'tmp_dir': config.get_cloud_config_value(
'tmp_dir', vm_, __opts__, default='/tmp/.saltcloud'
),
'deploy_command': config.get_cloud_config_value(
'deploy_command', vm_, __opts__,
default='/tmp/.saltcloud/deploy.sh',
),
'start_action': __opts__['start_action'],
'parallel': __opts__['parallel'],
'minion_pem': vm_['priv_key'],
'minion_pub': vm_['pub_key'],
'keep_tmp': __opts__['keep_tmp'],
'preseed_minion_keys': vm_.get('preseed_minion_keys', None),
'sudo': config.get_cloud_config_value(
'sudo', vm_, __opts__, default=(ssh_username != 'root')
),
'sudo_password': config.get_cloud_config_value(
'sudo_password', vm_, __opts__, default=None
),
'tty': config.get_cloud_config_value(
'tty', vm_, __opts__, default=False
),
'display_ssh_output': config.get_cloud_config_value(
'display_ssh_output', vm_, __opts__, default=True
),
'script_args': config.get_cloud_config_value(
'script_args', vm_, __opts__
),
'script_env': config.get_cloud_config_value(
'script_env',
vm_,
__opts__
),
'minion_conf': salt.utils.cloud.minion_config(__opts__, vm_)
}
if ssh_username != 'root':
deploy_kwargs['username'] = ssh_username
deploy_kwargs['tty'] = True
log.debug('Using {0} as SSH username'.format(ssh_username))
if key_filename is not None:
deploy_kwargs['key_filename'] = key_filename
log.debug(
'Using {0} as SSH key file'.format(key_filename)
)
elif 'password' in data.extra:
deploy_kwargs['password'] = data.extra['password']
log.debug('Logging into SSH using password')
ret = {}
if config.get_cloud_config_value('deploy', vm_, __opts__) is True:
deploy_script = script(vm_)
deploy_kwargs['script'] = deploy_script.script
# Deploy salt-master files, if necessary
if config.get_cloud_config_value('make_master', vm_, __opts__) is True:
deploy_kwargs['make_master'] = True
deploy_kwargs['master_pub'] = vm_['master_pub']
deploy_kwargs['master_pem'] = vm_['master_pem']
master_conf = salt.utils.cloud.master_config(__opts__, vm_)
deploy_kwargs['master_conf'] = master_conf
if master_conf.get('syndic_master', None):
deploy_kwargs['make_syndic'] = True
deploy_kwargs['make_minion'] = config.get_cloud_config_value(
'make_minion', vm_, __opts__, default=True
)
# Check for Windows install params
win_installer = config.get_cloud_config_value(
'win_installer',
vm_,
__opts__
)
if win_installer:
deploy_kwargs['win_installer'] = win_installer
minion = salt.utils.cloud.minion_config(__opts__, vm_)
deploy_kwargs['master'] = minion['master']
deploy_kwargs['username'] = config.get_cloud_config_value(
'win_username', vm_, __opts__, default='Administrator'
)
deploy_kwargs['password'] = config.get_cloud_config_value(
'win_password', vm_, __opts__, default=''
)
# Store what was used to the deploy the VM
event_kwargs = copy.deepcopy(deploy_kwargs)
del event_kwargs['minion_pem']
del event_kwargs['minion_pub']
del event_kwargs['sudo_password']
if 'password' in event_kwargs:
del event_kwargs['password']
ret['deploy_kwargs'] = event_kwargs
salt.utils.cloud.fire_event(
'event',
'executing deploy script',
'salt/cloud/{0}/deploying'.format(vm_['name']),
{'kwargs': event_kwargs},
transport=__opts__['transport']
)
deployed = False
if win_installer:
deployed = salt.utils.cloud.deploy_windows(**deploy_kwargs)
else:
deployed = salt.utils.cloud.deploy_script(**deploy_kwargs)
if deployed:
log.info('Salt installed on {0}'.format(vm_['name']))
else:
log.error(
'Failed to deploy and start Salt on Cloud VM {0}'.format(
vm_['name']
)
)
vm_['ssh_host'] = ip_address
ret = salt.utils.cloud.bootstrap(vm_, __opts__)
ret.update(data.__dict__)

View File

@ -118,7 +118,6 @@ Alternatively, one could use the private IP to connect by specifying:
# Import python libs
import os
import copy
import logging
import socket
import pprint
@ -378,44 +377,19 @@ def managedcloud(vm_):
)
def create(vm_):
def request_instance(vm_=None, call=None):
'''
Create a single VM from a data dict
'''
deploy = config.get_cloud_config_value('deploy', vm_, __opts__)
key_filename = config.get_cloud_config_value(
'ssh_key_file', vm_, __opts__, search_global=False, default=None
)
if key_filename is not None:
key_filename = os.path.expanduser(key_filename)
if not os.path.isfile(key_filename):
raise SaltCloudConfigError(
'The defined ssh_key_file {0!r} does not exist'.format(
key_filename
)
)
Put together all of the information necessary to request an instance on Openstack
and then fire off the request the instance.
if deploy is True and key_filename is None and \
salt.utils.which('sshpass') is None:
Returns data about the instance
'''
if call == 'function':
# Technically this function may be called other ways too, but it
# definitely cannot be called with --function.
raise SaltCloudSystemExit(
'Cannot deploy salt in a VM if the \'ssh_key_file\' setting '
'is not set and \'sshpass\' binary is not present on the '
'system for the password.'
'The request_instance action must be called with -a or --action.'
)
salt.utils.cloud.fire_event(
'event',
'starting create',
'salt/cloud/{0}/creating'.format(vm_['name']),
{
'name': vm_['name'],
'profile': vm_['profile'],
'provider': vm_['provider'],
},
transport=__opts__['transport']
)
log.info('Creating Cloud VM {0}'.format(vm_['name']))
salt.utils.cloud.check_name(vm_['name'], 'a-zA-Z0-9._-')
conn = get_conn()
kwargs = {
@ -425,28 +399,22 @@ def create(vm_):
try:
kwargs['image'] = get_image(conn, vm_)
except Exception as exc:
log.error(
raise SaltCloudSystemExit(
'Error creating {0} on OPENSTACK\n\n'
'Could not find image {1}: {2}\n'.format(
vm_['name'], vm_['image'], exc
),
# Show the traceback if the debug logging level is enabled
exc_info=log.isEnabledFor(logging.DEBUG)
)
)
return False
try:
kwargs['size'] = get_size(conn, vm_)
except Exception as exc:
log.error(
raise SaltCloudSystemExit(
'Error creating {0} on OPENSTACK\n\n'
'Could not find size {1}: {2}\n'.format(
vm_['name'], vm_['size'], exc
),
# Show the traceback if the debug logging level is enabled
exc_info=log.isEnabledFor(logging.DEBUG)
)
)
return False
kwargs['ex_keyname'] = config.get_cloud_config_value(
'ssh_key_name', vm_, __opts__, search_global=False
@ -532,6 +500,7 @@ def create(vm_):
pass
else:
raise
vm_['floating'] = floating
files = config.get_cloud_config_value(
'files', vm_, __opts__, search_global=False
@ -573,6 +542,7 @@ def create(vm_):
try:
data = conn.create_node(**kwargs)
return data, vm_
except Exception as exc:
log.error(
'Error creating {0} on OpenStack\n\n'
@ -583,7 +553,69 @@ def create(vm_):
# Show the traceback if the debug logging level is enabled
exc_info=log.isEnabledFor(logging.DEBUG)
)
return False
return False, vm_
def create(vm_):
'''
Create a single VM from a data dict
'''
deploy = config.get_cloud_config_value('deploy', vm_, __opts__)
key_filename = config.get_cloud_config_value(
'ssh_key_file', vm_, __opts__, search_global=False, default=None
)
if key_filename is not None:
key_filename = os.path.expanduser(key_filename)
if not os.path.isfile(key_filename):
raise SaltCloudConfigError(
'The defined ssh_key_file {0!r} does not exist'.format(
key_filename
)
)
if deploy is True and key_filename is None and \
salt.utils.which('sshpass') is None:
raise SaltCloudSystemExit(
'Cannot deploy salt in a VM if the \'ssh_key_file\' setting '
'is not set and \'sshpass\' binary is not present on the '
'system for the password.'
)
vm_['key_filename'] = key_filename
salt.utils.cloud.fire_event(
'event',
'starting create',
'salt/cloud/{0}/creating'.format(vm_['name']),
{
'name': vm_['name'],
'profile': vm_['profile'],
'provider': vm_['provider'],
},
transport=__opts__['transport']
)
conn = get_conn()
if 'instance_id' in vm_:
# This was probably created via another process, and doesn't have
# things like salt keys created yet, so let's create them now.
if 'pub_key' not in vm_ and 'priv_key' not in vm_:
log.debug('Generating minion keys for {0[name]!r}'.format(vm_))
vm_['priv_key'], vm_['pub_key'] = salt.utils.cloud.gen_keys(
salt.config.get_cloud_config_value(
'keysize',
vm_,
__opts__
)
)
else:
# Put together all of the information required to request the instance,
# and then fire off the request for it
data, vm_ = request_instance(vm_)
# Pull the instance ID, valid for both spot and normal instances
vm_['instance_id'] = data.id
def __query_node_data(vm_, data, floating):
try:
@ -699,7 +731,7 @@ def create(vm_):
try:
data = salt.utils.cloud.wait_for_ip(
__query_node_data,
update_args=(vm_, data, floating),
update_args=(vm_, data, vm_['floating']),
timeout=config.get_cloud_config_value(
'wait_for_ip_timeout', vm_, __opts__, default=10 * 60),
interval=config.get_cloud_config_value(
@ -727,135 +759,8 @@ def create(vm_):
if not ip_address:
raise SaltCloudSystemExit('A valid IP address was not found')
ssh_username = config.get_cloud_config_value(
'ssh_username', vm_, __opts__, default='root'
)
deploy_kwargs = {
'opts': __opts__,
'host': ip_address,
'name': vm_['name'],
'sock_dir': __opts__['sock_dir'],
'tmp_dir': config.get_cloud_config_value(
'tmp_dir', vm_, __opts__, default='/tmp/.saltcloud'
),
'deploy_command': config.get_cloud_config_value(
'deploy_command', vm_, __opts__,
default='/tmp/.saltcloud/deploy.sh',
),
'start_action': __opts__['start_action'],
'parallel': __opts__['parallel'],
'minion_pem': vm_['priv_key'],
'minion_pub': vm_['pub_key'],
'keep_tmp': __opts__['keep_tmp'],
'preseed_minion_keys': vm_.get('preseed_minion_keys', None),
'sudo': config.get_cloud_config_value(
'sudo', vm_, __opts__, default=(ssh_username != 'root')
),
'sudo_password': config.get_cloud_config_value(
'sudo_password', vm_, __opts__, default=None
),
'display_ssh_output': config.get_cloud_config_value(
'display_ssh_output', vm_, __opts__, default=True
),
'script_args': config.get_cloud_config_value(
'script_args', vm_, __opts__
),
'script_env': config.get_cloud_config_value('script_env',
vm_,
__opts__),
'minion_conf': salt.utils.cloud.minion_config(__opts__,
vm_)
}
if ssh_username != 'root':
deploy_kwargs['username'] = ssh_username
deploy_kwargs['tty'] = True
log.debug('Using {0} as SSH username'.format(ssh_username))
if key_filename is not None:
deploy_kwargs['key_filename'] = key_filename
log.debug(
'Using {0} as SSH key file'.format(key_filename)
)
elif hasattr(data, 'extra') and 'password' in data.extra:
deploy_kwargs['password'] = data.extra['password']
log.debug('Logging into SSH using password')
ret = {}
sudo = config.get_cloud_config_value(
'sudo', vm_, __opts__, default=(ssh_username != 'root')
)
if sudo is not None:
deploy_kwargs['sudo'] = sudo
log.debug('Running root commands using sudo')
if config.get_cloud_config_value('deploy', vm_, __opts__) is True:
deploy_script = script(vm_)
deploy_kwargs['script'] = deploy_script.script
# Deploy salt-master files, if necessary
if config.get_cloud_config_value('make_master', vm_, __opts__) is True:
deploy_kwargs['make_master'] = True
deploy_kwargs['master_pub'] = vm_['master_pub']
deploy_kwargs['master_pem'] = vm_['master_pem']
master_conf = salt.utils.cloud.master_config(__opts__, vm_)
deploy_kwargs['master_conf'] = master_conf
if master_conf.get('syndic_master', None):
deploy_kwargs['make_syndic'] = True
deploy_kwargs['make_minion'] = config.get_cloud_config_value(
'make_minion', vm_, __opts__, default=True
)
# Check for Windows install params
win_installer = config.get_cloud_config_value('win_installer',
vm_,
__opts__)
if win_installer:
deploy_kwargs['win_installer'] = win_installer
minion = salt.utils.cloud.minion_config(__opts__, vm_)
deploy_kwargs['master'] = minion['master']
deploy_kwargs['username'] = config.get_cloud_config_value(
'win_username', vm_, __opts__, default='Administrator'
)
deploy_kwargs['password'] = config.get_cloud_config_value(
'win_password', vm_, __opts__, default=''
)
# Store what was used to the deploy the VM
event_kwargs = copy.deepcopy(deploy_kwargs)
del event_kwargs['minion_pem']
del event_kwargs['minion_pub']
del event_kwargs['sudo_password']
if 'password' in event_kwargs:
del event_kwargs['password']
ret['deploy_kwargs'] = event_kwargs
salt.utils.cloud.fire_event(
'event',
'executing deploy script',
'salt/cloud/{0}/deploying'.format(vm_['name']),
{'kwargs': event_kwargs},
transport=__opts__['transport']
)
deployed = False
if win_installer:
deployed = salt.utils.cloud.deploy_windows(**deploy_kwargs)
else:
deployed = salt.utils.cloud.deploy_script(**deploy_kwargs)
if deployed:
log.info('Salt installed on {0}'.format(vm_['name']))
else:
log.error(
'Failed to deploy and start Salt on Cloud VM {0}'.format(
vm_['name']
)
)
vm_['ssh_host'] = ip_address
ret = salt.utils.cloud.bootstrap(vm_, __opts__)
ret.update(data.__dict__)
if hasattr(data, 'extra') and 'password' in data.extra: