In [1]:
cd ansible
/notebooks/notebooks/ansible
In [2]:
cat inventory
#
# This inventory file contains a list of server to
# play with - divided in groups.
#
[course]
# this is the local machine where you run jupyter
# the tutorial just works with this one.
pythonforsysadmin_course_1 ansible_connection=local
# Another group of servers
# where we can pass optional arguments
# Homework: you can play with this group of host
# once you exchange ssh-keys between the pythonforsysadmin_course_1
# container and the pythonforsysadmin_ansible_* ones._
[ansible]
172.17.0.[5:7]
Now check if you can ping the local host.
In [14]:
# Check connections versus the local host in the "course" group
!ansible -i inventory course -msetup
pythonforsysadmin_course_1 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"172.17.0.3"
],
"ansible_all_ipv6_addresses": [
"fe80::42:acff:fe11:3"
],
"ansible_architecture": "x86_64",
"ansible_bios_date": "06/30/2014",
"ansible_bios_version": "A00",
"ansible_cmdline": {
"BOOT_IMAGE": "/vmlinuz-4.9.17-100.fc24.x86_64",
"LANG": "it_IT.UTF-8",
"i8042.nopnp": true,
"rd.lvm.lv": "vg0/root00",
"ro": true,
"root": "/dev/mapper/vg0-root00"
},
"ansible_date_time": {
"date": "2017-04-05",
"day": "05",
"epoch": "1491399416",
"hour": "13",
"iso8601": "2017-04-05T13:36:56Z",
"iso8601_basic": "20170405T133656277588",
"iso8601_basic_short": "20170405T133656",
"iso8601_micro": "2017-04-05T13:36:56.277679Z",
"minute": "36",
"month": "04",
"second": "56",
"time": "13:36:56",
"tz": "UTC",
"tz_offset": "+0000",
"weekday": "Wednesday",
"weekday_number": "3",
"weeknumber": "14",
"year": "2017"
},
"ansible_default_ipv4": {
"address": "172.17.0.3",
"alias": "eth0",
"broadcast": "global",
"gateway": "172.17.0.1",
"interface": "eth0",
"macaddress": "02:42:ac:11:00:03",
"mtu": 1500,
"netmask": "255.255.0.0",
"network": "172.17.0.0",
"type": "ether"
},
"ansible_default_ipv6": {},
"ansible_devices": {
"sda": {
"holders": [],
"host": "",
"model": "ST500LM000-1EJ16",
"partitions": {
"sda1": {
"sectors": "1024000",
"sectorsize": 512,
"size": "500.00 MB",
"start": "2048"
},
"sda2": {
"sectors": "81920",
"sectorsize": 512,
"size": "40.00 MB",
"start": "1026048"
},
"sda3": {
"sectors": "262144",
"sectorsize": 512,
"size": "128.00 MB",
"start": "1107968"
},
"sda4": {
"sectors": "1536000",
"sectorsize": 512,
"size": "750.00 MB",
"start": "1370112"
},
"sda5": {
"sectors": "819200",
"sectorsize": 512,
"size": "400.00 MB",
"start": "2906112"
},
"sda6": {
"sectors": "14827568",
"sectorsize": 512,
"size": "7.07 GB",
"start": "961943552"
},
"sda7": {
"sectors": "1048576",
"sectorsize": 512,
"size": "512.00 MB",
"start": "3725312"
},
"sda8": {
"sectors": "897589248",
"sectorsize": 512,
"size": "428.00 GB",
"start": "4773888"
},
"sda9": {
"sectors": "8388608",
"sectorsize": 512,
"size": "4.00 GB",
"start": "902363136"
}
},
"removable": "0",
"rotational": "1",
"sas_address": null,
"sas_device_handle": null,
"scheduler_mode": "cfq",
"sectors": "976773168",
"sectorsize": "512",
"size": "465.76 GB",
"support_discard": "0",
"vendor": "ATA"
}
},
"ansible_distribution": "Debian",
"ansible_distribution_major_version": "8",
"ansible_distribution_release": "jessie",
"ansible_distribution_version": "8.5",
"ansible_dns": {
"nameservers": [
"10.0.11.254",
"#",
"removeme-babel-dns",
"10.0.11.254",
"#",
"removeme-babel-dns",
"10.0.11.254",
"#",
"removeme-babel-dns",
"10.0.11.254",
"10.0.252.5"
],
"search": [
"babel.it"
]
},
"ansible_domain": "",
"ansible_env": {
"CLICOLOR": "1",
"GIT_PAGER": "cat",
"GPG_KEY": "C01E1CAD5EA2C4F0B8E3571504C367C218ADD4FF",
"HOME": "/root",
"HOSTNAME": "7ddd5bc0dd90",
"JPY_PARENT_PID": "6",
"LANG": "C.UTF-8",
"LC_ALL": "C.UTF-8",
"LC_MESSAGES": "C.UTF-8",
"PAGER": "cat",
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"PWD": "/notebooks/notebooks/ansible",
"PYTHONPATH": "",
"PYTHON_PIP_VERSION": "8.1.2",
"PYTHON_VERSION": "2.7.12",
"TERM": "xterm-color"
},
"ansible_eth0": {
"active": true,
"device": "eth0",
"ipv4": {
"address": "172.17.0.3",
"broadcast": "global",
"netmask": "255.255.0.0",
"network": "172.17.0.0"
},
"ipv6": [
{
"address": "fe80::42:acff:fe11:3",
"prefix": "64",
"scope": "link"
}
],
"macaddress": "02:42:ac:11:00:03",
"mtu": 1500,
"promisc": false,
"type": "ether"
},
"ansible_fips": false,
"ansible_form_factor": "Portable",
"ansible_fqdn": "7ddd5bc0dd90",
"ansible_gather_subset": [
"hardware",
"network",
"virtual"
],
"ansible_hostname": "7ddd5bc0dd90",
"ansible_interfaces": [
"lo",
"eth0"
],
"ansible_kernel": "4.9.17-100.fc24.x86_64",
"ansible_lo": {
"active": true,
"device": "lo",
"ipv4": {
"address": "127.0.0.1",
"broadcast": "host",
"netmask": "255.0.0.0",
"network": "127.0.0.0"
},
"ipv6": [
{
"address": "::1",
"prefix": "128",
"scope": "host"
}
],
"mtu": 65536,
"promisc": false,
"type": "loopback"
},
"ansible_machine": "x86_64",
"ansible_machine_id": "748cfc5d0ac0444e85d1cccb08411403",
"ansible_memfree_mb": 706,
"ansible_memory_mb": {
"nocache": {
"free": 3707,
"used": 4200
},
"real": {
"free": 706,
"total": 7907,
"used": 7201
},
"swap": {
"cached": 0,
"free": 4095,
"total": 4095,
"used": 0
}
},
"ansible_memtotal_mb": 7907,
"ansible_mounts": [
{
"device": "/dev/mapper/docker-253:2-537280731-c85cb1165b8c710d56b97bfa1bbd902f1dc2eed671a883f570d48a8ab23dc822",
"fstype": "xfs",
"mount": "/",
"options": "rw,context=\"system_u:object_r:svirt_sandbox_file_t:s0:c567,c688\",relatime,nouuid,attr2,inode64,logbsize=64k,sunit=128,swidth=128,noquota",
"size_available": 105882546176,
"size_total": 107320705024,
"uuid": "NA"
},
{
"device": "/dev/mapper/vg0-home",
"fstype": "xfs",
"mount": "/notebooks",
"options": "rw,seclabel,relatime,attr2,inode64,noquota",
"size_available": 21948248064,
"size_total": 214643507200,
"uuid": "NA"
},
{
"device": "/dev/mapper/vg0-data",
"fstype": "xfs",
"mount": "/etc/resolv.conf",
"options": "rw,seclabel,relatime,attr2,inode64,noquota",
"size_available": 4040863744,
"size_total": 214643507200,
"uuid": "NA"
},
{
"device": "/dev/mapper/vg0-data",
"fstype": "xfs",
"mount": "/etc/hostname",
"options": "rw,seclabel,relatime,attr2,inode64,noquota",
"size_available": 4040863744,
"size_total": 214643507200,
"uuid": "NA"
},
{
"device": "/dev/mapper/vg0-data",
"fstype": "xfs",
"mount": "/etc/hosts",
"options": "rw,seclabel,relatime,attr2,inode64,noquota",
"size_available": 4040863744,
"size_total": 214643507200,
"uuid": "NA"
}
],
"ansible_nodename": "7ddd5bc0dd90",
"ansible_os_family": "Debian",
"ansible_pkg_mgr": "apt",
"ansible_processor": [
"GenuineIntel",
"Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz",
"GenuineIntel",
"Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz",
"GenuineIntel",
"Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz",
"GenuineIntel",
"Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz"
],
"ansible_processor_cores": 2,
"ansible_processor_count": 1,
"ansible_processor_threads_per_core": 2,
"ansible_processor_vcpus": 4,
"ansible_product_name": "Inspiron 7347",
"ansible_product_serial": "54CK432",
"ansible_product_uuid": "4C4C4544-0034-4310-804B-B5C04F343332",
"ansible_product_version": "00h",
"ansible_python": {
"executable": "/usr/bin/python",
"has_sslcontext": true,
"type": "CPython",
"version": {
"major": 2,
"micro": 9,
"minor": 7,
"releaselevel": "final",
"serial": 0
},
"version_info": [
2,
7,
9,
"final",
0
]
},
"ansible_python_version": "2.7.9",
"ansible_selinux": false,
"ansible_service_mgr": "upstart",
"ansible_swapfree_mb": 4095,
"ansible_swaptotal_mb": 4095,
"ansible_system": "Linux",
"ansible_system_capabilities": [
"cap_chown",
"cap_dac_override",
"cap_fowner",
"cap_fsetid",
"cap_kill",
"cap_setgid",
"cap_setuid",
"cap_setpcap",
"cap_net_bind_service",
"cap_net_raw",
"cap_sys_chroot",
"cap_mknod",
"cap_audit_write",
"cap_setfcap+eip"
],
"ansible_system_capabilities_enforced": "True",
"ansible_system_vendor": "Dell Inc.",
"ansible_uptime_seconds": 12220,
"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": "docker",
"module_setup": true
},
"changed": false
}
In [4]:
# Pinging all hosts gives some errors too, due to missing hosts or no ssh-key exchange
!ansible -i inventory -m ping all
pythonforsysadmin_course_1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.17.0.5 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh.",
"unreachable": true
}
172.17.0.6 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh.",
"unreachable": true
}
172.17.0.7 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh.",
"unreachable": true
}
You can split your servers in many inventory files, like
# staging inventory file
# run with
# ansible -i staging ...
[ws]
staging-ws-[0:3]
[jboss]
staging-boss-[0:6]
# production inventory file
# run with
# ansible -i production ...
[ws]
ws-[0:3]
[jboss]
boss-[0:6]
To run a group of tasks with ansible, just:
A playbook is a list of tasks in yml format, something like
#
# playbook.yml
#
- name: All public traffic is redirected via https
uri:
url: http://{{server_host}}/
validate_certs: false
follow_redirects: none
status_code: 301
- name: This webapp is served
uri:
url: https://{{server_host}}/webapp-1
validate_certs: false
status_code: 200
HEADER_testflag: test
- name: The WS is serverd and requires authentication
uri:
url: https://{{server_host}}/rest/v1/method
validate_certs: false
status_code: 401
In this case, instead of making actual installation|setup tasks, we just created a testsuite validating our deployment. Now we must write another playbook which takes care of deployng the actual machine.
In [12]:
!cat python-course-test.yml
# Run this with
#
# #ansible-playbook -i inventory python-course-test.yml
#
- hosts: course
tasks:
- name: The /notebooks directory should exist
file: path="/notebooks" state=directory
- name: jupyter is responding on 8888
uri:
url: http://0.0.0.0:8888/notebooks
validate_certs: false
status_code: 200 # modify this line to simulate an error and see the outcome!
- name: The template.conf is in place
file: path="/tmp/template.conf" state=file
In [19]:
!ansible-playbook -i inventory python-course-test.yml
PLAY [course] ******************************************************************
TASK [setup] *******************************************************************
ok: [pythonforsysadmin_course_1]
TASK [The /notebooks directory should exist] ***********************************
ok: [pythonforsysadmin_course_1]
TASK [jupyter is responding on 8888] *******************************************
ok: [pythonforsysadmin_course_1]
TASK [The template.conf is in place] *******************************************
ok: [pythonforsysadmin_course_1]
PLAY RECAP *********************************************************************
pythonforsysadmin_course_1 : ok=4 changed=0 unreachable=0 failed=0
As you can see something is missing: this playbook is not going to modify our machine but only test that everything is in place.
See ansible-playbook --check
and --diff
for further infos.
We can run a setup playbook, conventionally named site.yml.
In [15]:
!cat site.yml
# Run this with
#
# #ansible-playbook -i inventory site.yml
#
- hosts: course
tasks:
- name: Create a file from a template
template: src=mytemplate.j2 dest=/tmp/template.conf
- name: Ensure needed packages are present and eventually install them
apt: name={{item}} state=present
with_items:
- python
- python-dev
# ignore_errors: yes # ignore errors during the course (eg. connectivity)
In [20]:
!ansible-playbook -i inventory site.yml --diff --limit=course # in this case the --limit does not change anything ;)
PLAY [course] ******************************************************************
TASK [setup] *******************************************************************
ok: [pythonforsysadmin_course_1]
TASK [Create a file from a template] *******************************************
ok: [pythonforsysadmin_course_1]
TASK [Ensure needed packages are present and eventually install them] **********
ok: [pythonforsysadmin_course_1] => (item=[u'python', u'python-dev'])
PLAY RECAP *********************************************************************
pythonforsysadmin_course_1 : ok=3 changed=0 unreachable=0 failed=0
In [23]:
!cat mytemplate.j2
#
# A simple templated file for ansible.
# See the documentation to use this flexible
# jinja template.
GW=10.0.0.254 # a static line
HOSTNAME={{ansible_hostname}} # a dynamic one
Content source: ioggstream/python-course
Similar notebooks: