目 录CONTENT

文章目录

ansible_runner使用记录

cplinux98
2022-11-10 / 0 评论 / 0 点赞 / 1,230 阅读 / 946 字 / 正在检测是否收录...

00:文章简介

记录了ansible_runner的使用和遇到的问题解决办法

01:ansible_runner介绍

https://docs.ansible.com/ansible/latest/dev_guide/developing_api.html
在ansible官方网站中写到:
This API is intended for internal Ansible use. Ansible may make changes to this API at any time that could break backward compatibility with older versions of the API. Because of this, external use is not supported by Ansible. If you want to use Python API only for executing playbooks or modules, consider ansible-runner first.

If you would like to use Ansible programmatically from a language other than Python, trigger events asynchronously, or have access control and logging demands, please see the AWX project.
https://github.com/ansible/awx/

02:ansible_runner封装

在使用ansible_runner的时候需要指定inventory和playbook文件,这里对其封装一个方法,可以直接传入参数执行

run的参数的参考 https://ansible-runner.readthedocs.io/en/1.4.6/source/ansible_runner.html
events的返回值 https://ansible-runner.readthedocs.io/en/latest/ansible_runner/#module-ansible_runner.runner

import os
import uuid
import shutil
import pathlib
import ansible_runner

class RunAnsible:
    """
    项目使用/opt/ansible作为运行根目录,并使用uuid生成不重复的临时运行目录,运行完成后会清除该临时运行目录
    """
    def __init__(self, host):
        self.host = host
        self.temp_id = str(uuid.uuid4()).replace("-", '')
        self.data_dir = os.path.join("/opt", "ansible", self.temp_id)
        self.inventory = self.make_inventory(self.host)
        self.make_dir = pathlib.Path.mkdir(pathlib.Path(self.data_dir), parents=True, exist_ok=True)

    @classmethod
    def make_inventory(cls, host):
        data = {
            "all": {
                "hosts": host
            }
        }
        return data

    def clear(self):
        ret = pathlib.Path(self.data_dir).exists()
        if ret:
            ret2 = shutil.rmtree(
                self.data_dir,
                # ignore_errors=True
            )
            return ('ok', ret2)
        else:
            return ('not', ret)

    def run_model(self, model=None, model_args=None):
        print(self.data_dir)
        m = ansible_runner.run(
            private_data_dir=self.data_dir,
            inventory=self.inventory,
            host_pattern="all",
            module=model,
            module_args=model_args,
            quiet=True
        )
        print(m.rc)
        stdout = m.stdout.read()
        self.clear()
        return stdout

    def run_playbook(self, playbook=None):
        playbook_path = os.path.join(self.data_dir, 'playbook.yaml')
        print(playbook_path)
        with open(playbook_path, 'w+') as fd:
            fd.write(playbook)

        m = ansible_runner.run_async(
            private_data_dir=self.data_dir,
            inventory=self.inventory,
            playbook=playbook_path,
            quiet=True
        )
        events = m[1].events
        return events

03:ansible_runner封装使用示例

# 运行模块
result = RunAnsible(ipaddress).run_model(model, model_args)

# 运行playbook
a = RunAnsible('10.10.100.39')
my_playbook = """
---
- name: test host
  hosts: all
  tasks:
  - name: shell id 
    command: "sleep 5"
"""

for event in a.run_playbook(playbook=my_playbook):
    print(event['stdout']) # 循环输出playbook运行结果,输出结果和ansible命令行一致

04:ansible_runner使用中遇到的问题及解决办法

遇到的问题:

项目中使用uwsgi运行Django程序,并使用systemd来管理uwsgi,程序中使用了ansible_runner,在测试中发现下面的问题:

1. 使用uwsgi --ini xx.ini 和python manage.py runserver时,ansible_runner可以输出带颜色的stdout,但是使用systemd管理uwsgi后,输出的stdout不带颜色

2. uwsgi官方给的systemd示例,在使用过程中会出现启动失败的情况

排查原因

1. systemd启动失败是因为进程启动方式问题,使用forking即可解决

2. ansible_runner颜色问题,是因为缺少环境变量TERM=xterm-256color
# 排查方法,在两个方法中使用os.environ打印环境变量,最后排查出systemd中缺少上面的变量,导致出现无颜色
# 如果环境变量很多,使用EnvironmentDir指定文件,文件内容为key=value
# 测试时修改service后需要使用 systemd daemon-reload重新加载

附上验证没问题的配置

# uwsgi
[uwsgi]
socket=127.0.0.1:8000
chdir=/opt/SmartPXE/
module=smartpxe.wsgi:application
master=True
processes=cpu_count
pidfile=/tmp/SmartPXE-master.pid
daemonize=/var/log/SmartPXE-uwsgi.log
vacuum=True
# project.service
[Unit]
Description=SmartPXE App Server
After=network.target

[Service]
User=root
Environment=TERM=xterm-256color
WorkingDirectory=/opt/project/
ExecStart=/usr/local/bin/uwsgi --ini /opt/project/service_conf/uwsgi.ini
Restart=always
KillSignal=SIGQUIT
Type=forking

[Install]
WantedBy=multi-user.target
0

评论区