diff --git a/README.md b/README.md index e148731..d58faf1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ # module_lxc_container_info -Ansible module to get runtime informations from LXC containers \ No newline at end of file +Ansible module to get runtime informations from LXC containers + +## Testing Example + + % python3 ./lxc_container_info.py +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = r''' +--- +module: lxc_container_info +short_description: Gather info about LXC Containers +version_added: "0.1.0" +description: Gather some information about (all) LXC Containers +options: + name: + description: Name of Container to gather informations + required: false + type: str +requirements: + - 'lxc-python3' +author: + - Sven Velt +''' + +EXAMPLES = r''' +# Gather information of all containers: +- name: Gather LXC informations + lxc_container_info: + +# Gather information of one container: +- name: Gather LXC informations + lxc_container_info: + name: containername +''' + + +RETURN = r''' +# These are examples of possible return values, and in general should use other names for return values. +containers: + description: dict of container information + returned: always + type: complex + contains: + containername: + description: name of container + type: complex + contains: + all_interfaces: + description: List of all interfaces + type: str + returned: always + sample: '["lo", "eth0"]' + defined: + description: if container is defined + type: bool + returned: always + sample: true + exists: + description: if container is defined + type: bool + returned: always + sample: true + init_pid: + description: PID of init of container (if running) + type: init + sample: 1234 +original_message: + description: The original name param that was passed in. + type: str + returned: always + sample: 'hello world' +message: + description: The output message that the test module generates. + type: str + returned: always + sample: 'goodbye' +my_useful_info: + description: The dictionary containing information about your system. + type: dict + returned: always + sample: { + 'foo': 'bar', + 'answer': 42, + } +''' + +import ipaddress + +try: + import lxc +except ImportError: + HAS_LXC = False +else: + HAS_LXC = True + +from ansible.module_utils.basic import AnsibleModule + + +def run_module(): + module_args = dict( + name=dict(type='str', default=''), + ) + + result = dict( + changed=False, + containers={}, + ) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=True + ) + + if not HAS_LXC: + module.fail_json( + msg='The `lxc` module is not importable. Check the requirements.' + ) + + if module.params['name']: + ctnames = [ module.params['name'], ] + else: + ctnames = lxc.list_containers() + + for ctname in ctnames: + ct = lxc.Container(ctname) + + res_ct = {} + res_ct['defined'] = ct.defined + res_ct['exists'] = ct.defined + res_ct['state'] = ct.state + res_ct['running'] = ct.running + res_ct['init_pid'] = ct.init_pid + res_ct['all_interfaces'] = ct.get_interfaces() + + res_ifaces = {} + for iface in ct.get_interfaces(): + res_if = {} + res_if['ipv4_addresses'] = [] + res_if['ipv6_addresses'] = [] + for addr in ct.get_ips(iface): + try: + res_if['ipv4_addresses'].append(str(ipaddress.IPv4Address(addr))) + except ipaddress.AddressValueError: + try: + res_if['ipv6_addresses'].append(str(ipaddress.IPv6Address(addr))) + except: + pass + res_ifaces[iface] = res_if + res_ct['interfaces'] = res_ifaces + + res_stat = {} + if ct.running: + res_stat['mem'] = { + 'usage': int(ct.get_cgroup_item("memory.usage_in_bytes")), + 'max_usage': int(ct.get_cgroup_item("memory.max_usage_in_bytes")), + 'usage_mb': int(ct.get_cgroup_item("memory.usage_in_bytes")) // 1048576, + 'max_usage_mb': int(ct.get_cgroup_item("memory.max_usage_in_bytes")) // 1048576, + } + res_stat['kmem'] = { + 'usage': int(ct.get_cgroup_item("memory.kmem.usage_in_bytes")), + 'max_usage': int(ct.get_cgroup_item("memory.kmem.max_usage_in_bytes")), + 'usage_mb': int(ct.get_cgroup_item("memory.kmem.usage_in_bytes")) // 1048576, + 'max_usage_mb': int(ct.get_cgroup_item("memory.kmem.max_usage_in_bytes")) // 1048576, + } + res_ct['stats'] = res_stat + + result['containers'][ctname] = res_ct + + module.exit_json(**result) + + +def main(): + run_module() + + +if __name__ == '__main__': + main() diff --git a/module_test_args.json b/module_test_args.json new file mode 100644 index 0000000..4729d1d --- /dev/null +++ b/module_test_args.json @@ -0,0 +1,6 @@ +{ + "ANSIBLE_MODULE_ARGS": { + "name": "container_name" + } +} +