Affichage des articles dont le libellé est lvm. Afficher tous les articles
Affichage des articles dont le libellé est lvm. Afficher tous les articles

jeudi 9 octobre 2014

Comparaison de la gestion des FS avec Puppet et Ansible

Suite de mes aventures avec Ansible : aujourd'hui c'est du système Linux.

Les données du problème : je veux pouvoir gérer le LVM Linux et retailler mes FS à la demande.

La recette sous Puppet

Sous Puppet, en utilisant un fichier yaml/Hiera, l'écriture de tout ceci se ferait avec quelque chose de ce genre :

---
classes: ['lvm']

lvm::volume_groups:
  rootvg:
    physical_volumes:
      - /dev/sda2
    logical_volumes:
      tmp:
        size: 2G
        mountpath: /tmp
  datavg:
    physical_volumes:
      - /dev/sdb
    logical_volumes:
      test:
        size: 128
        mountpath: /test

Ne pas oublier non plus d'inclure le code suivant dans le fichier site.pp :

hiera_include('classes','')

Bien penser également à installer le module lvm, sinon ça ne marchera pas (puppetlabs-lvm).

Bon, sous Ansible, toutes ces belles choses n'existent pas (encore) en l'état mais sous forme de brique à assembler. On va voir comment recréer un mécanisme à peu près similaire.

La recette sous Ansible

Je me place dans le cadre d'un playbook Ansible avec un fichier system.yml se trouvant dans un répertoire de travail ~/ansible avec le contenu suivant :

---
# Playbook de gestion du système

- name: Propriétés communes système
  hosts: all
  remote_user: root

  roles:
    - system

Autre fichier présent : group_vars/all avec le contenu suivant :

---
# Variable applicable à tous

vgs:
  rootvg: "/dev/sda2"
  datavg: "/dev/sdb"

lvs:
  test:
    vg: rootvg
    mountpoint: /test
    size: 256

Ce fichier sera a spécialiser par groupe de machine mais est l'équivalent de notre fichier yaml/Hiera. Reste maintenant à écrire notre liste de tâche qui nous permettra de gérer ces FS (qu'on mettra dans le fichier roles/system/tasks/main.yml) :

---
- name: VG/PV Configuration
  lvg: vg={{ item.key }} pvs={{ item.value }} state=present
  with_dict: vgs

- name: LV creation
  lvol: vg={{ item.value.vg }} lv={{item.key}} size={{item.value.size}}
  register: task
  with_dict: lvs

- name: LV format
  filesystem: fstype=ext4 dev=/dev/mapper/{{item.value.vg}}-{{item.key}}
  with_dict: lvs

- name: Mount
  mount: name={{item.value.mountpoint}} src=/dev/mapper/{{item.value.vg}}-{{item.key}} dump=1 passno=2 fstype=ext4 state=mounted
  when: item.value.has_key('mountpoint')
  with_dict: lvs

- name: FS resize
  command: resize2fs /dev/mapper/{{item.item.value.vg}}-{{item.item.key}}
  with_items: task.results
  when: item.changed == True

NB : cette recette ne gère que des fs de type ext4. Si vous voulez gérer du xfs/btrfs/fegafatfs, il faudra changer la commande resize2fs par autre chose.

Le fonctionnement de la recette est assez simple : on enchaine les opérations (création du PV/VG, création du LV, formatage et montage) et on exécute la commande resize2fs qu'en cas de changement sur le LV (cf FS resize, ligne when: item.changed == True).

Reste maintenant à lancer notre playbook avec la commande ansible-playbook -i ./hosts ./system.yml. Vous devriez obtenir le résultat suivant :

PLAY [Propriétés communes système] ******************************

GATHERING FACTS *************************************************
ok: [machine1]

TASK: [common | VG/PV Configuration] ****************************
ok: [machine1] => (item={'key': 'datavg', 'value': '/dev/sdb'})
ok: [machine1] => (item={'key': 'rootvg', 'value': '/dev/sda2'})

TASK: [common | LV creation] ************************************
changed: [machine1] => (item={'key': 'test', 'value': ...})

TASK: [common | LV format] **************************************
changed: [machine1] => (item={'key': 'test', 'value': ...})

TASK: [common | Mount] ******************************************
changed: [machine1] => (item={'key': 'test', 'value': ...})

TASK: [common | FS resize] **************************************
changed: [machine1] => (item={u'msg': u'', 'item': ...})

