Operation Dimension Tool Ansible call callbacks implementation result NoSQL callback

Source: Internet
Author: User
Tags redis sqlite sqlite database

Objective:

Ansible results By default is output to the CLI terminal and log inside, used to saltsatck the returners data callback, also very much like Ansible also have, at first did not know this function, oneself also simple to achieve such a function.


My implementation is to do some output logic inside the module. When using the Ansible Runner API, it is runner the code at the back and finally adds a section to the Redis output logic. The output of the data here is somewhat unique, but it can only be done in terms of modules and APIs.  If it is using playbook words, according to my previous ideas, and then continue to change the source code ansbile. These two days to listen to Shen Zan said, Ansible has a callback_plugins function, can make some judgments about the state of execution, such as execution success, execution failure, asynchronous execution, asynchronous execution failure, playbook start, end, and so on.

I do not say complex, simply say an example, the implementation of the results, are pushed into the redis inside, can also be temporarily deposited into the SQLite database, but this section of the code I have to shield, interested friends to engage in. For the data inside the Redis can write a page display, specifically record the wrong problem, the success of pass away.

The code is as follows Copy Code
#xiaorui. cc

Import OS
Import time
Import Sqlite3
Import Redis
Import JSON

dbname = '/tmp/setup.db '
time_format= '%y-%m-%d%h:%m:%s '

Try
con = sqlite3.connect (dbname)
cur = con.cursor ()
Except
Pass

def log (host, data):

# if Type (data) = = Dict:
# invocation = Data.pop (' invocation ', None)
# if Invocation.get (' module_name ', None)!= ' Setup ':
# return
#
# facts = data.get (' ansible_facts ', None)
#
# now = Time.strftime (Time_format, Time.localtime ())
#
# try:
# ' Host ' is a unique index
# Cur.execute ("REPLACE into Inventory" (now, host, Arch, Dist, distvers, Sys,kernel) VALUES (?,?,?,?,?,?,?); ",
#        (
# Now,
# facts.get (' Ansible_hostname ', None),
# facts.get (' ansible_architecture ', None),
# facts.get (' ansible_distribution ', None),
# facts.get (' ansible_distribution_version ', None),
# facts.get (' Ansible_system ', None),
# facts.get (' Ansible_kernel ', None)
#        ))
# Con.commit ()
# except:
# Pass
#
Class Callbackmodule (object):
def RUNNER_ON_OK (self, Host, res):
R = Redis. Redis (host= ' 127.0.0.1 ', port=6379, db=0)
R.set (Host,str (res))

f = open ('/tmp/11 ', ' a ')
F.write (str (host))
F.write (str (RES))
F.close ()
Log (host, res)
def runner_on_failed (self, host, res, ignore_errors=false):
f = open ('/tmp/11 ', ' a ')
F.write (' Nbadn ')
F.close ()
Log (host, res)



You can still receive all of the facts data.

Although I use the above example Redis,sqlite database, in fact, I personally recommend the use of MongoDB such a document database. Because Ansible main runner function, give callbacks pass a variable called res, he is a Dict object, if put to Redis hash,sqlite of various fields, enough to annoy you, if direct MONGO, it is simple, Direct Insert! Oh, my.




Here in show a mail callbacks code, scene is, very time-consuming task, when the execution completed, see the results? But you can also continue to look at the terminal, since we talked about Callbacks_plugins, you can push the results into your mailbox, of course, only to send you wrong, there are problems. The following callback code needs to be replaced with its own mailbox, password, SMTP server.

The code is as follows Copy Code
#xiaorui. cc


Import Smtplib

def Mail (subject= ' ansible error mail ', sender= ' <root> ', to= ' root ', Cc=none, Bcc=none, Body=none):
If not body:
BODY = Subject

SMTP = Smtplib. SMTP (' localhost ')

Content = ' from:%sn '% sender
Content = ' to:%sn '% to
If cc:
Content + = ' cc:%SN '% cc
Content + = ' Subject:%snn '% Subject
Content + + Body

