ansible 2.7调用

程序

import json
from collections import namedtuple
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 class ResultsCollector(CallbackBase):
"""重构执行结果"""
def __init__(self, *args, **kwargs):
super(ResultsCollector, self).__init__(*args, **kwargs)
self.host_ok = {}
self.host_unreachable = {}
self.host_failed = {} def v2_runner_on_unreachable(self, result, *args, **kwargs):
"""不可达"""
self.host_unreachable[result._host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs):
"""执行成功"""
self.host_ok[result._host.get_name()] = result def v2_runner_on_failed(self, result, *args, **kwargs):
"""执行失败"""
self.host_failed[result._host.get_name()] = result def run_ansible(module_name,module_args,host_list,option_dict):
# 初始化需要的对象
Options = namedtuple('Options',
['connection', 'module_path', 'forks', 'become',
'become_method', 'private_key_file','become_user',
'remote_user', 'check', 'diff']
)
#负责查找和读取yaml、json和ini文件
loader = DataLoader() options = Options(connection='ssh', module_path=None, forks=5, become=option_dict['become'],
become_method='sudo',private_key_file="/root/.ssh/id_rsa",
become_user='root', remote_user=option_dict['remote_user'], check=False, diff=False
) passwords = dict(vault_pass='secret') # 实例化ResultCallback来处理结果
callback = ResultsCollector() # 创建库存(inventory)并传递给VariableManager
inventory = InventoryManager(loader=loader, sources=['/etc/ansible/hosts'])
variable_manager = VariableManager(loader=loader, inventory=inventory) # 创建任务
host = ",".join(host_list)
play_source = dict(
name="Ansible Play",
hosts=host,
gather_facts='no',
tasks=[
dict(action=dict(module=module_name, args=module_args), register='shell_out'),
]
)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader) # 开始执行
tqm = None tqm = TaskQueueManager(
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
options=options,
passwords=passwords,
stdout_callback=callback,
)
result = tqm.run(play) result_raw = {'success': {}, 'failed': {}, 'unreachable': {}} for host, result in callback.host_ok.items():
result_raw['success'][host] = result._result['stdout_lines'] for host, result in callback.host_failed.items():
result_raw['failed'][host] = result._result['stderr_lines'] for host, result in callback.host_unreachable.items():
result_raw['unreachable'][host] = result._result["msg"] return json.dumps(result_raw, indent=4) if __name__ == "__main__":
option_dict={"become":True,"remote_user":"opadmin"}
module_name = 'shell'
module_args = "hostname"
host_list = ['10.0.0.131','10.0.0.132']
ret = run_ansible(module_name,module_args,host_list,option_dict)
print(ret)

运行结果:

[root@mcw1 ~]$ python3 runapi.py
{
"success": {},
"failed": {},
"unreachable": {
"10.0.0.132": "Failed to connect to the host via ssh: opadmin@10.0.0.132: Permission denied (publickey,password).\r\n",
"10.0.0.131": "Failed to connect to the host via ssh: opadmin@10.0.0.131: Permission denied (publickey,password,keyboard-interactive).\r\n"
}
}
[root@mcw1 ~]$

又上面程序可知,是用opadmin用户连接,而我并没有这个用户,改成root当前连接用户就行了

执行结果如下:

[root@mcw1 ~]$ python3 runapi.py
{
"success": {
"10.0.0.132": [
"mcw2"
],
"10.0.0.131": [
"mcw1"
]
},
"failed": {},
"unreachable": {}
}

新增主机133,但是这台主机并没有运行,肯定连不上

[root@mcw1 ~]$ python3 runapi.py
[WARNING]: Could not match supplied host pattern, ignoring: 10.0.0.133 {
"success": {
"10.0.0.132": [
"mcw2"
],
"10.0.0.131": [
"mcw1"
]
},
"failed": {},
"unreachable": {}
}

打印结果:

for host, result in callback.host_ok.items():
  result_raw['success'][host] = result._result['stdout_lines']
  print('chenggongde',result)


for host, result in callback.host_failed.items():
  result_raw['failed'][host] = result._result['stderr_lines']
  print('shibaide',result)


[root@mcw1 ~]$ python3 runapi.py
[WARNING]: Could not match supplied host pattern, ignoring: 10.0.0.133 chenggongde <ansible.executor.task_result.TaskResult object at 0x7f39929c5828>
chenggongde <ansible.executor.task_result.TaskResult object at 0x7f399215ad30>
{
"success": {
"10.0.0.132": [
"mcw2"
],
"10.0.0.131": [
"mcw1"
]
},
"failed": {},
"unreachable": {}
}
[root@mcw1 ~]$ vim runapi.py
[root@mcw1 ~]$
[root@mcw1 ~]$

for host, result in callback.host_ok.items():
  result_raw['success'][host] = result._result['stdout_lines']
  print('chenggongde',result._result)


for host, result in callback.host_failed.items():
  result_raw['failed'][host] = result._result['stderr_lines']
  print('shibaide',result.result)

[root@mcw1 ~]$ python3 runapi.py
[WARNING]: Could not match supplied host pattern, ignoring: 10.0.0.133 chenggongde {'changed': True, 'end': '2021-12-14 11:43:50.453528', 'stdout': 'mcw2', 'cmd': 'hostname', 'rc': 0, 'start': '2021-12-14 11:43:50.438420', 'stderr': '', 'delta': '0:00:00.015108', 'invocation': {'module_args': {'creates': None, 'executable': None, '_uses_shell': True, '_raw_params': 'hostname', 'removes': None, 'argv': None, 'warn': True, 'chdir': None, 'stdin': None}}, '_ansible_parsed': True, 'stdout_lines': ['mcw2'], 'stderr_lines': [], '_ansible_no_log': False}
chenggongde {'changed': True, 'end': '2021-12-14 03:43:49.826931', 'stdout': 'mcw1', 'cmd': 'hostname', 'rc': 0, 'start': '2021-12-14 03:43:49.820276', 'stderr': '', 'delta': '0:00:00.006655', 'invocation': {'module_args': {'creates': None, 'executable': None, '_uses_shell': True, '_raw_params': 'hostname', 'removes': None, 'argv': None, 'warn': True, 'chdir': None, 'stdin': None}}, '_ansible_parsed': True, 'stdout_lines': ['mcw1'], 'stderr_lines': [], '_ansible_no_log': False}
{
"success": {
"10.0.0.132": [
"mcw2"
],
"10.0.0.131": [
"mcw1"
]
},
"failed": {},
"unreachable": {}
}

成功返回结果JSON格式

{
'changed': True,
'end': '2021-12-14 11:43:50.453528',
'stdout': 'mcw2',
'cmd': 'hostname',
'rc': 0,
'start': '2021-12-14 11:43:50.438420',
'stderr': '',
'delta': '0:00:00.015108',
'invocation': {
'module_args': {
'creates': None,
'executable': None,
'_uses_shell': True,
'_raw_params': 'hostname',
'removes': None,
'argv': None,
'warn': True,
'chdir': None,
'stdin': None
}
},
'_ansible_parsed': True,
'stdout_lines': ['mcw2'],
'stderr_lines': [],
'_ansible_no_log': False
}

成功返回结果

ansible的setup模块返回信息

[root@mcw1 ~]$ ansible 10.0.0.132 -m setup
10.0.0.132 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"172.16.1.132",
"10.0.0.132"
],
"ansible_all_ipv6_addresses": [
"fe80::20c:29ff:fe01:a8d1",
"fe80::20c:29ff:fe01:a8c7"
],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "07/02/2015",
"ansible_bios_version": "6.00",
"ansible_cmdline": {
"BOOT_IMAGE": "/vmlinuz-3.10.0-693.el7.x86_64",
"LANG": "en_US.UTF-8",
"crashkernel": "auto",
"quiet": true,
"rhgb": true,
"ro": true,
"root": "UUID=a6a0174b-0f9f-4b72-a404-439c25a15ec9"
},
"ansible_date_time": {
"date": "2021-12-14",
"day": "14",
"epoch": "1639454188",
"hour": "11",
"iso8601": "2021-12-14T03:56:28Z",
"iso8601_basic": "20211214T115628396754",
"iso8601_basic_short": "20211214T115628",
"iso8601_micro": "2021-12-14T03:56:28.396754Z",
"minute": "56",
"month": "12",
"second": "28",
"time": "11:56:28",
"tz": "CST",
"tz_offset": "+0800",
"weekday": "Tuesday",
"weekday_number": "2",
"weeknumber": "50",
"year": "2021"
},
"ansible_default_ipv4": {
"address": "10.0.0.132",
"alias": "ens33",
"broadcast": "10.0.0.255",
"gateway": "10.0.0.2",
"interface": "ens33",
"macaddress": "00:0c:29:01:a8:c7",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "10.0.0.0",
"type": "ether"
},
"ansible_default_ipv6": {},
"ansible_device_links": {
"ids": {
"sr0": [
"ata-VMware_Virtual_IDE_CDROM_Drive_10000000000000000001"
]
},
"labels": {
"sr0": [
"CentOS\\x207\\x20x86_64"
]
},
"masters": {},
"uuids": {
"sda1": [
"20f697d6-9ca0-4b9e-9f20-56325684f2ca"
],
"sda2": [
"6042e061-f29b-4ac1-9f32-87980ddf0e1f"
],
"sda3": [
"a6a0174b-0f9f-4b72-a404-439c25a15ec9"
],
"sr0": [
"2017-09-06-10-51-00-00"
]
}
},
"ansible_devices": {
"sda": {
"holders": [],
"host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
"links": {
"ids": [],
"labels": [],
"masters": [],
"uuids": []
},
"model": "VMware Virtual S",
"partitions": {
"sda1": {
"holders": [],
"links": {
"ids": [],
"labels": [],
"masters": [],
"uuids": [
"20f697d6-9ca0-4b9e-9f20-56325684f2ca"
]
},
"sectors": "1015808",
"sectorsize": 512,
"size": "496.00 MB",
"start": "2048",
"uuid": "20f697d6-9ca0-4b9e-9f20-56325684f2ca"
},
"sda2": {
"holders": [],
"links": {
"ids": [],
"labels": [],
"masters": [],
"uuids": [
"6042e061-f29b-4ac1-9f32-87980ddf0e1f"
]
},
"sectors": "1587200",
"sectorsize": 512,
"size": "775.00 MB",
"start": "1017856",
"uuid": "6042e061-f29b-4ac1-9f32-87980ddf0e1f"
},
"sda3": {
"holders": [],
"links": {
"ids": [],
"labels": [],
"masters": [],
"uuids": [
"a6a0174b-0f9f-4b72-a404-439c25a15ec9"
]
},
"sectors": "39337984",
"sectorsize": 512,
"size": "18.76 GB",
"start": "2605056",
"uuid": "a6a0174b-0f9f-4b72-a404-439c25a15ec9"
}
},
"removable": "0",
"rotational": "1",
"sas_address": null,
"sas_device_handle": null,
"scheduler_mode": "deadline",
"sectors": "41943040",
"sectorsize": "512",
"size": "20.00 GB",
"support_discard": "0",
"vendor": "VMware,",
"virtual": 1
},
"sr0": {
"holders": [],
"host": "IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)",
"links": {
"ids": [
"ata-VMware_Virtual_IDE_CDROM_Drive_10000000000000000001"
],
"labels": [
"CentOS\\x207\\x20x86_64"
],
"masters": [],
"uuids": [
"2017-09-06-10-51-00-00"
]
},
"model": "VMware IDE CDR10",
"partitions": {},
"removable": "1",
"rotational": "1",
"sas_address": null,
"sas_device_handle": null,
"scheduler_mode": "cfq",
"sectors": "8830976",
"sectorsize": "2048",
"size": "4.21 GB",
"support_discard": "0",
"vendor": "NECVMWar",
"virtual": 1
}
},
"ansible_distribution": "CentOS",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/redhat-release",
"ansible_distribution_file_variety": "RedHat",
"ansible_distribution_major_version": "7",
"ansible_distribution_release": "Core",
"ansible_distribution_version": "7.4",
"ansible_dns": {
"nameservers": [
"2.5.5.5",
"2.6.6.6",
"223.5.5.5",
"223.6.6.6"
]
},
"ansible_domain": "",
"ansible_effective_group_id": 0,
"ansible_effective_user_id": 0,
"ansible_ens33": {
"active": true,
"device": "ens33",
"features": {
"busy_poll": "off [fixed]",
"fcoe_mtu": "off [fixed]",
"generic_receive_offload": "on",
"generic_segmentation_offload": "on",
"highdma": "off [fixed]",
"hw_tc_offload": "off [fixed]",
"l2_fwd_offload": "off [fixed]",
"large_receive_offload": "off [fixed]",
"loopback": "off [fixed]",
"netns_local": "off [fixed]",
"ntuple_filters": "off [fixed]",
"receive_hashing": "off [fixed]",
"rx_all": "off",
"rx_checksumming": "off",
"rx_fcs": "off",
"rx_vlan_filter": "on [fixed]",
"rx_vlan_offload": "on",
"rx_vlan_stag_filter": "off [fixed]",
"rx_vlan_stag_hw_parse": "off [fixed]",
"scatter_gather": "on",
"tcp_segmentation_offload": "on",
"tx_checksum_fcoe_crc": "off [fixed]",
"tx_checksum_ip_generic": "on",
"tx_checksum_ipv4": "off [fixed]",
"tx_checksum_ipv6": "off [fixed]",
"tx_checksum_sctp": "off [fixed]",
"tx_checksumming": "on",
"tx_fcoe_segmentation": "off [fixed]",
"tx_gre_csum_segmentation": "off [fixed]",
"tx_gre_segmentation": "off [fixed]",
"tx_gso_partial": "off [fixed]",
"tx_gso_robust": "off [fixed]",
"tx_ipip_segmentation": "off [fixed]",
"tx_lockless": "off [fixed]",
"tx_mpls_segmentation": "off [fixed]",
"tx_nocache_copy": "off",
"tx_scatter_gather": "on",
"tx_scatter_gather_fraglist": "off [fixed]",
"tx_sctp_segmentation": "off [fixed]",
"tx_sit_segmentation": "off [fixed]",
"tx_tcp6_segmentation": "off [fixed]",
"tx_tcp_ecn_segmentation": "off [fixed]",
"tx_tcp_mangleid_segmentation": "off",
"tx_tcp_segmentation": "on",
"tx_udp_tnl_csum_segmentation": "off [fixed]",
"tx_udp_tnl_segmentation": "off [fixed]",
"tx_vlan_offload": "on [fixed]",
"tx_vlan_stag_hw_insert": "off [fixed]",
"udp_fragmentation_offload": "off [fixed]",
"vlan_challenged": "off [fixed]"
},
"hw_timestamp_filters": [],
"ipv4": {
"address": "10.0.0.132",
"broadcast": "10.0.0.255",
"netmask": "255.255.255.0",
"network": "10.0.0.0"
},
"ipv6": [
{
"address": "fe80::20c:29ff:fe01:a8c7",
"prefix": "64",
"scope": "link"
}
],
"macaddress": "00:0c:29:01:a8:c7",
"module": "e1000",
"mtu": 1500,
"pciid": "0000:02:01.0",
"promisc": false,
"speed": 1000,
"timestamping": [
"tx_software",
"rx_software",
"software"
],
"type": "ether"
},
"ansible_ens37": {
"active": true,
"device": "ens37",
"features": {
"busy_poll": "off [fixed]",
"fcoe_mtu": "off [fixed]",
"generic_receive_offload": "on",
"generic_segmentation_offload": "on",
"highdma": "off [fixed]",
"hw_tc_offload": "off [fixed]",
"l2_fwd_offload": "off [fixed]",
"large_receive_offload": "off [fixed]",
"loopback": "off [fixed]",
"netns_local": "off [fixed]",
"ntuple_filters": "off [fixed]",
"receive_hashing": "off [fixed]",
"rx_all": "off",
"rx_checksumming": "off",
"rx_fcs": "off",
"rx_vlan_filter": "on [fixed]",
"rx_vlan_offload": "on",
"rx_vlan_stag_filter": "off [fixed]",
"rx_vlan_stag_hw_parse": "off [fixed]",
"scatter_gather": "on",
"tcp_segmentation_offload": "on",
"tx_checksum_fcoe_crc": "off [fixed]",
"tx_checksum_ip_generic": "on",
"tx_checksum_ipv4": "off [fixed]",
"tx_checksum_ipv6": "off [fixed]",
"tx_checksum_sctp": "off [fixed]",
"tx_checksumming": "on",
"tx_fcoe_segmentation": "off [fixed]",
"tx_gre_csum_segmentation": "off [fixed]",
"tx_gre_segmentation": "off [fixed]",
"tx_gso_partial": "off [fixed]",
"tx_gso_robust": "off [fixed]",
"tx_ipip_segmentation": "off [fixed]",
"tx_lockless": "off [fixed]",
"tx_mpls_segmentation": "off [fixed]",
"tx_nocache_copy": "off",
"tx_scatter_gather": "on",
"tx_scatter_gather_fraglist": "off [fixed]",
"tx_sctp_segmentation": "off [fixed]",
"tx_sit_segmentation": "off [fixed]",
"tx_tcp6_segmentation": "off [fixed]",
"tx_tcp_ecn_segmentation": "off [fixed]",
"tx_tcp_mangleid_segmentation": "off",
"tx_tcp_segmentation": "on",
"tx_udp_tnl_csum_segmentation": "off [fixed]",
"tx_udp_tnl_segmentation": "off [fixed]",
"tx_vlan_offload": "on [fixed]",
"tx_vlan_stag_hw_insert": "off [fixed]",
"udp_fragmentation_offload": "off [fixed]",
"vlan_challenged": "off [fixed]"
},
"hw_timestamp_filters": [],
"ipv4": {
"address": "172.16.1.132",
"broadcast": "172.16.1.255",
"netmask": "255.255.255.0",
"network": "172.16.1.0"
},
"ipv6": [
{
"address": "fe80::20c:29ff:fe01:a8d1",
"prefix": "64",
"scope": "link"
}
],
"macaddress": "00:0c:29:01:a8:d1",
"module": "e1000",
"mtu": 1500,
"pciid": "0000:02:05.0",
"promisc": false,
"speed": 1000,
"timestamping": [
"tx_software",
"rx_software",
"software"
],
"type": "ether"
},
"ansible_env": {
"HOME": "/root",
"LANG": "en_US.UTF-8",
"LESSOPEN": "||/usr/bin/lesspipe.sh %s",
"LOGNAME": "root",
"LS_COLORS": "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:",
"MAIL": "/var/mail/root",
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
"PWD": "/root",
"SHELL": "/bin/bash",
"SHLVL": "2",
"SSH_CLIENT": "10.0.0.131 45784 22",
"SSH_CONNECTION": "10.0.0.131 45784 10.0.0.132 22",
"SSH_TTY": "/dev/pts/1",
"TERM": "xterm",
"USER": "root",
"XDG_RUNTIME_DIR": "/run/user/0",
"XDG_SESSION_ID": "33",
"_": "/usr/bin/python"
},
"ansible_fibre_channel_wwn": [],
"ansible_fips": false,
"ansible_form_factor": "Other",
"ansible_fqdn": "mcw2",
"ansible_hostname": "mcw2",
"ansible_hostnqn": "",
"ansible_interfaces": [
"lo",
"ens37",
"ens33"
],
"ansible_is_chroot": false,
"ansible_iscsi_iqn": "",
"ansible_kernel": "3.10.0-693.el7.x86_64",
"ansible_kernel_version": "#1 SMP Tue Aug 22 21:09:27 UTC 2017",
"ansible_lo": {
"active": true,
"device": "lo",
"features": {
"busy_poll": "off [fixed]",
"fcoe_mtu": "off [fixed]",
"generic_receive_offload": "on",
"generic_segmentation_offload": "on",
"highdma": "on [fixed]",
"hw_tc_offload": "off [fixed]",
"l2_fwd_offload": "off [fixed]",
"large_receive_offload": "off [fixed]",
"loopback": "on [fixed]",
"netns_local": "on [fixed]",
"ntuple_filters": "off [fixed]",
"receive_hashing": "off [fixed]",
"rx_all": "off [fixed]",
"rx_checksumming": "on [fixed]",
"rx_fcs": "off [fixed]",
"rx_vlan_filter": "off [fixed]",
"rx_vlan_offload": "off [fixed]",
"rx_vlan_stag_filter": "off [fixed]",
"rx_vlan_stag_hw_parse": "off [fixed]",
"scatter_gather": "on",
"tcp_segmentation_offload": "on",
"tx_checksum_fcoe_crc": "off [fixed]",
"tx_checksum_ip_generic": "on [fixed]",
"tx_checksum_ipv4": "off [fixed]",
"tx_checksum_ipv6": "off [fixed]",
"tx_checksum_sctp": "on [fixed]",
"tx_checksumming": "on",
"tx_fcoe_segmentation": "off [fixed]",
"tx_gre_csum_segmentation": "off [fixed]",
"tx_gre_segmentation": "off [fixed]",
"tx_gso_partial": "off [fixed]",
"tx_gso_robust": "off [fixed]",
"tx_ipip_segmentation": "off [fixed]",
"tx_lockless": "on [fixed]",
"tx_mpls_segmentation": "off [fixed]",
"tx_nocache_copy": "off [fixed]",
"tx_scatter_gather": "on [fixed]",
"tx_scatter_gather_fraglist": "on [fixed]",
"tx_sctp_segmentation": "on",
"tx_sit_segmentation": "off [fixed]",
"tx_tcp6_segmentation": "on",
"tx_tcp_ecn_segmentation": "on",
"tx_tcp_mangleid_segmentation": "on",
"tx_tcp_segmentation": "on",
"tx_udp_tnl_csum_segmentation": "off [fixed]",
"tx_udp_tnl_segmentation": "off [fixed]",
"tx_vlan_offload": "off [fixed]",
"tx_vlan_stag_hw_insert": "off [fixed]",
"udp_fragmentation_offload": "on",
"vlan_challenged": "on [fixed]"
},
"hw_timestamp_filters": [],
"ipv4": {
"address": "127.0.0.1",
"broadcast": "",
"netmask": "255.0.0.0",
"network": "127.0.0.0"
},
"ipv6": [
{
"address": "::1",
"prefix": "128",
"scope": "host"
}
],
"mtu": 65536,
"promisc": false,
"timestamping": [
"rx_software",
"software"
],
"type": "loopback"
},
"ansible_local": {},
"ansible_lsb": {},
"ansible_machine": "x86_64",
"ansible_machine_id": "06fe05f799ee4e959f6d4acfaf48fb73",
"ansible_memfree_mb": 708,
"ansible_memory_mb": {
"nocache": {
"free": 799,
"used": 177
},
"real": {
"free": 708,
"total": 976,
"used": 268
},
"swap": {
"cached": 0,
"free": 774,
"total": 774,
"used": 0
}
},
"ansible_memtotal_mb": 976,
"ansible_mounts": [
{
"block_available": 97473,
"block_size": 4096,
"block_total": 126121,
"block_used": 28648,
"device": "/dev/sda1",
"fstype": "xfs",
"inode_available": 253625,
"inode_total": 253952,
"inode_used": 327,
"mount": "/boot",
"options": "rw,relatime,attr2,inode64,noquota",
"size_available": 399249408,
"size_total": 516591616,
"uuid": "20f697d6-9ca0-4b9e-9f20-56325684f2ca"
},
{
"block_available": 4445479,
"block_size": 4096,
"block_total": 4914688,
"block_used": 469209,
"device": "/dev/sda3",
"fstype": "xfs",
"inode_available": 9777400,
"inode_total": 9834496,
"inode_used": 57096,
"mount": "/",
"options": "rw,relatime,attr2,inode64,noquota",
"size_available": 18208681984,
"size_total": 20130562048,
"uuid": "a6a0174b-0f9f-4b72-a404-439c25a15ec9"
}
],
"ansible_nodename": "mcw2",
"ansible_os_family": "RedHat",
"ansible_pkg_mgr": "yum",
"ansible_proc_cmdline": {
"BOOT_IMAGE": "/vmlinuz-3.10.0-693.el7.x86_64",
"LANG": "en_US.UTF-8",
"crashkernel": "auto",
"quiet": true,
"rhgb": true,
"ro": true,
"root": "UUID=a6a0174b-0f9f-4b72-a404-439c25a15ec9"
},
"ansible_processor": [
"0",
"GenuineIntel",
"Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz"
],
"ansible_processor_cores": 1,
"ansible_processor_count": 1,
"ansible_processor_threads_per_core": 1,
"ansible_processor_vcpus": 1,
"ansible_product_name": "VMware Virtual Platform",
"ansible_product_serial": "VMware-56 4d f7 ae 22 ca 1a 94-0f 51 de bd d1 01 a8 c7",
"ansible_product_uuid": "AEF74D56-CA22-941A-0F51-DEBDD101A8C7",
"ansible_product_version": "None",
"ansible_python": {
"executable": "/usr/bin/python",
"has_sslcontext": true,
"type": "CPython",
"version": {
"major": 2,
"micro": 5,
"minor": 7,
"releaselevel": "final",
"serial": 0
},
"version_info": [
2,
7,
5,
"final",
0
]
},
"ansible_python_version": "2.7.5",
"ansible_real_group_id": 0,
"ansible_real_user_id": 0,
"ansible_selinux": {
"status": "disabled"
},
"ansible_selinux_python_present": true,
"ansible_service_mgr": "systemd",
"ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHN5nr0MqsICjVJdjFRKBty6woRTynokXmAIMVv2KDJatAe4s+AcJbeXa/F6STBNg3lSv7E/tMuRqfhg1HNgQXo=",
"ansible_ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIOdVpn9SHhP8EuyhGSVsf7PhpbGXVMA/Y0JPc4J3yGrB",
"ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQCwSeY75Lwu9XO7LrCAa/KB+e+5x/Sm8JtC6C70JUai/PHvL1uMWOalZtiPrCsaoNsokBLvnMjA/fqrAjY0Q+hVVifJt0tM4TgN5akeKQkrZsZ7WdxKZS8mMyxpgJFWvaPmBg+gCTDRQdafJJdXTwHJ70Gt/Fas85EF/uV4SUUMMUb/xts20BIOu0CznS9qmrWU8yS0p4AogSsmuWtnqzlqSaiEdpe38Cz6vIuZymsc0t4JltKu04cg2+D9pSp/YWXF/yMq2uVXidOgWQeTDkxX6hPu/qTau49DiSB/eS8+RUeguI5ibrr1brbl5hGODgI5e/yfCnZ/VxWXhcoJEF1D",
"ansible_swapfree_mb": 774,
"ansible_swaptotal_mb": 774,
"ansible_system": "Linux",
"ansible_system_capabilities": [
"cap_chown",
"cap_dac_override",
"cap_dac_read_search",
"cap_fowner",
"cap_fsetid",
"cap_kill",
"cap_setgid",
"cap_setuid",
"cap_setpcap",
"cap_linux_immutable",
"cap_net_bind_service",
"cap_net_broadcast",
"cap_net_admin",
"cap_net_raw",
"cap_ipc_lock",
"cap_ipc_owner",
"cap_sys_module",
"cap_sys_rawio",
"cap_sys_chroot",
"cap_sys_ptrace",
"cap_sys_pacct",
"cap_sys_admin",
"cap_sys_boot",
"cap_sys_nice",
"cap_sys_resource",
"cap_sys_time",
"cap_sys_tty_config",
"cap_mknod",
"cap_lease",
"cap_audit_write",
"cap_audit_control",
"cap_setfcap",
"cap_mac_override",
"cap_mac_admin",
"cap_syslog",
"35",
"36+ep"
],
"ansible_system_capabilities_enforced": "True",
"ansible_system_vendor": "VMware, Inc.",
"ansible_uptime_seconds": 5667,
"ansible_user_dir": "/root",
"ansible_user_gecos": "root",
"ansible_user_gid": 0,
"ansible_user_id": "root",
"ansible_user_shell": "/bin/bash",
"ansible_user_uid": 0,
"ansible_userspace_architecture": "x86_64",
"ansible_userspace_bits": "64",
"ansible_virtualization_role": "guest",
"ansible_virtualization_type": "VMware",
"discovered_interpreter_python": "/usr/bin/python",
"gather_subset": [
"all"
],
"module_setup": true
},
"changed": false
}

很多信息

ansibe2.9 api调用

简书挺详细的:https://www.jianshu.com/p/ec1e4d8438e9

官网  https://docs.ansible.com/ansible/latest/dev_guide/developing_api.html

查看版本信息

[root@mcw01 ~/mcw]$ ansible --version
ansible 2.9.27
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/mcw', u'/root/mcw']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Aug 4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
[root@mcw01 ~/mcw]$

api调用程序示例

#!/usr/bin/env python

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type import json
import shutil import ansible.constants as C
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.module_utils.common.collections import ImmutableDict
from ansible.inventory.manager import InventoryManager
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.play import Play
from ansible.plugins.callback import CallbackBase
from ansible.vars.manager import VariableManager
from ansible import context # Create a callback plugin so we can capture the output
class ResultsCollectorJSONCallback(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 __init__(self, *args, **kwargs):
super(ResultsCollectorJSONCallback, self).__init__(*args, **kwargs)
self.host_ok = {}
self.host_unreachable = {}
self.host_failed = {} def v2_runner_on_unreachable(self, result):
host = result._host
self.host_unreachable[host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs):
"""Print a json representation of the result. Also, store the result in an instance attribute for retrieval later
"""
host = result._host
self.host_ok[host.get_name()] = result
print(json.dumps({host.name: result._result}, indent=4)) def v2_runner_on_failed(self, result, *args, **kwargs):
host = result._host
self.host_failed[host.get_name()] = result def main():
host_list = ['10.0.0.12']#['localhost', 'www.example.com', 'www.google.com']
# since the API is constructed for CLI it expects certain options to always be set in the context object
context.CLIARGS = ImmutableDict(connection='smart', module_path=['/to/mymodules', '/usr/share/ansible'], forks=10, become=None,
become_method=None, become_user=None, check=False, diff=False)
# required for
# https://github.com/ansible/ansible/blob/devel/lib/ansible/inventory/manager.py#L204
sources = ','.join(host_list)
if len(host_list) == 1:
sources += ',' # initialize needed objects
loader = DataLoader() # Takes care of finding and reading yaml, json and ini files
passwords = dict(vault_pass='secret') # Instantiate our ResultsCollectorJSONCallback for handling results as they come in. Ansible expects this to be one of its main display outlets
results_callback = ResultsCollectorJSONCallback() # create inventory, use path to host config file as source or hosts in a comma separated string
inventory = InventoryManager(loader=loader, sources=sources) # variable manager takes care of merging all the different sources to give you a unified view of variables available in each context
variable_manager = VariableManager(loader=loader, inventory=inventory) # instantiate task queue manager, which takes care of forking and setting up all objects to iterate over host list and tasks
# IMPORTANT: This also adds library dirs paths to the module loader
# IMPORTANT: and so it must be initialized before calling `Play.load()`.
tqm = TaskQueueManager(
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
passwords=passwords,
stdout_callback=results_callback, # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout
) # create data structure that represents our play, including tasks, this is basically what our YAML loader does internally.
play_source = dict(
name="Ansible Play",
hosts=host_list,
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}}'))),
dict(action=dict(module='command', args=dict(cmd='/usr/bin/uptime'))),
]
) # Create play object, playbook objects use .load instead of init or new methods,
# this will also automatically create the task objects from the info provided in play_source
play = Play().load(play_source, variable_manager=variable_manager, loader=loader) # Actually run it
try:
result = tqm.run(play) # most interesting data for a play is actually sent to the callback's methods
finally:
# we always need to cleanup child procs and the structures we use to communicate with them
tqm.cleanup()
if loader:
loader.cleanup_all_tmp_files() # Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) print("UP ***********")
for host, result in results_callback.host_ok.items():
print('{0} >>> {1}'.format(host, result._result['stdout'])) print("FAILED *******")
for host, result in results_callback.host_failed.items():
print('{0} >>> {1}'.format(host, result._result['msg'])) print("DOWN *********")
for host, result in results_callback.host_unreachable.items():
print('{0} >>> {1}'.format(host, result._result['msg'])) if __name__ == '__main__':
main()