PLAY RECAP ******************************************************
machine1        : ok=6    changed=4    unreachable=0    failed=0   

Changeons la taille de notre FS pour autre chose et relançons ansible pour vérifier la bonne prise en compte de tout ceci :

PLAY [Propriétés communes système] ******************************

GATHERING FACTS *************************************************
ok: [machine1]

[...]

TASK: [common | LV creation] ************************************
changed: [machine1] => (item={'key': 'test', 'value': ...})

[...]

TASK: [common | FS resize] **************************************
changed: [machine1] => (item={u'msg': u'', 'item': ...})

PLAY RECAP ******************************************************
machine1        : ok=6    changed=2    unreachable=0    failed=0   

Tout c'est bien passé. Il ne me reste plus qu'à vous souhaiter une bonne gestion de vos LV !

lundi 22 juillet 2013

Utilisation de Puppet sous AIX pour la gestion des logicals volumes

Depuis quelques temps, j'ai découvert un nouveau sujet d'amusement : Puppet. Le produit est particulièrement intéressant et j'ai commencé à travailler sur un POC impliquant des agents pour différents OS (AIX, Linux et bien sûr Windows).

C'est à cette occasion que j'ai découvert l'existence de Puppet Forge et notamment l'excellente extension permettant de gérer les volumes groupes de Linux (extension lvm). Suite à ça j'ai voulu disposer de la même chose pour AIX. Au début, j'ai voulu implémenter ça directement dans le module lvm mais devant le travail que ça représentait, j'ai préféré faire quelque chose de spécifique mais surtout de plus simple. Je verrai plus tard pour faire ça comme il faut :)

Cette classe s'utilise sous la forme de module. Il vous faut donc créer un répertoire /etc/puppet/modules/aix avec un sous répertoire manifests:
mkdir -p /etc/puppet/modules/aix/manifests
Créer ensuite le fichier aix/manifests/logical_volume.pp avec le contenu suivant :

# Handle AIX LVM
define aix::logical_volume(
  $mount_point,
  $ensure = "present",
  $vg = "rootvg",
  $size = "",
  $lv_options = "",
  $fs_options = ""
) {

  $lv_name = $title
  $fs_type = "jfs2"

  case $ensure {
    # Clean up the whole chain.
    cleaned: {
        mount { $mount_point: ensure => "unmounted",
                atboot=> false, device => "/dev/$lv_name" } ->
        exec {"/usr/sbin/rmfs /dev/$lv_name ":
            onlyif => "/bin/test -n \"`/usr/sbin/lsfs $mount_point 2> /dev/null`\"",
        }
    }
    # Create the whole FS
    /^(present|created)$/: {
        # Creation du FS avec un nombre de block = 1
        exec {"/usr/sbin/mklv -t$fs_type -y $lv_name $options $vg 1":
            onlyif => "/bin/test ! -b /dev/$lv_name"
        } ->
        exec {"/usr/sbin/crfs -v$fs_type -d $lv_name -m $mount_point $options -A yes -a logname='INLINE'":
            onlyif => "/bin/test -z \"`/usr/sbin/lsfs $mount_point 2> /dev/null`\"",
        } ->
        mount { $mount_point: ensure => "mounted", atboot=> true, device => "/dev/$lv_name" }
        case $size {
            /^(\d+)([KMGT])$/: {
                $size_hash = { "K" => 1, "M" => 1024, "G" => 1048576, "T" => 1073741824 }
                $kilo_size = $1 * $size_hash[$2]
                $block_size = $kilo_size * 2
                exec {"/usr/sbin/chfs -a size=$size $mount_point":
                    onlyif => "/bin/test ! \"`/usr/sbin/lsfs $mount_point | /usr/bin/awk '/$lv_name/ { print \$5 }'`\" = \"$block_size\"",
                    require => Mount[$mount_point]
                }
            }
            /^\s*$/: { }
            default: {
                fail ( 'size is not valid (eg: 1G, 256M, 1T etc.)' )
            }
        }
    }
    default: {
        fail ( 'aix::logical_volume: ensure parameter can only be set to cleaned or present/created' )
    }
  }
}
De là, vous pourrez l'utiliser sous cette forme dans une déclaration de noeud :
node 'machineaix' {
  aix::logical_volume { "test":
      mount_point => "/test",
      size => "1G"
  }
}

Cette merveille a été testé avec succès sous AIX 7.1 et devrait fonctionner sans problème sous AIX 5.3 et 6.1.