addresses = To.split (', ')
If cc:
Addresses + = Cc.split (', ')
If Bcc:
Addresses + = Bcc.split (', ')

For address in addresses:
Smtp.sendmail (sender, address, content)

Smtp.quit ()


Class Callbackmodule (object):

"""
This is ansible callback plugin mails errors to interested parties.
"""

def runner_on_failed (self, host, res, ignore_errors=false):
If ignore_errors:
Return
Sender = ' "Ansible:%s" <root> '% host
Subject = ' Failed:% (module_name) s% (Module_args) s '% res[' invocation ']
BODY = ' The following task failed for host ' + Host + ': nn% (module_name) s% (Module_args) snn '% res[' invocation ']
If ' stdout ' in Res.keys () and res[' stdout ']:
Subject = res[' stdout '].strip (' RN '). Split (' n ') [-1]
Body + = ' with the following output in standard Output:nn ' + res[' stdout '] + ' nn '
If ' stderr ' in Res.keys () and res[' stderr ']:
Subject = res[' stderr '].strip (' RN '). Split (' n ') [-1]
Body + = ' with the following output in standard Error:nn ' + res[' stderr '] + ' nn '
If ' msg ' in Res.keys () and res[' msg ']:
Subject = res[' msg '].strip (' RN '). Split (' n ') [0]
Body + = ' with the following Message:nn ' + res[' msg '] + ' nn '
Body + + ' A complete dump of the ' error:nn ' + str (RES)
Mail (Sender=sender, Subject=subject, Body=body)

def runner_on_unreachable (self, Host, res):
Sender = ' "Ansible:%s" <root> '% host
If Isinstance (res, basestring):
Subject = ' unreachable:%s '% Res.strip (' RN '). Split (' n ') [-1]
BODY = ' A error occured for host ' + Host + ' with the following Message:nn ' + res
Else
Subject = ' unreachable:%s '% res[' msg '].strip (' RN '). Split (' n ') [0]
BODY = ' A error occured for host ' + Host + ' with the following Message:nn ' +
res[' msg '] + ' nna complete dump of the Error:nn ' + str (RES)
Mail (Sender=sender, Subject=subject, Body=body)

def runner_on_async_failed (self, host, res, Jid):
Sender = ' "Ansible:%s" <root> '% host
If Isinstance (res, basestring):
Subject = ' Async failure:%s '% Res.strip (' RN '). Split (' n ') [-1]
BODY = ' A error occured for host ' + Host + ' with the following Message:nn ' + res
Else
Subject = ' Async failure:%s '% res[' msg '].strip (' RN '). Split (' n ') [0]
BODY = ' A error occured for host ' + Host + ' with the following Message:nn ' +
res[' msg '] + ' nna complete dump of the Error:nn ' + str (RES)
Mail (Sender=sender, Subject=subject, Body=body)



What if you don't want to send an email and don't want to get into the database?  That's a little low-end. Write directly to the file.

The official gave an example, everybody follow the template to write on the line.

The code is as follows Copy Code
Import OS
Import time
Import JSON

time_format= "%b%d%Y%h:%m:%s"
msg_format= "% (now) s-% (category) s-% (data) SNN"

If not os.path.exists ("/var/log/ansible/hosts"):
Os.makedirs ("/var/log/ansible/hosts")

def log (host, category, data):
If type (data) = = Dict:
If ' verbose_override ' in data:
# Avoid logging extraneous data from facts
data = ' omitted '
Else
data = Data.copy ()
invocation = Data.pop (' invocation ', None)
data = json.dumps (data)
If invocation is not None:
data = Json.dumps (invocation) + "=>%s"% data

Path = Os.path.join ("/var/log/ansible/hosts", host)
now = Time.strftime (Time_format, Time.localtime ())
FD = open (path, "a")
Fd.write (msg_format% dict (Now=now, Category=category, Data=data))
Fd.close ()

