Ansible Python API
官方文檔
參考
import json
import shutil
from ansible. module_utils. common. collections import ImmutableDict
from ansible. parsing. dataloader import DataLoader
from ansible. vars . manager import VariableManager
from ansible. inventory. manager import InventoryManager
from ansible. playbook. play import Play
from ansible. executor. task_queue_manager import TaskQueueManager
from ansible. plugins. callback import CallbackBase
from ansible import context
import ansible. constants as C
class ResultCallback ( CallbackBase) :
"""A sample callback plugin used for performing an action as results come in
If you want to collect all results into a single object for processing at
the end of the execution, look into utilizing the ``json`` callback plugin
or writing your own custom callback plugin
"""
def v2_runner_on_ok ( self, result, ** kwargs) :
"""Print a json representation of the result
This method could store the result in an instance attribute for retrieval later
"""
host = result. _host
print ( json. dumps( { host. name: result. _result} , indent= 4 ) )
context. CLIARGS = ImmutableDict( connection= 'local' , module_path= [ '/to/mymodules' ] , forks= 10 , become= None ,
become_method= None , become_user= None , check= False , diff= False )
loader = DataLoader( )
passwords = dict ( vault_pass= 'secret' )
results_callback = ResultCallback( )
inventory = InventoryManager( loader= loader, sources= 'localhost,' )
variable_manager = VariableManager( loader= loader, inventory= inventory)
play_source = dict (
name = "Ansible Play" ,
hosts = 'localhost' ,
gather_facts = 'no' ,
tasks = [
dict ( action= dict ( module= 'shell' , args= 'ls' ) , register= 'shell_out' ) ,
dict ( action= dict ( module= 'debug' , args= dict ( msg= '{{shell_out.stdout}}' ) ) )
]
)
play = Play( ) . load( play_source, variable_manager= variable_manager, loader= loader)
tqm = None
try :
tqm = TaskQueueManager(
inventory= inventory,
variable_manager= variable_manager,
loader= loader,
passwords= passwords,
stdout_callback= results_callback,
)
result = tqm. run( play)
finally :
if tqm is not None :
tqm. cleanup( )
shutil. rmtree( C. DEFAULT_LOCAL_TMP, True )
import sys
from collections import namedtuple
from ansible. parsing. dataloader import DataLoader
from ansible. vars . manager import VariableManager
from ansible. inventory. manager import InventoryManager
from ansible. inventory. host import Host
from ansible. inventory. group import Group
from ansible. playbook. play import Play
from ansible. executor. task_queue_manager import TaskQueueManager
from ansible. executor. playbook_executor import PlaybookExecutor
def adhoc ( ) :
"""
ad-hoc 調用
資產配置信息 這個是通過 InventoryManager和VariableManager 定義
執行選項 這個是通過namedtuple來定義
執行對象和模塊 通過dict()來定義
定義play 通過Play來定義
最後通過 TaskQueueManager 的實例來執行play
:return:
"""
dl = DataLoader( )
im = InventoryManager( loader= dl, sources= [ "hosts" ] )
vm = VariableManager( loader= dl, inventory= im)
Options = namedtuple( "Options" , [
"connection" , "remote_user" , "ask_sudo_pass" , "verbosity" , "ack_pass" ,
"module_path" , "forks" , "become" , "become_method" , "become_user" , "check" ,
"listhosts" , "listtasks" , "listtags" , "syntax" , "sudo_user" , "sudo" , "diff"
] )
"""
這裏就是Options的實例,然後你就可以賦值,這個爲了給ansible設置執行選項 ansibile 172.16.48.171 -m shell -a 'ls /tmp' -f 5
這裏的選項就是ansible命令中 -f -C -D -m等執行選項
"""
options = Options( connection= 'smart' , remote_user= None , ack_pass= None , sudo_user= None , forks= 5 , sudo= None , ask_sudo_pass= False ,
verbosity= 5 , module_path= None , become= None , become_method= None , become_user= None , check= False , diff= False ,
listhosts= None , listtasks= None , listtags= None , syntax= None )
play_source = dict ( name= "Ansible Play" ,
hosts= "172.16.48.242" ,
gather_facts= "no" ,
tasks= [
dict ( action= dict ( module= "shell" , args= "ls /tmp" ) )
] )
play = Play( ) . load( play_source, variable_manager= vm, loader= dl)
passwords = dict ( )
tqm = TaskQueueManager(
inventory= im,
variable_manager= vm,
loader= dl,
options= options,
passwords= passwords,
)
result = tqm. run( play)
print ( result)
def main ( ) :
adhoc( )
if __name__ == "__main__" :
try :
main( )
finally :
sys. exit( )
import sys
from collections import namedtuple
from ansible. parsing. dataloader import DataLoader
from ansible. vars . manager import VariableManager
from ansible. inventory. manager import InventoryManager
from ansible. inventory. host import Host
from ansible. inventory. group import Group
from ansible. playbook. play import Play
from ansible. executor. task_queue_manager import TaskQueueManager
from ansible. executor. playbook_executor import PlaybookExecutor
def execplaybook ( ) :
"""
調用 playbook
調用playboo大致和調用ad-hoc相同,只是真正調用的是使用PlaybookExecutor
:return:
"""
dl = DataLoader( )
im = InventoryManager( loader= dl, sources= [ "hosts" ] )
vm = VariableManager( loader= dl, inventory= im)
Options = namedtuple( "Options" , [
"connection" , "remote_user" , "ask_sudo_pass" , "verbosity" , "ack_pass" ,
"module_path" , "forks" , "become" , "become_method" , "become_user" , "check" ,
"listhosts" , "listtasks" , "listtags" , "syntax" , "sudo_user" , "sudo" , "diff"
] )
"""
這裏就是Options的實例,然後你就可以賦值,這個爲了給ansible設置執行選項 ansibile 172.16.48.171 -m shell -a 'ls /tmp' -f 5
這裏的選項就是ansible命令中 -f -C -D -m等執行選項
"""
options = Options( connection= 'smart' , remote_user= None , ack_pass= None , sudo_user= None , forks= 5 , sudo= None ,
ask_sudo_pass= False ,
verbosity= 5 , module_path= None , become= None , become_method= None , become_user= None , check= False ,
diff= False ,
listhosts= None , listtasks= None , listtags= None , syntax= None )
passwords = dict ( )
try :
playbook = PlaybookExecutor( playbooks= [ "f1.yml" ] , inventory= im, variable_manager= vm, loader= dl, options= options, passwords= passwords)
playbook. run( )
except Exception as err:
print ( err)
def main ( ) :
execplaybook( )
if __name__ == "__main__" :
try :
main( )
finally :
sys. exit( )
"""ansible管理iptables"""
import shutil
import ansible. constants as C
from ansible import context
from ansible. executor. task_queue_manager import TaskQueueManager
from ansible. inventory. manager import InventoryManager
from ansible. module_utils. common. collections import ImmutableDict
from ansible. parsing. dataloader import DataLoader
from ansible. playbook. play import Play
from ansible. plugins. callback import CallbackBase
from ansible. vars . manager import VariableManager
class ResultCallback ( CallbackBase) :
"""
回調類,給ansible執行ad-hoc命令後回調使用
"""
def __init__ ( self) :
super ( ResultCallback, self) . __init__( )
self. result = None
def v2_runner_on_ok ( self, result, ** kwargs) :
"""
運行成功時回調
:param result:
:param kwargs:
:return: 返回json對象
"""
host = result. _host
self. result = { host. name: result. _result}
def v2_runner_on_failed ( self, result, ignore_errors= False ) :
"""
運行失敗時回調
:param result:
:param ignore_errors:
:return: 返回json對象
"""
host = result. _host
self. result = { host. name: result. _result}
def v2_runner_on_unreachable ( self, result) :
"""
主機連接失敗時回調
:param result:
:return: 返回json對象
"""
host = result. _host
self. result = { host. name: result. _result}
class FireWall ( object ) :
"""
iptables規則核心類
"""
def __init__ ( self, inventory_path, hosts= 'all' , remote_user= None , become_user= 'root' , password= None ) :
"""
:param inventory_path: str inventory文件路徑 必傳參數
:param hosts: str 傳入的主機,和inventory文件的需要匹配上 默認所有主機
:param remote_user: str 遠程連接用戶 非必傳參數 默認app用戶
:param become_user: str 遠程執行命令用戶 非必傳參數 默認root用戶
:param password: str 遠程主機密碼 非必傳參數 默認使用ssh公鑰對連接
"""
context. CLIARGS = ImmutableDict(
connection= 'smart' ,
remote_user= remote_user,
ack_pass= None ,
sudo_user= None ,
forks= 5 ,
sudo= True ,
ask_sudo_pass= False ,
verbosity= 5 ,
module_path= None ,
become= True ,
become_method= 'sudo' ,
become_user= become_user,
check= False ,
diff= False ,
listhosts= None ,
listtasks= None ,
listtags= None ,
syntax= None
)
self. _loader = DataLoader( )
self. _passwords = dict ( ) if password is None else dict ( vault_pass= password)
self. _results_callback = ResultCallback( )
self. _inventory = InventoryManager( loader= self. _loader, sources= [ inventory_path] )
self. _variable_manager = VariableManager( loader= self. _loader, inventory= self. _inventory)
self. _hosts = hosts
self. _redis_key = 'bdc_aomp_firewall_iptables_{}' . format ( '_' . join( self. _hosts. split( '.' ) ) )
def _run_shell_task ( self, name, cmd) :
"""
執行shell命令私有類
:param name: 任務名稱
:param cmd: shell命令
:return: 返回回調類的結果
"""
play_source = dict (
name= name,
hosts= self. _hosts,
gather_facts= 'no' ,
tasks= [
dict ( action= dict ( module= 'shell' , args= cmd) , register= 'shell_out' ) ,
]
)
play = Play( ) . load( play_source, variable_manager= self. _variable_manager, loader= self. _loader)
tqm = None
try :
tqm = TaskQueueManager(
inventory= self. _inventory,
variable_manager= self. _variable_manager,
loader= self. _loader,
passwords= self. _passwords,
stdout_callback= self. _results_callback,
)
tqm. run( play)
finally :
if tqm is not None :
tqm. cleanup( )
shutil. rmtree( C. DEFAULT_LOCAL_TMP, True )
return self. _results_callback. result
def _save_rule ( self) :
"""
用來保存iptables的規則方法,默認添加和刪除的iptables規則保存在內存中,執行完新增和刪除規則後需要調用該方法
:return: tuple (True, None)
"""
cmd = 'service iptables save'
res = self. _run_shell_task( 'append rules' , cmd)
if res[ self. _hosts] [ 'rc' ] != 0 :
return False , res[ self. _hosts] [ 'stderr' ]
else :
return True , None
def get_iptables ( self) :
"""
通過ansible獲取遠程主機的iptables規則
:return: tuple (rules, None)
"""
name = 'get iptables'
cmd = 'iptables -nL --line-number'
result = self. _run_shell_task( name, cmd)
if result is None :
return None , 'get iptables failed!'
if result[ self. _hosts] . get( 'unreachable' ) is True :
return None , result[ self. _hosts] [ 'msg' ]
if result[ self. _hosts] [ 'rc' ] != 0 :
return None , result[ self. _hosts] [ 'stderr' ]
try :
forward_index = result[ self. _hosts] [ 'stdout_lines' ] . index( 'Chain FORWARD (policy DROP)' )
except Exception:
forward_index = result[ self. _hosts] [ 'stdout_lines' ] . index( 'Chain FORWARD (policy ACCEPT)' )
output_index = result[ self. _hosts] [ 'stdout_lines' ] . index( 'Chain OUTPUT (policy ACCEPT)' )
input_list = [ ]
forward_list = [ ]
output_list = [ ]
for i, data in enumerate ( result[ self. _hosts] [ 'stdout_lines' ] ) :
res_dict = {
'num' : None ,
'target' : None ,
'prot' : None ,
'opt' : None ,
'source' : None ,
'destination' : None ,
'rules' : None
}
if len ( data) > 0 and 'num' not in data and 'Chain' not in data:
rules = data. split( )
res_dict[ 'num' ] = rules[ 0 ]
res_dict[ 'target' ] = rules[ 1 ]
res_dict[ 'prot' ] = rules[ 2 ]
res_dict[ 'opt' ] = rules[ 3 ]
res_dict[ 'source' ] = rules[ 4 ]
res_dict[ 'destination' ] = rules[ 5 ]
if len ( rules) > 6 :
res_dict[ 'rules' ] = ' ' . join( rules[ 6 : ] )
if i < forward_index:
input_list. append( res_dict)
elif i < output_index:
forward_list. append( res_dict)
else :
output_list. append( res_dict)
res = { "input" : input_list, "forward" : forward_list, "output" : output_list}
return res, None
def get_hosts ( self) :
"""
獲取管理的主機列表
:return: dict
"""
return { 'hosts' : [ i. address for i in self. _inventory. get_hosts( ) ] }
def append_rule ( self, target, source= None , dpt= None , prot= 'all' , chain= 'INPUT' ) :
"""
向iptables規則後面新增規則
:param target: str 放行還是屏蔽 指[ACCEPT, DROP]
:param chain: str 出入站或者轉發的目標規則,大些,特指 [INPUT, FORWARD, OUTPUT]三個值
:param source: str 源ip地址
:param dpt: str 目的地端口
:param prot: str 協議
:return: tuple (True, None)
"""
if not any ( [ source, dpt] ) :
return False , 'source 或者 dpt參數缺失'
if dpt is not None and prot not in [ 'tcp' , 'udp' ] :
return False , 'dpt 參數不能出現在非tcp或者udp協議內'
if source is None and prot in [ 'tcp' , 'udp' ] :
cmd = 'iptables -A {chain} -p {prot} --dport {dpt} -j {target}' . format (
chain= chain, prot= prot, dpt= dpt, target= target
)
elif all ( [ chain, prot, source, dpt] ) :
cmd = 'iptables -A {chain} -p {prot} -s {source} --dport {dpt} -j {target}' . format (
chain= chain, prot= prot, source= source, dpt= dpt, target= target
)
else :
cmd = 'iptables -A {chain} -p {prot} -s {source} -j {target}' . format (
chain= chain, prot= prot, source= source, target= target
)
res = self. _run_shell_task( 'append rules' , cmd)
if res[ self. _hosts] [ 'rc' ] != 0 :
return False , res[ self. _hosts] [ 'stderr' ]
else :
res, exception = self. _save_rule( )
if exception is not None :
return False , exception
return True , None
def delete_rule ( self, num, chain= 'INPUT' ) :
"""
刪除iptables規則
:param chain: str 出入站或者轉發的目標規則,大些,特指 [INPUT, FORWARD, OUTPUT]三個值
:param num: str 對應的股則序號id
:return: tuple (True, None)
"""
cmd = 'iptables -D {} {}' . format ( chain, num)
res = self. _run_shell_task( 'append rules' , cmd)
if res[ self. _hosts] [ 'rc' ] != 0 :
return False , res[ self. _hosts] [ 'stderr' ]
else :
res, exception = self. _save_rule( )
if exception is not None :
return False , exception
return True , None
def check_rules ( self, num, chain= 'INPUT' ) :
"""
檢查iptables的規則序號是否正確
:param chain: str 出入站或者轉發的目標規則,大些,特指 [INPUT, FORWARD, OUTPUT]三個值
:param num: str 出入站或者轉發的目標規則,大些,特指 [INPUT, FORWARD, OUTPUT]三個值
:return: tuple (True, None)
"""
res, exception = self. get_iptables( )
if exception is not None :
return False , exception
data = res[ chain. lower( ) ]
nums = [ i[ 'num' ] for i in data]
if num not in nums:
return False , '{}規則內沒有num爲{}的規則!' . format ( chain, num)
else :
return True , None
def search_rules ( self, source= None , dpt= None , prot= None , chain= 'INPUT' ) :
if not any ( [ source, dpt, prot] ) :
return None , '缺少查詢條件'
data, err = self. get_iptables( )
if err is not None :
return None , err
data = data[ chain. lower( ) ]
res = list ( )
for i in data:
if all ( [ source, dpt, prot] ) :
if source in i[ 'source' ] and ( i[ 'rules' ] is not None and dpt in i[ 'rules' ] ) and prot in i[ 'prot' ] :
res. append( i)
elif all ( [ source, dpt] ) :
if source in i[ 'source' ] and ( i[ 'rules' ] is not None and dpt in i[ 'rules' ] ) :
res. append( i)
elif all ( [ dpt, prot] ) :
if dpt in i[ 'source' ] and prot in i[ 'prot' ] :
res. append( i)
elif source:
if source in i[ 'source' ] :
res. append( i)
elif dpt:
if i[ 'rules' ] is not None and dpt in i[ 'rules' ] :
res. append( i)
elif prot:
if prot in i[ 'prot' ] :
res. append( i)
return res, None