Ansible 2.0 support in ansible handlers
All ansible handlers are now using ansible process instead of python API Change-Id: I14c06830e52610b41a1c5776a6d6cb8af1651478 Closes-bug: #1534145
This commit is contained in:
parent
75858724e4
commit
038c46c3e7
2
bootstrap/playbooks/files/ubuntu-ansible.sh
Normal file → Executable file
2
bootstrap/playbooks/files/ubuntu-ansible.sh
Normal file → Executable file
@ -8,4 +8,4 @@ sudo apt-get update
|
|||||||
sudo apt-get install -y python-setuptools python-dev autoconf g++
|
sudo apt-get install -y python-setuptools python-dev autoconf g++
|
||||||
sudo easy_install pip
|
sudo easy_install pip
|
||||||
sudo pip install -U pip
|
sudo pip install -U pip
|
||||||
sudo pip install "ansible<2.0"
|
sudo pip install "ansible"
|
||||||
|
@ -14,7 +14,7 @@ tabulate==0.7.5
|
|||||||
gevent>=1.0.2
|
gevent>=1.0.2
|
||||||
|
|
||||||
# we need callbacks for now
|
# we need callbacks for now
|
||||||
ansible<2.0
|
ansible
|
||||||
|
|
||||||
mock
|
mock
|
||||||
multipledispatch==0.4.8
|
multipledispatch==0.4.8
|
||||||
|
@ -19,7 +19,6 @@ import json
|
|||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from solar.core.handlers import base
|
|
||||||
from solar.core.handlers.base import SOLAR_TEMP_LOCAL_LOCATION
|
from solar.core.handlers.base import SOLAR_TEMP_LOCAL_LOCATION
|
||||||
from solar.core.handlers.base import TempFileHandler
|
from solar.core.handlers.base import TempFileHandler
|
||||||
from solar.core.log import log
|
from solar.core.log import log
|
||||||
@ -29,7 +28,7 @@ from solar.core.provider import SVNProvider
|
|||||||
ROLES_PATH = '/etc/ansible/roles'
|
ROLES_PATH = '/etc/ansible/roles'
|
||||||
|
|
||||||
|
|
||||||
class AnsiblePlaybookBase(base.BaseHandler):
|
class AnsiblePlaybookBase(TempFileHandler):
|
||||||
|
|
||||||
def download_roles(self, urls):
|
def download_roles(self, urls):
|
||||||
if not os.path.exists(ROLES_PATH):
|
if not os.path.exists(ROLES_PATH):
|
||||||
@ -39,8 +38,43 @@ class AnsiblePlaybookBase(base.BaseHandler):
|
|||||||
provider.run()
|
provider.run()
|
||||||
shutil.copytree(provider.directory, ROLES_PATH)
|
shutil.copytree(provider.directory, ROLES_PATH)
|
||||||
|
|
||||||
|
def make_ansible_command(self, remote_playbook_file,
|
||||||
|
remote_inventory_file, remote_extra_vars_file,
|
||||||
|
ansible_library_path):
|
||||||
|
if ansible_library_path:
|
||||||
|
remote_ansible_library_path = ansible_library_path.replace(
|
||||||
|
SOLAR_TEMP_LOCAL_LOCATION, '/tmp/')
|
||||||
|
call_args = [
|
||||||
|
'ansible-playbook',
|
||||||
|
'--module-path',
|
||||||
|
remote_ansible_library_path,
|
||||||
|
'-i',
|
||||||
|
remote_inventory_file,
|
||||||
|
'--extra-vars',
|
||||||
|
'@%s' % remote_extra_vars_file,
|
||||||
|
remote_playbook_file
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
call_args = [
|
||||||
|
'ansible-playbook',
|
||||||
|
'-i',
|
||||||
|
remote_inventory_file,
|
||||||
|
'--extra-vars',
|
||||||
|
'@%s' % remote_extra_vars_file,
|
||||||
|
remote_playbook_file
|
||||||
|
]
|
||||||
|
return call_args
|
||||||
|
|
||||||
class AnsiblePlaybook(AnsiblePlaybookBase, TempFileHandler):
|
def _copy_ansible_library(self, resource):
|
||||||
|
base_path = resource.db_obj.base_path
|
||||||
|
src_ansible_library_dir = os.path.join(base_path, 'ansible_library')
|
||||||
|
trg_ansible_library_dir = None
|
||||||
|
if os.path.exists(src_ansible_library_dir):
|
||||||
|
log.debug("Adding ansible_library for %s", resource.name)
|
||||||
|
trg_ansible_library_dir = os.path.join(
|
||||||
|
self.dirs[resource.name], 'ansible_library')
|
||||||
|
shutil.copytree(src_ansible_library_dir, trg_ansible_library_dir)
|
||||||
|
return trg_ansible_library_dir
|
||||||
|
|
||||||
def _make_playbook(self, resource, action, action_path):
|
def _make_playbook(self, resource, action, action_path):
|
||||||
dir_path = self.dirs[resource.name]
|
dir_path = self.dirs[resource.name]
|
||||||
@ -68,6 +102,9 @@ class AnsiblePlaybook(AnsiblePlaybookBase, TempFileHandler):
|
|||||||
r_args = resource.args
|
r_args = resource.args
|
||||||
return json.dumps(r_args)
|
return json.dumps(r_args)
|
||||||
|
|
||||||
|
|
||||||
|
class AnsiblePlaybook(AnsiblePlaybookBase):
|
||||||
|
|
||||||
def action(self, resource, action):
|
def action(self, resource, action):
|
||||||
action_file = os.path.join(
|
action_file = os.path.join(
|
||||||
resource.db_obj.actions_path,
|
resource.db_obj.actions_path,
|
||||||
@ -95,28 +132,11 @@ class AnsiblePlaybook(AnsiblePlaybookBase, TempFileHandler):
|
|||||||
remote_extra_vars_file = extra_vars_file.replace(
|
remote_extra_vars_file = extra_vars_file.replace(
|
||||||
SOLAR_TEMP_LOCAL_LOCATION, '/tmp/')
|
SOLAR_TEMP_LOCAL_LOCATION, '/tmp/')
|
||||||
|
|
||||||
if ansible_library_path:
|
call_args = self.make_ansible_command(remote_playbook_file,
|
||||||
remote_ansible_library_path = ansible_library_path.replace(
|
remote_inventory_file,
|
||||||
SOLAR_TEMP_LOCAL_LOCATION, '/tmp/')
|
remote_extra_vars_file,
|
||||||
call_args = [
|
ansible_library_path)
|
||||||
'ansible-playbook',
|
|
||||||
'--module-path',
|
|
||||||
remote_ansible_library_path,
|
|
||||||
'-i',
|
|
||||||
remote_inventory_file,
|
|
||||||
'--extra-vars',
|
|
||||||
'@%s' % remote_extra_vars_file,
|
|
||||||
remote_playbook_file
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
call_args = [
|
|
||||||
'ansible-playbook',
|
|
||||||
'-i',
|
|
||||||
remote_inventory_file,
|
|
||||||
'--extra-vars',
|
|
||||||
'@%s' % remote_extra_vars_file,
|
|
||||||
remote_playbook_file
|
|
||||||
]
|
|
||||||
log.debug('EXECUTING: %s', ' '.join(call_args))
|
log.debug('EXECUTING: %s', ' '.join(call_args))
|
||||||
|
|
||||||
rst = self.transport_run.run(resource, *call_args)
|
rst = self.transport_run.run(resource, *call_args)
|
||||||
|
@ -15,73 +15,60 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# this has to be before callbacks, otherwise ansible circural import problem
|
|
||||||
from ansible import utils
|
|
||||||
|
|
||||||
# intentional line, otherwise H306
|
|
||||||
from ansible import callbacks
|
|
||||||
|
|
||||||
import ansible.constants as C
|
|
||||||
from ansible.playbook import PlayBook
|
|
||||||
|
|
||||||
from solar.core.transports.base import find_named_transport
|
|
||||||
from solar import errors
|
from solar import errors
|
||||||
|
|
||||||
from solar.core.handlers.ansible_playbook import AnsiblePlaybookBase
|
from solar.core.handlers.ansible_playbook import AnsiblePlaybookBase
|
||||||
|
from solar.core.log import log
|
||||||
|
from solar.core.transports.base import find_named_transport
|
||||||
|
from solar.utils import execute
|
||||||
|
|
||||||
|
|
||||||
class AnsiblePlaybookLocal(AnsiblePlaybookBase):
|
class AnsiblePlaybookLocal(AnsiblePlaybookBase):
|
||||||
|
|
||||||
|
def _make_inventory(self, resource):
|
||||||
|
ssh_transport = find_named_transport(resource, 'ssh')
|
||||||
|
ssh_key = ssh_transport.get('key')
|
||||||
|
ssh_password = ssh_transport.get('password')
|
||||||
|
|
||||||
|
if ssh_key:
|
||||||
|
inventory = '{0} ansible_ssh_host={1} ansible_connection=ssh \
|
||||||
|
ansible_ssh_user={2} ansible_ssh_private_key_file={3}'
|
||||||
|
ssh_auth_data = ssh_key
|
||||||
|
elif ssh_password:
|
||||||
|
inventory = '{0} ansible_ssh_host={1} \
|
||||||
|
ansible_ssh_user={2} ansible_ssh_pass={3}'
|
||||||
|
ssh_auth_data = ssh_password
|
||||||
|
else:
|
||||||
|
raise Exception("No key and no password given")
|
||||||
|
user = ssh_transport['user']
|
||||||
|
host = resource.ip()
|
||||||
|
return inventory.format(host, host, user, ssh_auth_data)
|
||||||
|
|
||||||
def action(self, resource, action):
|
def action(self, resource, action):
|
||||||
# This would require to put this file to remote and execute it (mostly)
|
|
||||||
|
|
||||||
ssh_props = find_named_transport(resource, 'ssh')
|
|
||||||
|
|
||||||
remote_user = ssh_props['user']
|
|
||||||
private_key_file = ssh_props.get('key')
|
|
||||||
ssh_password = ssh_props.get('password')
|
|
||||||
|
|
||||||
action_file = os.path.join(
|
action_file = os.path.join(
|
||||||
resource.db_obj.actions_path,
|
resource.db_obj.actions_path,
|
||||||
resource.actions[action])
|
resource.actions[action])
|
||||||
|
|
||||||
|
files = self._make_playbook(resource,
|
||||||
|
action,
|
||||||
|
action_file)
|
||||||
|
playbook_file, inventory_file, extra_vars_file = files
|
||||||
|
|
||||||
variables = resource.args
|
variables = resource.args
|
||||||
if 'roles' in variables:
|
if 'roles' in variables:
|
||||||
self.download_roles(variables['roles'])
|
self.download_roles(variables['roles'])
|
||||||
|
|
||||||
host = resource.ip()
|
ansible_library_path = self._copy_ansible_library(resource)
|
||||||
transport = C.DEFAULT_TRANSPORT
|
call_args = self.make_ansible_command(playbook_file,
|
||||||
|
inventory_file,
|
||||||
|
extra_vars_file,
|
||||||
|
ansible_library_path)
|
||||||
|
|
||||||
C.HOST_KEY_CHECKING = False
|
log.debug('EXECUTING: %s', ' '.join(call_args))
|
||||||
|
|
||||||
stats = callbacks.AggregateStats()
|
ret, out, err = execute(call_args)
|
||||||
playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
|
if ret == 0:
|
||||||
runner_cb = callbacks.PlaybookRunnerCallbacks(
|
return
|
||||||
stats, verbose=utils.VERBOSITY)
|
|
||||||
|
|
||||||
opts = dict(
|
|
||||||
playbook=action_file,
|
|
||||||
remote_user=remote_user,
|
|
||||||
host_list=[host],
|
|
||||||
extra_vars=variables,
|
|
||||||
callbacks=playbook_cb,
|
|
||||||
runner_callbacks=runner_cb,
|
|
||||||
stats=stats,
|
|
||||||
transport=transport)
|
|
||||||
|
|
||||||
if ssh_password:
|
|
||||||
opts['remote_pass'] = ssh_password
|
|
||||||
elif private_key_file:
|
|
||||||
opts['private_key_file'] = private_key_file
|
|
||||||
else:
|
else:
|
||||||
raise Exception("No key and no password given")
|
raise errors.SolarError(out)
|
||||||
|
|
||||||
play = PlayBook(**opts)
|
|
||||||
|
|
||||||
play.run()
|
|
||||||
summary = stats.summarize(host)
|
|
||||||
|
|
||||||
if summary.get('unreachable') or summary.get('failures'):
|
|
||||||
raise errors.SolarError(
|
|
||||||
'Ansible playbook %s failed with next summary %s',
|
|
||||||
action_file, summary)
|
|
||||||
|
@ -57,9 +57,13 @@ class AnsibleTemplateLocal(AnsibleTemplateBase):
|
|||||||
log.debug('inventory_file: %s', inventory_file)
|
log.debug('inventory_file: %s', inventory_file)
|
||||||
log.debug('playbook_file: %s', playbook_file)
|
log.debug('playbook_file: %s', playbook_file)
|
||||||
|
|
||||||
lib_path = self.get_library_path()
|
lib_path = self._copy_ansible_library(resource)
|
||||||
call_args = ['ansible-playbook', '--module-path', lib_path,
|
if lib_path:
|
||||||
'-i', inventory_file, playbook_file]
|
call_args = ['ansible-playbook', '--module-path', lib_path,
|
||||||
|
'-i', inventory_file, playbook_file]
|
||||||
|
else:
|
||||||
|
call_args = ['ansible-playbook', '-i', inventory_file,
|
||||||
|
playbook_file]
|
||||||
log.debug('EXECUTING: %s', ' '.join(call_args))
|
log.debug('EXECUTING: %s', ' '.join(call_args))
|
||||||
|
|
||||||
ret, out, err = execute(call_args)
|
ret, out, err = execute(call_args)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user