Class Callbackmodule (object):
"""
Logs playbook results, per host, in/var/log/ansible/hosts
"""

def on_any (self, *args, **kwargs):
Pass

def runner_on_failed (self, host, res, ignore_errors=false):
Log (host, ' FAILED ', res)

def RUNNER_ON_OK (self, Host, res):
Log (host, ' OK ', res)

def runner_on_skipped (self, Host, Item=none):
Log (host, ' skipped ', ' ... ')

def runner_on_unreachable (self, Host, res):
Log (host, ' unreachable ', res)

def runner_on_no_hosts (self):
Pass

def runner_on_async_poll (self, host, res, Jid, clock):
Pass

def RUNNER_ON_ASYNC_OK (self, host, res, Jid):
Pass

def runner_on_async_failed (self, host, res, Jid):
Log (host, ' async_failed ', res)

def playbook_on_start (self):
Pass

def playbook_on_notify (self, host, handler):
Pass

def playbook_on_no_hosts_matched (self):
Pass

def playbook_on_no_hosts_remaining (self):
Pass

def playbook_on_task_start (self, Name, is_conditional):
Pass

def playbook_on_vars_prompt (self, varname, private=true, Prompt=none, Encrypt=none, Confirm=false, Salt_size=none, Salt=none, Default=none):
Pass

def playbook_on_setup (self):
Pass

def playbook_on_import_for_host (self, Host, imported_file):
Log (host, ' imported ', imported_file)

def playbook_on_not_import_for_host (self, Host, missing_file):
Log (host, ' notimported ', missing_file)

def playbook_on_play_start (self, name):
Pass

def playbook_on_stats (self, stats):
Pass







You can also do what you want to do with the webhooks hook way.


The various states of callbacks are still many, and the words of each function are well understood.

Like what:

On_any has him everywhere! Any state he had triggered.

runner_on_failed failure

RUNNER_ON_OK success

Runner_on_unreachable network can not reach

Runner_on_no_hosts No hosts

Asynchronous execution of Runner_on_async_poll tasks

When Playbook_on_start playbook executes,

Wait a minute.... Try it yourself!

The code is as follows Copy Code
Class Callbackmodule (object):


def on_any (self, *args, **kwargs):
Pass

def runner_on_failed (self, host, res, ignore_errors=false):
Log (host, ' FAILED ', res)

def RUNNER_ON_OK (self, Host, res):
Log (host, ' OK ', res)

def runner_on_skipped (self, Host, Item=none):
Log (host, ' skipped ', ' ... ')

def runner_on_unreachable (self, Host, res):
Log (host, ' unreachable ', res)

def runner_on_no_hosts (self):
Pass

def runner_on_async_poll (self, host, res, Jid, clock):
Pass

def RUNNER_ON_ASYNC_OK (self, host, res, Jid):
Pass

def runner_on_async_failed (self, host, res, Jid):
Log (host, ' async_failed ', res)

def playbook_on_start (self):
Pass

def playbook_on_notify (self, host, handler):
Pass

def playbook_on_no_hosts_matched (self):
Pass

def playbook_on_no_hosts_remaining (self):
Pass

def playbook_on_task_start (self, Name, is_conditional):
Pass

def playbook_on_vars_prompt (self, varname, private=true, Prompt=none, Encrypt=none, Confirm=false, Salt_size=none, Salt=none, Default=none):
Pass

def playbook_on_setup (self):
Pass

def playbook_on_import_for_host (self, Host, imported_file):
Log (host, ' imported ', imported_file)

def playbook_on_not_import_for_host (self, Host, missing_file):
Log (host, ' notimported ', missing_file)

def playbook_on_play_start (self, name):
Pass

def playbook_on_stats (self, stats):
Pass



We can simply look at the ansible callbacks source code.

Two classes are provided, one for supply ansible-playbook and one for supply ansible, the CLI. Depending on the situation, call a different function, first will hit the terminal, log logs, and finally the custom callbacks Plug-ins.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.