ansible检测链路状态和切换状态

控制机
ansible.cfg

callback_plugins   = /usr/share/ansible/plugins/callback:/opt/ansible/plugins/callback

[ssh_connection]
ssh_args = -F /opt/ansible/ssh/ssh_config -o ControlMaster=auto -o ControlPersist=5m
control_path = /opt/ansible/ssh/ansible-ssh-%%h-%%p-%%r

pipelining = True

ssh_config

Host 69.169.xx.xx
    User ansible
    Port 29922
    ForwardAgent yes
    StrictHostKeyChecking no

Host 10.150.1.*
    User ansible
    Port 29922
    ProxyCommand ssh -p 29922 ansible@69.169.xx.xx -W %h:%p
    ForwardAgent yes
    StrictHostKeyChecking no

Host 173.45.xx.xx
    User ansible
    Port 29922
    ForwardAgent yes
    StrictHostKeyChecking no

Host 10.160.1.*
    User ansible
    Port 29922
    ProxyCommand ssh -p 29922 ansible@173.45.xx.xx -W %h:%p
    ForwardAgent yes
    StrictHostKeyChecking no

inventory

[dc]
69.169.xx.xx

[la]
173.45.xx.xx

[proxy-dc]
10.150.1.219
10.150.1.220

[proxy-la]
10.160.1.219
10.160.1.220

change_link.yaml

- hosts: proxy-dc
  gather_facts: no
  vars: 
    proxy_host: '221.228.xx.xx'
                
  tasks: 
    - name: update /etc/hosts
      template: src=templates/hosts.j2 dest=/etc/hosts owner=root group=root mode=0644 
      notify: restart dnsmasq

  handlers:
    - name: restart dnsmasq
      service:  name=dnsmasq state=restarted

demo example_play.py

以ansible用户身份登录远程机房内网服务器,sudo切换root权限,返回服务器的网卡流量、连接数、hosts指向

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import json
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager
from ansible.inventory import Inventory
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase

def play_task(host, nic):
    
    class ResultCallback(CallbackBase):
        def __init__(self, *args, **kwargs):
            self.results = None

        def v2_runner_on_unreachable(self, result):
            ip = result._host.get_name()
            self.results = (ip, '', '', '', '') 

        def v2_runner_on_failed(self, result,  *args, **kwargs):
            ip = result._host.get_name()
            self.results = (ip, '', '', '', '')

        def v2_runner_on_ok(self, result, *args, **kwargs):
            ip = result._host.get_name()

            traffic_in = result._result['link_info']['in']
            traffic_out = result._result['link_info']['out']
            connection = result._result['link_info']['connection']
            current_link = result._result['link_info']['current_link']    
            self.results = (ip, traffic_in, traffic_out, connection, current_link)

    Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check'])

    variable_manager = VariableManager()
    loader = DataLoader()
    options = Options(
        connection = 'ssh', 
        module_path = '/opt/ansible/plugins', 
        forks = 100,
        become = True, 
        become_method = 'sudo', 
        become_user = 'root', 
        check = False
    )

    passwords = dict(vault_pass='secret')
    results_callback = ResultCallback()

    inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='/opt/ansible/inventory')
    variable_manager.set_inventory(inventory)

    play_source =  dict(
        name = 'Ansible Play',
        hosts = host,
        gather_facts = 'no',
        tasks = [
            dict(action=dict(module='link_info', args='interface=%s' % nic)),
        ]
    )

    play = Play().load(play_source, variable_manager=variable_manager, loader=loader)

    tqm = None
    try:
        tqm = TaskQueueManager(
            inventory=inventory,
            variable_manager=variable_manager,
            loader=loader,
            options=options,
            passwords=None,
            stdout_callback=results_callback,
        )
        tqm.run(play)
    finally:
        if tqm is not None:
            tqm.cleanup()
    return results_callback.results

link_info模块

#!/usr/bin/env python
# -*- coding: utf-8 -*-

DOCUMENTATION = '''
---

'''

EXAMPLES = '''
---

'''

import re, socket
import datetime, time
import subprocess

from ansible.module_utils.basic import *

def unit_convert(data):
    if data < 10**3:
        return str(round(float(data), 2))
    elif data > 10**3 and data < 10**6:
        return str(round(float(data) / 10**3, 2)) + 'Kb'
    elif data > 10**6 and data < 10**9:
        return str(round(float(data) / 10**6, 2)) + 'Mb'
    elif data > 10**9 and data < 10**12:
        return str(round(float(data) / 10**9, 2)) + 'Gb'
    elif data > 10**12 and data < 10**15:
        return str(round(float(data) / 10**12, 2)) + 'Tb'

def get_traffic_info():
    proc_stat = '/proc/net/dev'
    traffic = []

    with open(proc_stat, 'r') as f:
        for line in f:
            m = re.match('s*(S+):s*(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+(d+)s+', line)
            if m:
                traffic.append((m.group(1), int(m.group(2)), int(m.group(10))))
                                                                                                                                                                      
    return traffic

def get_connection_info():
    command = 'netstat -n |grep ^tcp |wc -l'
    p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output, error = p.communicate()

    return int(output)

def get_current_link_info():
    hostfile = '/etc/hosts'
    with open(hostfile, 'r') as f:
        for line in f:
            m = re.match('(d{1,3}.d{1,3}.d{1,3}.d{1,3})s+(S+)', line)
            if m and m.group(2) == 'wx.service.live.tvmining.com':
                return m.group(1)

    return 'unknown'

def main():
    module = AnsibleModule(
        argument_spec = {
            'interface': { 'default': 'em2', 'type': 'str'}
        },
        supports_check_mode = True
    )

    counter = 2
    first = get_traffic_info()
    time.sleep(counter)
    second = get_traffic_info()
    traffic = map(lambda x, y: (x[0], unit_convert(abs(x[1]-y[1])*8), unit_convert(abs(x[2]-y[2])*8)), first, second)

    for name, receive, transmit in traffic:
        if name == module.params['interface']:
            traffic_in, traffic_out = receive, transmit

    connection = get_connection_info()
    current_link = get_current_link_info()

    message = {
        'in': traffic_in,
        'out': traffic_out,
        'connection': connection,
        'current_link': current_link,
    }

    module.exit_json(changed=False, link_info=message)

if __name__ == '__main__':
    main()

demo example_playbook.py

以ansible身份登录远程内网服务器,sudo切换root权限,执行change_link.yaml

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager
from ansible.inventory import Inventory
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase
from ansible.executor.playbook_executor import PlaybookExecutor

Options = namedtuple('Options', 
    ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax'])
# 这些options项是必须的,缺少的话程序报错

options = Options(
    connection = 'ssh', 
    module_path = '/path/to/mymodules', 
    forks = 100, 
    become = True, 
    become_method = 'sudo', 
    become_user = 'root', 
    check = False, 
    listhosts = None,
    listtasks = None,
    listtags = None,
    syntax = None
)

loader = DataLoader()
variable_manager = VariableManager()
inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='/opt/ansible/inventory')
variable_manager.set_inventory(inventory)

playbooks=['/opt/ansible/change_link.yaml']
pb = PlaybookExecutor(playbooks=playbooks, inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=None)
  
pb.run()
原文地址:https://www.cnblogs.com/liujitao79/p/5714818.html