2014-11-17 12 views
9

Domanda semplice: Desidero eliminare alcuni file se l'utilizzo della partizione supera una determinata percentuale.Utilizzo di ansible per gestire lo spazio su disco

Ho accesso a "size_total" e "size_available" tramite "ansible_mounts". cioè .:

ansible myhost -m setup -a 'filter=ansible_mounts' 
myhost | success >> { 
"ansible_facts": { 
    "ansible_mounts": [ 
     { 
      "device": "/dev/mapper/RootVolGroup00-lv_root", 
      "fstype": "ext4", 
      "mount": "/", 
      "options": "rw", 
      "size_available": 5033046016, 
      "size_total": 8455118848 
     }, 

Come faccio ad accedere a quei valori, e come avrei eseguire azioni condizionale basati su di essi utilizzando Ansible?

risposta

12

risposta di Slava sicuramente era sulla strada giusta, qui è quello che ho usato:

- name: test for available disk space 
    assert: 
    that: 
     - not {{ item.mount == '/' and (item.size_available < item.size_total - (item.size_total|float * 0.8)) }} 
     - not {{ item.mount == '/var' and (item.size_available < item.size_total - (item.size_total|float * 0.8)) }} 
    with_items: ansible_mounts 
    ignore_errors: yes 
    register: disk_free 

- name: free disk space 
    command: "/some/command/that/fixes/it" 
    when: disk_free|failed 

Il compito assert test semplicemente per una condizione, impostando ignore_errors e registrando il risultato del test su una nuova variabile, possiamo eseguire un'attività condizionale più avanti nel gioco invece di fallire solo quando il risultato dell'asser fallisce.

Gli stessi test potrebbero probabilmente essere scritti in modo più efficiente, ma a costo di leggibilità. Quindi non ho usato un ciclo di lista multipla nell'esempio. In questo caso l'attività scorre su ogni elemento nell'elenco dei filesystem montati (un fatto creato ansible, chiamato ansible_mounts.)

Negando il test evitiamo errori su montaggi di file system non presenti nella nostra lista, quindi semplici gesti matematici il riposo. La parte che mi ha fatto inciampare era che le variabili size_available e size_total erano stringhe, quindi un filtro jinja le converte in un float prima di calcolare la percentuale.

+2

Aggiungi alcune spiegazioni del tuo codice. – Nilambar

+0

Quando ho provato questo, ho ricevuto questo errore: "L'errore era: 'oggetto unicode' non ha attributo 'mount'" – konrad

+0

La risposta al problema "no attribute" mount "è da usare: with_items: '{{ansible_mounts }} '... tuttavia, sembra che anche l'esempio si interrompa (almeno in Ans 2.2.1.0) quando si tenta di utilizzare il costrutto | failed in un elenco. .. Posso far funzionare le asserzioni, ma avendo problemi a far funzionare la parte | failed. – Cognitiaclaeves

2

non ho la prova, ma vi suggerisco di provare qualcosa di simile:

file: 
    dest: /path/to/big/file 
    state: absent 
    when: "{% for point in ansible_mounts %}{% if point.mount == '/' and point.size_available > (point.size_total/100 * 85) %}true{% endif %}{% endfor %}" == "true" 

In questo esempio, abbiamo iterare su punti di montaggio e trovare "/", dopo che calcoliamo è lì utilizzo va oltre 85 percentuali e stampa "true" se è vero. Successivamente, confrontiamo quella stringa e decidiamo se questo file debba essere cancellato.

Ispirato esempi tra i seguenti blog: https://blog.codecentric.de/en/2014/08/jinja2-better-ansible-playbooks-templates/

0

La mia soluzione

- name: cleanup logs, free disk space below 20% 
    sudo: yes 
    command: find /var -name "*.log" \(\(-size +50M -mtime +7 \) -o -mtime +30 \) -exec truncate {} --size 0 \; 
    when: "item.mount == '/var' and (item.size_available < item.size_total * 0.2)" 
    with_items: ansible_mounts 

Questa troncherà qualsiasi file *.log sul volume /var che sono o più vecchi di 7 giorni e superiore a 50M o più vecchi di 30 giorni se lo spazio libero su disco scende al di sotto del 20%.

3

Nel mio caso, tutto quello che mi interessa è la partizione di root. Ma ho trovato quando ho usato l'esempio di frameloss sopra, che avevo bisogno di una condizione "o" negata, perché ogni punto di mount verrà testato rispetto all'asserzione. Se esisteva più di un punto di montaggio, significava che l'asserzione avrebbe sempre fallito. Nel mio esempio, sto verificando se size_available è meno del 50% di size_total direttamente, piuttosto che calcolarlo come ha fatto frameloss.

In secondo luogo, almeno nella versione di ansible che ho usato, era necessario includere il {{}} attorno alla variabile in with_items. Un errore che ho fatto che non era nell'esempio sopra non stava allineando la clausola 'when' alla stessa indentazione della direttiva 'fail'. (Se viene commesso questo errore, la soluzione non funziona ...)

# This works with ansible 2.2.1.0 
- hosts: api-endpoints 
    become: True 
    tasks: 

    - name: Test disk space available 
     assert: 
     that: 
      - item.mount != '/' or {{ item.mount == '/' and item.size_available > (item.size_total|float * 0.4) }} 
     with_items: '{{ ansible_mounts }}' 
     ignore_errors: yes 
     register: disk_free 

    - name: Fail when disk space needs attention 
     fail: 
     msg: 'Disk space needs attention.' 
     when: disk_free|failed 
Problemi correlati