执行结果:

[root@mcw01 ~/mcw]$ python 2.9ansibleapi.py
{
"10.0.0.12": {
"stderr_lines": [],
"changed": true,
"end": "2022-10-23 22:28:26.502922",
"_ansible_no_log": false,
"stdout": "10.0.0.11\n11.py\n2.9ansibleapi.py\nanaconda-ks.cfg\nAnsible\napache-tomcat-8.0.27\napache-tomcat-8.0.27.tar.gz\ncpis\ndemo.sh\ndump.rdb\njpress-web-newest\njpress-web-newest.tar.gz\njpress-web-newest.war\nlogs\nmcw\nmcw.py\nsite-packages.zip\nsonarqube\nsonar-scanner-cli-4.7.0.2747-linux.zip\ntomcat",
"cmd": "ls",
"start": "2022-10-23 22:28:26.491623",
"delta": "0:00:00.011299",
"stderr": "",
"rc": 0,
"invocation": {
"module_args": {
"warn": true,
"executable": null,
"_uses_shell": true,
"strip_empty_ends": true,
"_raw_params": "ls",
"removes": null,
"argv": null,
"creates": null,
"chdir": null,
"stdin_add_newline": true,
"stdin": null
}
},
"stdout_lines": [
"10.0.0.11",
"11.py",
"2.9ansibleapi.py",
"anaconda-ks.cfg",
"Ansible",
"apache-tomcat-8.0.27",
"apache-tomcat-8.0.27.tar.gz",
"cpis",
"demo.sh",
"dump.rdb",
"jpress-web-newest",
"jpress-web-newest.tar.gz",
"jpress-web-newest.war",
"logs",
"mcw",
"mcw.py",
"site-packages.zip",
"sonarqube",
"sonar-scanner-cli-4.7.0.2747-linux.zip",
"tomcat"
],
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
}
}
}
{
"10.0.0.12": {
"msg": "10.0.0.11\n11.py\n2.9ansibleapi.py\nanaconda-ks.cfg\nAnsible\napache-tomcat-8.0.27\napache-tomcat-8.0.27.tar.gz\ncpis\ndemo.sh\ndump.rdb\njpress-web-newest\njpress-web-newest.tar.gz\njpress-web-newest.war\nlogs\nmcw\nmcw.py\nsite-packages.zip\nsonarqube\nsonar-scanner-cli-4.7.0.2747-linux.zip\ntomcat",
"changed": false,
"_ansible_verbose_always": true,
"_ansible_no_log": false
}
}
{
"10.0.0.12": {
"stderr_lines": [],
"cmd": [
"/usr/bin/uptime"
],
"end": "2022-10-23 22:28:27.178912",
"_ansible_no_log": false,
"stdout": " 22:28:27 up 1 day, 6:46, 2 users, load average: 0.00, 0.01, 0.05",
"changed": true,
"rc": 0,
"start": "2022-10-23 22:28:27.165476",
"stderr": "",
"delta": "0:00:00.013436",
"invocation": {
"module_args": {
"creates": null,
"executable": null,
"_uses_shell": false,
"strip_empty_ends": true,
"_raw_params": "/usr/bin/uptime",
"removes": null,
"argv": null,
"warn": true,
"chdir": null,
"stdin_add_newline": true,
"stdin": null
}
},
"stdout_lines": [
" 22:28:27 up 1 day, 6:46, 2 users, load average: 0.00, 0.01, 0.05"
]
}
}
UP ***********
10.0.0.12 >>> 22:28:27 up 1 day, 6:46, 2 users, load average: 0.00, 0.01, 0.05
FAILED *******
DOWN *********
[root@mcw01 ~/mcw]$

我们将上面的程序,任务列表里的两个注释掉,只保留一个  执行uptime的命令。执行脚本,应该是相当于执行ansible 10.0.0.12 -m command -a "/usr/bin/uptime"

    play_source = dict(
name="Ansible Play",
hosts=host_list,
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}}'))),
dict(action=dict(module='command', args=dict(cmd='/usr/bin/uptime'))),
]
)

这相当于写剧本的方式。使用哪个模块,参数是什么。

看修改后的执行结果:有执行结果数据。

[root@mcw01 ~/mcw]$ python 2.9ansibleapi.py
{
"10.0.0.12": {
"stderr_lines": [],
"cmd": [
"/usr/bin/uptime"
],
"end": "2022-10-23 22:36:23.669234",
"_ansible_no_log": false,
"stdout": " 22:36:23 up 1 day, 6:54, 2 users, load average: 0.13, 0.04, 0.05",
"changed": true,
"rc": 0,
"start": "2022-10-23 22:36:23.658986",
"stderr": "",
"delta": "0:00:00.010248",
"invocation": {
"module_args": {
"creates": null,
"executable": null,
"_uses_shell": false,
"strip_empty_ends": true,
"_raw_params": "/usr/bin/uptime",
"removes": null,
"argv": null,
"warn": true,
"chdir": null,
"stdin_add_newline": true,
"stdin": null
}
},
"stdout_lines": [
" 22:36:23 up 1 day, 6:54, 2 users, load average: 0.13, 0.04, 0.05"
],
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
}
}
}
UP ***********
10.0.0.12 >>> 22:36:23 up 1 day, 6:54, 2 users, load average: 0.13, 0.04, 0.05
FAILED *******
DOWN *********
[root@mcw01 ~/mcw]$

最后的三个打印是任务执行ok或者失败或者主机不可达的结果打印。我们这里是正常执行命令获取到uptime数据。所以是ok那里打印出了数据。它是for循环后面的,然后获取到主机和主机执行命令的结果。

api调用程序分析(类似于runner ip)

我们只需要定义好hosts主机,主机组。然后定义好任务就可以了。如果有需要,可以对执行返回结果做些操作。:

[root@mcw01 ~/mcw]$ cat 2.9ansibleapi.py
#!/usr/bin/env python from __future__ import (absolute_import, division, print_function)
__metaclass__ = type import json
import shutil import ansible.constants as C
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.module_utils.common.collections import ImmutableDict
from ansible.inventory.manager import InventoryManager
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.play import Play
from ansible.plugins.callback import CallbackBase
from ansible.vars.manager import VariableManager
from ansible import context # Create a callback plugin so we can capture the output
class ResultsCollectorJSONCallback(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 __init__(self, *args, **kwargs):
super(ResultsCollectorJSONCallback, self).__init__(*args, **kwargs)
self.host_ok = {}
self.host_unreachable = {}
self.host_failed = {} def v2_runner_on_unreachable(self, result):
host = result._host
self.host_unreachable[host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs):
"""Print a json representation of the result. Also, store the result in an instance attribute for retrieval later
"""
host = result._host
self.host_ok[host.get_name()] = result
print(json.dumps({host.name: result._result}, indent=4)) #这就是我们在执行程序之后看到的结果json.成功才有 def v2_runner_on_failed(self, result, *args, **kwargs):
host = result._host
self.host_failed[host.get_name()] = result def main():
host_list = ['10.0.0.12']#定义主机['localhost', 'www.example.com', 'www.google.com']
# since the API is constructed for CLI it expects certain options to always be set in the context object
context.CLIARGS = ImmutableDict(connection='smart', module_path=['/to/mymodules', '/usr/share/ansible'], forks=10, become=None,
become_method=None, become_user=None, check=False, diff=False)
# required for
# https://github.com/ansible/ansible/blob/devel/lib/ansible/inventory/manager.py#L204
sources = ','.join(host_list)
if len(host_list) == 1:
sources += ',' #将主机以逗号分隔都拼接起来,如果只有一个数据,那么ip后面拼接个逗号
print(sources) # 结果: 10.0.0.12,
# initialize needed objects
loader = DataLoader() #打印结果<ansible.parsing.dataloader.DataLoader object at 0x1156fd0># Takes care of finding and reading yaml, json and ini files
passwords = dict(vault_pass='secret') #打印结果:{'vault_pass': 'secret'} # Instantiate our ResultsCollectorJSONCallback for handling results as they come in. Ansible expects this to be one of its main display outlets
results_callback = ResultsCollectorJSONCallback() #结果:回调函数对象 # create inventory, use path to host config file as source or hosts in a comma separated string
inventory = InventoryManager(loader=loader, sources=sources) #打印结果:inventory管理对象<ansible.inventory.manager.InventoryManager object at 0x1fe3550>
#数据加载对象,10.0.0.12,
# variable manager takes care of merging all the different sources to give you a unified view of variables available in each context
variable_manager = VariableManager(loader=loader, inventory=inventory) #变量管理对象<ansible.vars.manager.VariableManager object at 0x208d5d0> # instantiate task queue manager, which takes care of forking and setting up all objects to iterate over host list and tasks
# IMPORTANT: This also adds library dirs paths to the module loader
# IMPORTANT: and so it must be initialized before calling `Play.load()`.
tqm = TaskQueueManager( #打印结果:任务队列管理对象
inventory=inventory, #任务对象管理对象,传inventory管理对象,传变量管理对象,传数据加载对象,传密码,传回调函数对象
variable_manager=variable_manager, #上面跟我们相关的只有主机列表,其它不变就行啊。传递的参数都是刚刚定义好的
loader=loader,
passwords=passwords,
stdout_callback=results_callback, # Use our custom callback instead of the ``default`` callback plugin, which prints to stdout
) # create data structure that represents our play, including tasks, this is basically what our YAML loader does internally.
play_source = dict( #剧本源,是个字典,指定剧本名称吗?指定主机列表,指定是否需要收集facts
name="Ansible Play", #指定任务列表,任务列表中可以存放多个任务。
hosts=host_list, #这跟写剧本似的,剧本就是多个任务聚集起来的。每个任务有name,有使用哪个模块,使用了什么参数。
gather_facts='no', #这里也是这样。剧本里面还可以定义变量,循环,判断,注册变量等等,这些写法应该是不同的。如下,
tasks=[ #将任务一ls的执行结果注册为变量,变量名是shell_out。第二个任务调用这个注册变量的变量名,然后点stdout得到注册变量shell执行的标准输出
# dict(action=dict(module='shell', args='ls'), register='shell_out'),#这就是变量在任务之间的传递。可以参考写剧本,去找这个任务列表怎么实现对应功能的
# dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))),  #所以我们需要在任务列表中执行任务,在hosts中定义主机和主机组。有这两个基本上
dict(action=dict(module='command', args=dict(cmd='/usr/bin/uptime'))), #就能写剧本了,实现剧本功能了。我们主要关注这两点
]
) # Create play object, playbook objects use .load instead of init or new methods,
# this will also automatically create the task objects from the info provided in play_source
play = Play().load(play_source, variable_manager=variable_manager, loader=loader) #打印结果:Ansible Play,估计是用了str方法了。
#实例化一个剧本对象,将剧本源(名字,主机,是否收集facts,有哪些剧本任务)导入到剧本对象;两变量管理对象导入到剧本对象中,将数据加载对象导入。估计内部会进行变量渲染等等之类的吧。暂时不需要关心
# Actually run it
try: #运行剧本。将剧本传入到任务队列管理里面的run方法中。这里面应该是对剧本任务进行消费。剧本对象传到任务队列里面了。里面包含了剧本需要的主机,剧本有哪些任务,剧本使用的变量等。
result = tqm.run(play) # most interesting data for a play is actually sent to the callback's methods
finally: #result打印结果好像只是个0,难道是显示执行成功的意思?我们看到执行的结果字典,应该就是在result和play之间哪里打印的。如果没有意外应该是result这里,运行剧本任务
# we always need to cleanup child procs and the structures we use to communicate with them #然后将运行结果在终端上打印出来这个结果字典
tqm.cleanup() #清理临时文件,也就是执行任务的过程中,会创建临时文件。任务执行完成,对临时文件进行清理。我们写程序也可以这样做。
if loader:
loader.cleanup_all_tmp_files() # Remove ansible tmpdir #C.DEFAULT_LOCAL_TMP是/root/.ansible/tmp/ansible-local-16916wo3RhL目录,里面有个临时文件101 /root/.ansible/tmp/ansible-tmp-1666015891.13-5454-129638497331557/AnsiballZ_command.py 。
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) print("results_callback: ",results_callback) #<__main__.ResultsCollectorJSONCallback object at 0x2858550>
print("results_callback.host_ok",results_callback.host_ok) #{'10.0.0.12': <ansible.executor.task_result.TaskResult object at 0x203dd90>}
print("results_callback.host_ok.items: ",results_callback.host_ok.items()) #[('10.0.0.12', <ansible.executor.task_result.TaskResult object at 0x203dd90>)]
for host, result in results_callback.host_ok.items():
print(host,result) #10.0.0.12 <ansible.executor.task_result.TaskResult object at 0x203dd90>
print("result._result: ",result._result)
print("结果对象里找表准输出,就是剧本执行的输出信息,这里就是命令uptime的执行打印结果: ",result._result['stdout']) {'stderr_lines': [], u'cmd': [u'/usr/bin/uptime'], u'end': u'2022-10-24 00:31:38.590871', '_ansible_no_log': False, u'stdout': u' 00:31:38 up 1 day, 8:49, 2 users, load average: 0.00, 0.01, 0.05', u'changed': True, u'rc': 0, u'start': u'2022-10-24 00:31:38.580309', u'stderr': u'', u'delta': u'0:00:00.010562', u'invocation': {u'module_args': {u'creates': None, u'executable': None, u'_uses_shell': False, u'strip_empty_ends': True, u'_raw_params': u'/usr/bin/uptime', u'removes': None, u'argv': None, u'warn': True, u'chdir': None, u'stdin_add_newline': True, u'stdin': None}}, 'stdout_lines': [u' 00:31:38 up 1 day, 8:49, 2 users, load average: 0.00, 0.01, 0.05'], 'ansible_facts': {u'discovered_interpreter_python': u'/usr/bin/python'}} 将数据整理如下:
{'stderr_lines': [],
u'cmd': [u'/usr/bin/uptime'],
u'end': u'2022-10-24 00:31:38.590871',
'_ansible_no_log': False,
u'stdout': u' 00:31:38 up 1 day, 8:49, 2 users, load average: 0.00, 0.01, 0.05',
u'changed': True,
u'rc': 0,
u'start': u'2022-10-24 00:31:38.580309',
u'stderr': u'',
u'delta': u'0:00:00.010562',
u'invocation': {
u'module_args': {u'creates': None,
u'executable': None,
u'_uses_shell': False,
u'strip_empty_ends': True,
u'_raw_params': u'/usr/bin/uptime',
u'removes': None,
u'argv': None,
u'warn': True,
u'chdir': None,
u'stdin_add_newline': True,
u'stdin': None
}
},
'stdout_lines': [u' 00:31:38 up 1 day, 8:49, 2 users, load average: 0.00, 0.01, 0.05'],
'ansible_facts': {u'discovered_interpreter_python': u'/usr/bin/python'}}
上面是result._result打印出来的。也就是我们需要指定的键,直接字典的方式取值就行了。标准输出就是命令的结果。回调函数,运行ok下面打印的也是这个 print("UP ***********")
for host, result in results_callback.host_ok.items():
print('{0} >>> {1}'.format(host, result._result['stdout'])) print("FAILED *******")
for host, result in results_callback.host_failed.items():
#当我们的任务里面dict(action=dict(module='command', args=dict(cmd='cat /usr/bin/uptimebbb'))),查看不存在的文件匹配到失败时。打印信息如下
print('{0} >>> {1}'.format(host, result._result['msg'])) #10.0.0.12 >>> non-zero return code
print("失败:",result._result)
失败: {'stderr_lines': [u'cat: /usr/bin/uptimebbb: No such file or directory'], u'cmd': [u'cat', u'/usr/bin/uptimebbb'], u'stdout': u'', u'msg': u'non-zero return code', u'delta': u'0:00:00.011209', 'stdout_lines': [], 'ansible_facts': {u'discovered_interpreter_python': u'/usr/bin/python'}, u'end': u'2022-10-24 00:44:23.455248', '_ansible_no_log': False, u'changed': True, u'start': u'2022-10-24 00:44:23.444039', u'stderr': u'cat: /usr/bin/uptimebbb: No such file or directory', u'rc': 1, u'invocation': {u'module_args': {u'creates': None, u'executable': None, u'_uses_shell': False, u'strip_empty_ends': True, u'_raw_params': u'cat /usr/bin/uptimebbb', u'removes': None, u'argv': None, u'warn': True, u'chdir': None, u'stdin_add_newline': True, u'stdin': None}}} 整理如下:我们这里定义打印的是msg.,
{'stderr_lines': [u'cat: /usr/bin/uptimebbb: No such file or directory'],
u'cmd': [u'cat', u'/usr/bin/uptimebbb'],
u'stdout': u'',
u'msg': u'non-zero return code',
u'delta': u'0:00:00.011209',
'stdout_lines': [],
'ansible_facts': {u'discovered_interpreter_python': u'/usr/bin/python'},
u'end': u'2022-10-24 00:44:23.455248',
'_ansible_no_log': False,
u'changed': True,
u'start': u'2022-10-24 00:44:23.444039',
u'stderr': u'cat: /usr/bin/uptimebbb: No such file or directory',
u'rc': 1,
u'invocation': {
u'module_args': {u'creates': None,
u'executable': None,
u'_uses_shell': False,
u'strip_empty_ends': True,
u'_raw_params': u'cat /usr/bin/uptimebbb',
u'removes': None,
u'argv': None,
u'warn': True,
u'chdir': None,
u'stdin_add_newline': True,
u'stdin': None}} } print("DOWN *********")
for host, result in results_callback.host_unreachable.items():
print('{0} >>> {1}'.format(host, result._result['msg'])) if __name__ == '__main__':
main()
[root@mcw01 ~/mcw]$

2.9传参的方式,执行命令,实现runner api。

[root@mcw01 ~/mcw]$ cat mytest.py
# _*_ coding:utf-8 __*__
# !/usr/bin/env python from __future__ import (absolute_import, division, print_function) __metaclass__ = type import json
import shutil import ansible.constants as C
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.module_utils.common.collections import ImmutableDict
from ansible.inventory.manager import InventoryManager
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.play import Play
from ansible.plugins.callback import CallbackBase
from ansible.vars.manager import VariableManager
from ansible import context # Create a callback plugin so we can capture the output
class ResultsCollectorJSONCallback(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 __init__(self, *args, **kwargs):
super(ResultsCollectorJSONCallback, self).__init__(*args, **kwargs)
self.host_ok = {}
self.host_unreachable = {}
self.host_failed = {} def v2_runner_on_unreachable(self, result):
host = result._host
self.host_unreachable[host.get_name()] = result def v2_runner_on_ok(self, result, *args, **kwargs):
"""Print a json representation of the result. Also, store the result in an instance attribute for retrieval later
"""
host = result._host
self.host_ok[host.get_name()] = result
print(json.dumps({host.name: result._result}, indent=4)) def v2_runner_on_failed(self, result, *args, **kwargs):
host = result._host
self.host_failed[host.get_name()] = result def main(host_list,module_name,module_args):
host_list = host_list # ['localhost', 'www.example.com', 'www.google.com']
# since the API is constructed for CLI it expects certain options to always be set in the context object
context.CLIARGS = ImmutableDict(connection='smart', module_path=['/to/mymodules', '/usr/share/ansible'], forks=10,
become=None,
become_method=None, become_user=None, check=False, diff=False)
# required for
# https://github.com/ansible/ansible/blob/devel/lib/ansible/inventory/manager.py#L204
sources = ','.join(host_list)
if len(host_list) == 1:
sources += ','
# initialize needed objects
loader = DataLoader() # Takes care of finding and reading yaml, json and ini files
passwords = dict(vault_pass='secret')
# Instantiate our ResultsCollectorJSONCallback for handling results as they come in. Ansible expects this to be one of its main display outlets
results_callback = ResultsCollectorJSONCallback() # create inventory, use path to host config file as source or hosts in a comma separated string
inventory = InventoryManager(loader=loader, sources=sources) # variable manager takes care of merging all the different sources to give you a unified view of variables available in each context
variable_manager = VariableManager(loader=loader, inventory=inventory) # instantiate task queue manager, which takes care of forking and setting up all objects to iterate over host list and tasks
# IMPORTANT: This also adds library dirs paths to the module loader
# IMPORTANT: and so it must be initialized before calling `Play.load()`.
tqm = TaskQueueManager(
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
passwords=passwords,
stdout_callback=results_callback,
# Use our custom callback instead of the ``default`` callback plugin, which prints to stdout
) # create data structure that represents our play, including tasks, this is basically what our YAML loader does internally.
play_source = dict(
name="Ansible Play",
hosts=host_list,
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}}'))),
# dict(action=dict(module='command', args=dict(cmd='cat /usr/bin/uptimebbb'))),
dict(action=dict(module=module_name, args=module_args)),
]
) # Create play object, playbook objects use .load instead of init or new methods,
# this will also automatically create the task objects from the info provided in play_source
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
# Actually run it
try:
result = tqm.run(play) # most interesting data for a play is actually sent to the callback's methods
finally:
# we always need to cleanup child procs and the structures we use to communicate with them
tqm.cleanup()
if loader:
loader.cleanup_all_tmp_files() # Remove ansible tmpdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True) print("UP ***********")
for host, result in results_callback.host_ok.items():
print('{0} >>> {1}'.format(host, result._result['stdout'])) print("FAILED *******")
for host, result in results_callback.host_failed.items():
print('{0} >>> {1}'.format(host, result._result['msg']))
print("失败:", result._result)
print("DOWN *********")
for host, result in results_callback.host_unreachable.items():
print('{0} >>> {1}'.format(host, result._result['msg']))
print("不可达:", result._result) if __name__ == '__main__':
option_dict={"become":True,"remote_user":"root"}
module_name = 'shell'
module_args = "/usr/bin/uptime"
host_list = ['10.0.0.11','10.0.0.12']
main(host_list,module_name,module_args) [root@mcw01 ~/mcw]$

执行结果:

[root@mcw01 ~/mcw]$ python mytest.py
{
"10.0.0.12": {
"stderr_lines": [],
"cmd": "/usr/bin/uptime",
"end": "2022-10-24 01:28:10.831660",
"_ansible_no_log": false,
"stdout": " 01:28:10 up 1 day, 9:46, 2 users, load average: 0.00, 0.01, 0.05",
"changed": true,
"rc": 0,
"start": "2022-10-24 01:28:10.820105",
"stderr": "",
"delta": "0:00:00.011555",
"invocation": {
"module_args": {
"creates": null,
"executable": null,
"_uses_shell": true,
"strip_empty_ends": true,
"_raw_params": "/usr/bin/uptime",
"removes": null,
"argv": null,
"warn": true,
"chdir": null,
"stdin_add_newline": true,
"stdin": null
}
},
"stdout_lines": [
" 01:28:10 up 1 day, 9:46, 2 users, load average: 0.00, 0.01, 0.05"
],
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
}
}
}
{
"10.0.0.11": {
"stderr_lines": [],
"cmd": "/usr/bin/uptime",
"end": "2022-10-24 01:28:11.153952",
"_ansible_no_log": false,
"stdout": " 01:28:11 up 1 day, 9:46, 4 users, load average: 0.68, 0.31, 0.24",
"changed": true,
"rc": 0,
"start": "2022-10-24 01:28:11.093208",
"stderr": "",
"delta": "0:00:00.060744",
"invocation": {
"module_args": {
"creates": null,
"executable": null,
"_uses_shell": true,
"strip_empty_ends": true,
"_raw_params": "/usr/bin/uptime",
"removes": null,
"argv": null,
"warn": true,
"chdir": null,
"stdin_add_newline": true,
"stdin": null
}
},
"stdout_lines": [
" 01:28:11 up 1 day, 9:46, 4 users, load average: 0.68, 0.31, 0.24"
],
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
}
}
}
UP ***********
10.0.0.11 >>> 01:28:11 up 1 day, 9:46, 4 users, load average: 0.68, 0.31, 0.24
10.0.0.12 >>> 01:28:10 up 1 day, 9:46, 2 users, load average: 0.00, 0.01, 0.05
FAILED *******
DOWN *********
[root@mcw01 ~/mcw]$

打印的东西就是我们程序能实实现的一个功能

ansible 1.9.6 api调用

runner api 简单调用案例,以及Runner类的初始化参数大全

程序:

import  ansible.runner
runner=ansible.runner.Runner(module_name='shell',module_args='hostname',pattern='all',forks=10)
result=runner.run()
for host,ret in result['contacted'].items():
print(host,ret['stdout'])

只需要将模块名字,你用的参数,以及主机和主机组传进来就可以了。因为ad-hoc模式有这三个就可以使用了。想要更多信息那就看它的其它参数

执行结果

我将源码Runner类的参数放到下面,供参数设置使用

class Runner(object):
''' core API interface to ansible ''' # see bin/ansible for how this is used... def __init__(self,
host_list=C.DEFAULT_HOST_LIST, # ex: /etc/ansible/hosts, legacy usage
module_path=None, # ex: /usr/share/ansible
module_name=C.DEFAULT_MODULE_NAME, # ex: copy
module_args=C.DEFAULT_MODULE_ARGS, # ex: "src=/tmp/a dest=/tmp/b"
forks=C.DEFAULT_FORKS, # parallelism level
timeout=C.DEFAULT_TIMEOUT, # SSH timeout
pattern=C.DEFAULT_PATTERN, # which hosts? ex: 'all', 'acme.example.org'
remote_user=C.DEFAULT_REMOTE_USER, # ex: 'username'
remote_pass=C.DEFAULT_REMOTE_PASS, # ex: 'password123' or None if using key
remote_port=None, # if SSH on different ports
private_key_file=C.DEFAULT_PRIVATE_KEY_FILE, # if not using keys/passwords
background=0, # async poll every X seconds, else 0 for non-async
basedir=None, # directory of playbook, if applicable
setup_cache=None, # used to share fact data w/ other tasks
vars_cache=None, # used to store variables about hosts
transport=C.DEFAULT_TRANSPORT, # 'ssh', 'paramiko', 'local'
conditional='True', # run only if this fact expression evals to true
callbacks=None, # used for output
module_vars=None, # a playbooks internals thing
play_vars=None, #
play_file_vars=None, #
role_vars=None, #
role_params=None, #
default_vars=None, #
extra_vars=None, # extra vars specified with he playbook(s)
is_playbook=False, # running from playbook or not?
inventory=None, # reference to Inventory object
subset=None, # subset pattern
check=False, # don't make any changes, just try to probe for potential changes
diff=False, # whether to show diffs for template files that change
environment=None, # environment variables (as dict) to use inside the command
complex_args=None, # structured data in addition to module_args, must be a dict
error_on_undefined_vars=C.DEFAULT_UNDEFINED_VAR_BEHAVIOR, # ex. False
accelerate=False, # use accelerated connection
accelerate_ipv6=False, # accelerated connection w/ IPv6
accelerate_port=None, # port to use with accelerated connection
vault_pass=None,
run_hosts=None, # an optional list of pre-calculated hosts to run on
no_log=False, # option to enable/disable logging for a given task
run_once=False, # option to enable/disable host bypass loop for a given task
become=False, # whether to run privelege escalation or not
become_method=C.DEFAULT_BECOME_METHOD,
become_user=C.DEFAULT_BECOME_USER, # ex: 'root'
become_pass=C.DEFAULT_BECOME_PASS, # ex: 'password123' or None
become_exe=C.DEFAULT_BECOME_EXE, # ex: /usr/local/bin/sudo
): # used to lock multiprocess inputs and outputs at various levels
self.output_lockfile = OUTPUT_LOCKFILE
self.process_lockfile = PROCESS_LOCKFILE if not complex_args:
complex_args = {} # storage & defaults
self.check = check
self.diff = diff
self.setup_cache = utils.default(setup_cache, lambda: ansible.cache.FactCache())
self.vars_cache = utils.default(vars_cache, lambda: collections.defaultdict(dict))
self.basedir = utils.default(basedir, lambda: os.getcwd())
self.callbacks = utils.default(callbacks, lambda: DefaultRunnerCallbacks())
self.generated_jid = str(random.randint(0, 999999999999))
self.transport = transport
self.inventory = utils.default(inventory, lambda: ansible.inventory.Inventory(host_list)) self.module_vars = utils.default(module_vars, lambda: {})
self.play_vars = utils.default(play_vars, lambda: {})
self.play_file_vars = utils.default(play_file_vars, lambda: {})
self.role_vars = utils.default(role_vars, lambda: {})
self.role_params = utils.default(role_params, lambda: {})
self.default_vars = utils.default(default_vars, lambda: {})
self.extra_vars = utils.default(extra_vars, lambda: {}) self.always_run = None
self.connector = connection.Connector(self)
self.conditional = conditional
self.delegate_to = None
self.module_name = module_name
self.forks = int(forks)
self.pattern = pattern
self.module_args = module_args
self.timeout = timeout
self.remote_user = remote_user
self.remote_pass = remote_pass
self.remote_port = remote_port
self.private_key_file = private_key_file
self.background = background
self.become = become
self.become_method = become_method
self.become_user_var = become_user
self.become_user = None
self.become_pass = become_pass
self.become_exe = become_exe
self.is_playbook = is_playbook
self.environment = environment
self.complex_args = complex_args
self.error_on_undefined_vars = error_on_undefined_vars
self.accelerate = accelerate
self.accelerate_port = accelerate_port
self.accelerate_ipv6 = accelerate_ipv6
self.callbacks.runner = self
self.omit_token = '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest()
self.vault_pass = vault_pass
self.no_log = no_log
self.run_once = run_once

我们直接打印结果json数据。刚刚是取了标准输出了。

result是如下字典。多个主机的执行情况

{'dark': {}, 'contacted': {
'10.0.0.11': {u'changed': True, u'end': u'2022-10-24 07:19:40.639601', u'stdout': u'mcw01', u'cmd': u'hostname',
u'start': u'2022-10-24 07:19:40.625335', u'delta': u'0:00:00.014266', u'stderr': u'', u'rc': 0,
'invocation': {'module_name': 'shell', 'module_complex_args': {}, 'module_args': u'hostname'},
u'warnings': []},
'10.0.0.13': {u'changed': True, u'end': u'2022-10-24 13:58:03.096806', u'stdout': u'mcw03', u'cmd': u'hostname',
u'start': u'2022-10-24 13:58:03.087297', u'delta': u'0:00:00.009509', u'stderr': u'', u'rc': 0,
'invocation': {'module_name': 'shell', 'module_complex_args': {}, 'module_args': u'hostname'},
u'warnings': []},
'10.0.0.12': {u'changed': True, u'end': u'2022-10-24 13:58:03.530927', u'stdout': u'mcw02', u'cmd': u'hostname',
u'start': u'2022-10-24 13:58:03.504361', u'delta': u'0:00:00.026566', u'stderr': u'', u'rc': 0,
'invocation': {'module_name': 'shell', 'module_complex_args': {}, 'module_args': u'hostname'},
u'warnings': []}}}

ret单个主机的信息如下:

{'10.0.0.11':
{u'changed': True,
u'end': u'2022-10-24 07:19:40.639601',
u'stdout': u'mcw01',
u'cmd': u'hostname',
u'start': u'2022-10-24 07:19:40.625335',
u'delta': u'0:00:00.014266',
u'stderr': u'',
u'rc': 0,
'invocation': {
'module_name': 'shell',
'module_complex_args': {},
'module_args': u'hostname'
},
u'warnings': []
} }

按理说错误信息放到dark里面了。但是我这里收不到错误信息。

runner api 不只是打印成功的,还打印执行失败的错误信息

import sys
sys.path.append("/root/untitled6/Lib/site-packages")
import ansible.runner
runner=ansible.runner.Runner(module_name='shell',host_list="/root/hosts",module_args='hostname',pattern='all',forks=10)
result=runner.run()
print(result)
print("##############################")
for host,ret in result['contacted'].items():
print(host,ret['stdout'])
for host,ret in result['dark'].items():
print(host,ret['msg'])

playbook api

[root@mcw02 ~/ansible]$ cat key.yaml
- hosts: "{{ hosts }}"
gather_facts: false
tasks:
- name: key
authorized_key: user=root key="{{ lookup('file','/root/.ssh/id_rsa.pub') }}"
[root@mcw02 ~/ansible]$ cat playapi.py #api.
from ansible.inventory import Inventory
from ansible.playbook import PlayBook
from ansible import callbacks
inventory=Inventory('./hosts')
stats=callbacks.AggregateStats()
playbook_cb=callbacks.PlaybookCallbacks()
runner_cb=callbacks.PlaybookRunnerCallbacks(stats)
results=PlayBook(playbook='key.yaml',callbacks=playbook_cb,runner_callbacks=runner_cb,stats=stats,inventory=inventory,extra_vars={'hosts':'all'})
res=results.run()
print(res)
[root@mcw02 ~/ansible]$

如下,确实调用了剧本key。yaml。我们传递的变量给模板,是所有主机,也是生效的。打印结果是json数据。我们指定了inventory文件。剧本实现了公钥分发到其它主机,将本机公钥写入了其它主机.ssh/authorized_keys中

返回的结果有点简单

{'10.0.0.11': {'unreachable': 0, 'skipped': 0, 'ok': 1, 'changed': 1, 'failures': 0},
'10.0.0.13': {'unreachable': 0, 'skipped': 0, 'ok': 1, 'changed': 1, 'failures': 0},
'10.0.0.12': {'unreachable': 1, 'skipped': 0, 'ok': 0, 'changed': 0, 'failures': 0}}

使用flask封装我们的api,提供http远程执行ansible命令

效果

我们的程序运行在主机2上

我们在主机3上执行curl命令访问接口,让主机2上的程序查主机3上的文件,成功返回执行结果,与主机3上的文件一致

我们在浏览器上访问接口,成功返回数据

此时,主机2是我们flask程序所在主机,也是ansible的主控机。我们可以通过http形式,在主机2上执行ad-hoc命令,使用各种模块。这就是使用flask封装了ansible的runner

api效果。下面我们看其他的。我们已经知道主机3中有mcw.py,那么我们看一下文件内容。我们可以看到跟主机上是一样的。由此我们就能通过写前端页面,进行各种post和get请求,是对ansible api的请求,那么我们在网页上可以实现管理一群机器了。也可以用ansible写控制台

我们根据调用剧本api,传的是剧本名称。后端会根据路径拼接成yaml文件。然后调用剧本api执行剧本。如果没有写路径,默认会从项目根路径找文件,如下。如果写了路径,就会找该路径下的文件

程序

下面就是flask蓝图

#_*_ coding:utf-8 __*__
from flask import Blueprint,request, render_template, redirect,abort
from apps.user.models import User
from ext import db import json
import ansible.runner
from ansible.inventory import Inventory
from ansible.playbook import PlayBook
from ansible import callbacks ansibleAPI_bp=Blueprint('ansibleAPI',__name__) @ansibleAPI_bp.route('/',methods=['GET','POST'])
def index():
return 'ok' hostfile='/root/ansible/hosts'
@ansibleAPI_bp.route('/API/Ansible/playbook',methods=['GET','POST'])
def Playbook():
"""
http://127.0.0.1:5000/API/Asible/playbook?ip=2.2.2.2&playbook=test
:return:
"""
print(request.args.get('playbook'))
vars={}
inventory = Inventory(hostfile)
stats = callbacks.AggregateStats()
playbook_cb = callbacks.PlaybookCallbacks()
runner_cb = callbacks.PlaybookRunnerCallbacks(stats)
hosts=request.args.get('ip')
task=request.args.get('playbook')
vars['hosts']=hosts
play=task+'.yaml'
results = PlayBook(playbook=play, callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats,
inventory=inventory, extra_vars=vars )
res = results.run()
return json.dumps(res,indent=4)
@ansibleAPI_bp.route('/API/Ansible/runner',methods=['GET','POST'])
def Runner():
"""
curl -H "Conten-Type: application/json" -X POST -d '{"ip":"1.1.1.1","module":"shell","args":"ls -l"}' http://127.0.0.1:5000/API/Ansible/runner
:return:
"""
print(request.args)
hosts=request.args.get('ip',None)
module=request.args.get('module',None)
args=request.args.get('args',None)
if hosts is None or module is None or args is None:
abort(400)
runner = ansible.runner.Runner(module_name=module, module_args=args, pattern=hosts, forks=10,host_list=hostfile)
tasks= runner.run()
cpis={}
cpis1={}
for (hostname, result) in tasks['contacted'].items():
if not 'failed' in result:
cpis[hostname]=result['stdout']
for (hostname, result) in tasks['dark'].items():
cpis1[hostname]=result['msg']
return render_template('ansibleApi/cpis.html',cpis=cpis,cpis1=cpis1)

下面是前端程序cpis.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>魔降风云变</title>
</head>
<body> <h1>################成功设备列表#######################</h1>
{% for k,v in cpis.items() %}
===========主机{{ k }}执行返回结果:================<br>
{{ v }}<br>
{% endfor %} <h1>##################失败设备列表#####################</h1>
{% for a,b in cpis1.items() %}
===========主机{{ a }}执行返回结果================<br>
{{ b }}<br>
{% endfor %}
</body>
</html>

ansible 1.9 api 复制即用,不影响系统原有环境

需要用到sys.path.append(“..“),可以了解这里:https://blog.csdn.net/universe_R/article/details/123370672

遇到的问题,当我们appen加入到sys.path中后,依然找不到模块:

此时我打印sys.path查看到默认的搜索路径,根据默认的包搜索路径过滤找到了其他人安装的ansibe 2.9的包。也就是没有找到包,因为这个包的搜索顺序在前,那么我们将我们的1.9的包路径insert到列表中第一个元素前。

经过测试,当我们执行程序时,打印出的sys.path会添加程序执行当前目录,然后添加上我们insert或者append进去的路径,我们让自己的程序sleep多运行一会 ;在另外一处,我们隔两秒打印一次sys.path,发现并没有正在运行的程序添加的路径。也就是说,执行python程序,有公共的包搜索路径,如果你执行的程序加入了其它的包搜索路径是不会影响公共的python路径的,我们程序加进去的包路是临时加进去,只对当前执行的程序生效,对其它程序是没有影响的。也就是说,我们使用sys.path.append 或者是insert是安全的,不会因为当前程序的搜索包路径的优先级对其它可能存在的python程序产生影响,因为加进去的路径只对当前程序生效

import sys
sys.path.append("/root/untitled6/Lib/site-packages")
import ansible.runner
runner=ansible.runner.Runner(module_name='shell',host_list="/root/hosts",module_args='hostname',pattern='all',forks=10)
result=runner.run()
print(result)
print("##############################")
for host,ret in result['contacted'].items():
print(host,ret['stdout'])
for host,ret in result['dark'].items():
print(host,ret['msg'])

首先我们看一下pycharm中环境。untitled6是windows上pycharm创建的一个项目,带有虚拟环境的。在pycharm中安装ansibe包失败,但是ansible依赖包已经装上了。在centos7虚拟机上源码包安装了ansibe 1.9,我们从python2.7的包目录下把ansibe包拷贝到笔记本的untitled6的虚拟环境包目录下了。也就是有了如下的ansibe包

接下来我们看我们下面需要操作的Linux服务器。我们新装了三个虚拟机。目前是没有ansible的。我是提前将主机1的公钥分发到主机2和3上了,然后免密第一次登录上2和3.不太确定是否需要设置好免密。我们接下来想要将上面的项目拷贝到Linux服务器中使用。

将项目解压下来

由于项目的虚拟环境python解释器是windows版本的,所以我们只能用一下Linux上原本的python解释器。后面可以考虑,虚拟环境中如何替换成Linux版python解释器,解除对别处资源的依赖性。

这里用Linux自身的装的python2.7执行我们写的一个简单程序,去调用ansibe api,发现无法导入模块。既然它找不到,那么我们就在执行这个文件之前指定它还能去哪里找包

将项目的包目录追加到Linux安装的python2.7找包的列表中去。让这个解释器能找到我们项目的包。结果是找到的,但是没有inventory文件,那么我们就创建一个

查看源码我们发现,这个参数应该是inventory文件,下面其实还有一个参数,但是注释是对象。而我们需要传的是文件。

如下,我们成功获取到各个主机的信息。由于我们主机1没有对连接自身做免密,所以这里就不能访问执行。由此可知,这点和ansible软件还是一样的,都需要免密。而这里我们没有在Linux上安装ansible,用的只是可以使用的python解释器,这个解释器指定路径的方式让它能找到我们项目虚拟环境中的ansibe包路径、,如果便可以使用ansibe api去执行ansibe命令了。所以即使原系统环境中有yum安装的ansibe,不管是啥版本,和我们调用ansibe api是没有关系 的,。

ansible其他一些使用总结

命令执行结果按原样换行

执行命令获得的结果,不是单行字符串显示,而是让它像终端执行命令一样多行展示

api 调用,获取命令执行结果的指定行和列数据。比如通过vmstat获取cpu使用率

shell命令取好值

根据命令获取到指定数据,然后处理数据,100减去cpu空闲的再除以100,获得cpu使用率。

api 第二种方式获取CPU使用率(shell输出指定行和指定列获取)

# _*_ coding:utf-8 _*_
import sys
sys.path.append("/root/untitled6/Lib/site-packages")
import ansible.runner
runner=ansible.runner.Runner(module_name='shell',host_list="/root/hosts",module_args="vmstat",pattern='all',forks=10)
result=runner.run()
for host,ret in result['contacted'].items():
print '=================================',host
res=ret['stdout'].split('\n')
print res
print '#################'
for i in res:
for j in i.split():
print j,
print
shiyonglv=(100-int(res[-1].split()[-3]))/100
print "CPU使用率为: ",shiyonglv,'%' for host,ret in result['dark'].items():
print host
print ret['msg']

api将返回数据按行和列封装到对象或者字典中

如果我们需要多个返回的数据。我们可以将数据分别保存到对象中或者时字典中,分别需要定义类和字典

ansible api调用及二次封装详解的更多相关文章

  1. 利用 Java 操作 Jenkins API 实现对 Jenkins 的控制详解

    本文转载自利用 Java 操作 Jenkins API 实现对 Jenkins 的控制详解 导语 由于最近工作需要利用 Jenkins 远程 API 操作 Jenkins 来完成一些列操作,就抽空研究 ...

  2. vc中调用Com组件的方法详解

    vc中调用Com组件的方法详解 转载自:网络,来源未知,如有知晓者请告知我.需求:1.创建myCom.dll,该COM只有一个组件,两个接口:   IGetRes--方法Hello(),   IGet ...

  3. Java进阶(三十二) HttpClient使用详解

    Java进阶(三十二) HttpClient使用详解 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们 ...

  4. 转:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法、shiro认证与shiro授权

    原文地址:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法.shiro认证与shiro授权 以下是部分内容,具体见原文. shiro介绍 什么是shiro shiro是Apache ...

  5. php调用C代码的方法详解和zend_parse_parameters函数详解

    php调用C代码的方法详解 在php程序中需要用到C代码,应该是下面两种情况: 1 已有C代码,在php程序中想直接用 2 由于php的性能问题,需要用C来实现部分功能   针对第一种情况,最合适的方 ...

  6. 2017.2.9 深入浅出MyBatis技术原理与实践-第八章 MyBatis-Spring(二)-----配置文件详解

    深入浅出MyBatis技术原理与实践-第八章 MyBatis-Spring(二) ------配置文件详解 8.2 MyBatis-Spring应用 8.2.1 概述 本文主要讲述通过注解配置MyBa ...

  7. Azure Terraform(二)语法详解

    一,引言 上篇文章开始,我们简单介绍了以下通过基础设施管理工具----- Terraform,通过它来统一管理复杂的云基础设施资源.作为入门演示,使用Terraform 部署Azure 资源组的方式直 ...

  8. 18.Java 封装详解/多态详解/类对象转型详解

    封装概述 简述 封装是面向对象的三大特征之一. 封装优点 提高代码的安全性. 提高代码的复用性. "高内聚":封装细节,便于修改内部代码,提高可维护性. "低耦合&quo ...

  9. Python3调用C程序(超详解)

    Python3调用C程序(超详解) Python为什么要调用C? 1.要提高代码的运算速度,C比Python快50倍以上 2.对于C语言里很多传统类库,不想用Python重写,想对从内存到文件接口这样 ...

  10. Java面向对象之封装详解

    封装详解 封装 该露的露,该藏的藏 1.我们程序设计要追求"高内聚.低耦合".高内聚:类的内部数据操作细节自己完成,不允许外部干涉:低耦合:仅暴露少量的方法给外部使用. 封装(数据 ...

随机推荐

  1. Jetty的http3模块

    启用http3模块,执行如下命令: java -jar $JETTY_HOME/start.jar --add-modules=http3 命令的输出,如下: ALERT: There are ena ...

  2. 首届OpenHarmony竞赛训练营结营颁奖,75所高校学子助力建设开源生态

      由OpenAtom OpenHarmony(以下简称"OpenHarmony")项目群工作委员会和OpenHarmony项目群技术指导委员会主办的首届OpenHarmony竞赛 ...

  3. 强!推荐一款API 接口自动化测试平台!

    在项目开发,迭代交付过程中开发人员,测试人员需要针对系统微服务API做调试,回归测试,性能测试.自动化测试,一个好的平台本质上需要解决API测试的5大基本问题. 1.支持不同的项目,角色,技术人员多人 ...

  4. innoSetup打包文件编写模板

    现在打包主要是使用 innosetup 这个软件来进行打包,支持录制脚本和手动编写脚本,比较好用. 此文章主要记录手写脚本,便于后期查询,借鉴. 文档: inno setup :https://blo ...

  5. Kubernetes Pod配置:从基础到高级实战技巧

    本文深入探讨了Kubernetes Pod配置的实战技巧和常见易错点. 关注[TechLeadCloud],分享互联网架构.云服务技术的全维度知识.作者拥有10+年互联网服务架构.AI产品研发经验.团 ...

  6. centos8 \CentOS 9 Stream rpm 安装mysql8.0.28

    centos8 rpm 安装mysql8.0.28 检查 检测系统是否自带安装 MySQL 命令如下: rpm -qa | grep mysql 如果如下存在已安装的包,就需要卸载 mysql80-c ...

  7. linux 性能自我学习 ———— 关于内存 [七]

    前言 内存的基本知识,将在操作系统篇中详细介绍,这里只说明如何排查问题. 正文 内存的分配和回收: 在malloc 是c 标准库中的内存分配函数,对应到系统调用上,有两种实现方式,一种是brk()和 ...

  8. locust的 -T,--tags使用

    官网的TAG配置说明:-T [TAG [TAG ...]], --tags [TAG [TAG ...]]List of tags to include in the test, so only ta ...

  9. Java实现学生投票系统

    "感谢您阅读本篇博客!如果您觉得本文对您有所帮助或启发,请不吝点赞和分享给更多的朋友.您的支持是我持续创作的动力,也欢迎留言交流,让我们一起探讨技术,共同成长!谢谢!" 代码 im ...

  10. 力扣569(MySQL)-员工薪水中位数(困难)

    题目: 写一个SQL查询,找出每个公司的工资中位数,以任意顺序返回结果表.查询结果个数如下所示. 输出结果如下:  解题思路: 中位数:位于集合正中间的元素.当数据总书为奇数时,最中间的数就是中位数, ...