Oracle ACFS hors Cluster

Introduction

ACFS (ASM Cluster File System) est arrivé avec le Grid Infrastructure (GI) 11.2.

On peut le résumer en le décrivant comme le successeur d’OCFS2 (Oracle Cluster File System 2) et DBFS (DataBase File System), et intégrant des fonctionnalités habituellement disponibles sur NFS (Network File System) telle la gestion de Snapshot.

Comme son nom l’indique, ACFS n’est logiquement disponible qu’en mode Cluster, mais les modules ACFS et ADVM (ASM Dynamic Volume Manager) sont bel et bien présents en mode Restart (GI non-Cluster).
Il est donc tout à fait possible d’exploiter ACFS dans des environnements non Cluster, mais l’intégration n’y est pas faite dans l’outillage Restart : pas de crsctl/srvctl pour le contrôler, pas de chargement automatique des modules kernel, donc impossibilité d’utiliser « fstab » pour monter les volumes ACFS au démarrage de l’OS.

Le but de cet article n’est pas de proposer une solution à un manque de fonctionnalité de Restart, vu que clairement un Cluster File System est fait pour fonctionner dans un Cluster.
D’ailleurs la méthode la plus simple pour en disposer sur un serveur Standalone est de faire une installation de type Cluster, mais mono-nœud.
Donc le but de cet article est en fait détourné : se familiariser avec la gestion des ressources par le GI et sa déclinaison « Restart ».

Nous allons créer 3 ressources qui seront gérées par Restart à la mode Cluster :

  • Ressource de contrôle des modules ADVM/ACFS
  • Ressource de contrôle des volumes ASM
  • Ressource de contrôle des points de montage ACFS

Puis nous créerons un volume ACFS qui sera géré par nos ressources.

 

1. Autoriser le user « oracle » à charger les modules ADVM/ACFS et à monter un volume

En root :

cat <<EOF >> /etc/sudoers
%oinstall ALL = (ALL) NOPASSWD: ${ORACLE_HOME}/bin/acfsload, /bin/mount
EOF

 

2. Création du script de contrôle des modules ADVM/ACFS et de sa ressource

En root :

cat <<EOF > /usr/local/bin/cust_drivers_acfs.sh
#!/bin/bash
#set -x
RC=1
DIR=\$(dirname \${0})
FILE=\$(basename \${0})
case \${1} in
 "start")
  sudo \${ORACLE_HOME}/bin/acfsload start -s
  RC=\${?}
  ;;
 "stop")
  RC=0
  let cnt=0
  while [ \${RC} -eq 0 ] && [ \${cnt} -le 10 ] ; do
   let cnt=cnt+1
   sudo \${ORACLE_HOME}/bin/acfsload stop -s
   sleep 5
   \${0} check
  done
  RC=0
  ;;
 "clean"|"abort")
  RC=0
  ;;
 "check")
  ls -a /dev/asm/|grep ".asm" > /dev/null
  RC=\${?}
  ;;
 *)
  echo "Usage : \$FILE {start|stop|check|clean|abort}"
  RC=1
  ;;
esac
exit \${RC}
EOF

chmod +x /usr/local/bin/cust_drivers_acfs.sh

crsctl add res cust.drivers.acfs -type local_resource -attr "ACTION_SCRIPT=/usr/local/bin/cust_drivers_acfs.sh,ACTION_TIMEOUT=60,CHECK_INTERVAL=60,ACL='owner:oracle:rwx,pgrp:root:r-x,other::r--'"
  • Ce script est un CallOut qui sera fourni à Restart pour contrôler le chargement / déchargement des modules ADVM/ACFS
  • Restart l’exécutera avec pour seul argument l’action à réaliser, à savoir :
    • start : chargement des modules
    • stop : déchargement des modules
    • clean : inutilisé ici, mais sert normalement à rendre un système propre en cas d’échec (Ex. : suppression de fichiers de type « pid »)
    • abort : inutilisé ici, mais sert normalement à interrompre une action en court de « start »
    • check : retourne l’état de la ressource, ici 0 si les modules sont bien chargés, sinon 1
  • Création de la ressource « cust.volumes.acfs » associée au script CallOut, avec les attributs suivants :
    • Arrêt de l’exécution du script après 60 secondes sans réponse
    • Exécution du « check » toutes les 60 secondes
    • Compte d’exécution du script : « oracle », Groupe ayant les droits d’exécution : « root », les autres ne les ayant pas

 

3. Création du script de contrôle des volumes ASM

En root :

cat <<EOF > /usr/local/bin/cust_volumes_acfs.sh
#!/bin/bash
#set -x
RC=1
export ORACLE_SID=\$(ps -eo cmd|grep -v grep|grep pmon|awk -F'_' '{print \$3}')
DIR=\$(dirname \${0})
FILE=\$(basename \${0})
case \${1} in
 "start")
  \${ORACLE_HOME}/bin/asmcmd volenable –all
  RC=\${?}
  ;;
 "stop")
  \${ORACLE_HOME}/bin/asmcmd voldisable –all
  RC=0
  ;;
 "clean"|"abort")
  RC=0
  ;;
 "check")
  nb=\$(ls /dev/asm|wc -w)
  if [ \$nb -eq 0 ] ; then
   RC=1
  else
   RC=0
  fi
  ;;
 *)
  echo "Usage : \$FILE {start|stop|check|clean|abort}"
  RC=1
 ;;
esac
exit \${RC}
EOF

chmod +x /usr/local/bin/cust_volumes_acfs.sh

crsctl add res cust.volumes.acfs -type local_resource -attr "ACTION_SCRIPT=/usr/local/bin/cust_volumes_acfs.sh,ACTION_TIMEOUT=60,CHECK_INTERVAL=60,START_DEPENDENCIES='pullup:always(ora.asm,cust.drivers.acfs) hard(ora.asm,cust.drivers.acfs)',STOP_DEPENDENCIES='hard(intermediate:ora.asm,intermediate:cust.drivers.acfs)',ACL='owner:oracle:rwx,pgrp:asmdba:r-x,other::r--'"
  • Ce script est un CallOut qui sera fourni à Restart pour contrôler l’activation / désactivation des volumes ASM
  • Restart l’exécutera avec pour seul argument l’action à réaliser, à savoir :
    • start : activation de tous les volumes ASM
    • stop : désactivation de tous les volumes ASM
    • clean : inutilisé ici, mais sert normalement à rendre un système propre en cas d’échec (Ex. : suppression de fichiers de type « pid »)
    • abort : inutilisé ici, mais sert normalement à interrompre une action en court de « start »
    • check : retourne l’état de la ressource, ici 0 si au moins un volume est actif, sinon 1
  • Création de la ressource « cust.volumes.acfs » associé au script CallOut, avec les attributs suivants :
    • Arrêt de l’exécution du script après 60 secondes sans réponse
    • Exécution du « check » toutes les 60 secondes
    • Ne peut démarrer qu’après les ressources « ora.asm » (l’instance ASM) et « cust.drivers.acfs » (le chargement des modules ADVM/ACFS), et lance leur démarrage le cas échéant
    • Ne peut s’arrêter qu’après les ressources « ora.asm » et « cust.drivers.acfs »
    • Compte d’exécution du script : « oracle », Groupe ayant les droits d’exécution : «asmdba», les autres ne les ayant pas

 

4. Création du script de contrôle des volumes ASM

En root :

cat <<EOF > /usr/local/bin/cust_mount_acfs.sh
#!/bin/bash
#set -x
RC=1
export ORACLE_SID=\$(ps -eo cmd|grep -v grep|grep pmon|awk -F'_' '{print \$3}')
DIR=\$(dirname \${0})
FILE=\$(basename \${0})

case \${1} in
 "start")
  \${ORACLE_HOME}/bin/asmcmd volinfo --all | egrep "Mountpath|Volume Device" | while read line ; do
   val=\$(echo \$line | awk -F': ' '{print \$2}')
   if [ "\$device" == "" ] ; then
    device=\$val
   else
    path=\$val
    if [ "\$path" != "" ] ; then
     /bin/mount -t acfs \$device \$path
    fi
    device=""
   fi
  done
  RC=\${?}
  ;;
 "stop")
  \${ORACLE_HOME}/bin/asmcmd volinfo --all | egrep "Mountpath|Volume Device" | while read line ; do
   val=\$(echo \$line | awk -F': ' '{print \$2}')
   if [ "\$device" == "" ] ; then
    device=\$val
   else
    path=\$val
    if [ "\$path" != "" ] ; then
     /bin/umount -f \$path
    fi
    device=""
   fi
  done
  RC=\${?}
  ;;
 "clean"|"abort")
  RC=0
  ;;
 "check")
  mount | grep acfs
  ;;
 *)
  echo "Usage : \$FILE {start|stop|check|clean|abort}"
  RC=1
 ;;
esac
exit \${RC}
EOF

chmod +x /usr/local/bin/cust_mount_acfs.sh

crsctl add res cust.mount.acfs -type local_resource -attr "ACTION_SCRIPT=/usr/local/bin/cust_mount_acfs.sh,ACTION_TIMEOUT=60,CHECK_INTERVAL=60,START_DEPENDENCIES='pullup:always(cust.volumes.acfs) hard(cust.volumes.acfs)',STOP_DEPENDENCIES='hard(intermediate:intermediate:cust.volumes.acfs)',ACL='owner:oracle:rwx,pgrp:asmdba:r-x,other::r--'"
  • Ce script est un CallOut qui sera fourni à Restart pour contrôler le montage / démontage des ACFS
  • Restart l’exécutera avec pour seul argument l’action à réaliser, à savoir :
    • start : montage de tous les ACFS
    • stop : démontage de tous les ACFS
    • clean : inutilisé ici, mais sert normalement à rendre un système propre en cas d’échec (Ex. : suppression de fichiers de type « pid »)
    • abort : inutilisé ici, mais sert normalement à interrompre une action en court de « start »
    • check : retourne l’état de la ressource, ici 0 si au moins un ACFS est monté, sinon 1
  • Création de la ressource « cust.mount.acfs » associé au script CallOut, avec les attributs suivants :
    • Arrêt de l’exécution du script après 60 secondes sans réponse
    • Exécution du « check » toutes les 60 secondes
    • Ne peut démarrer qu’après la ressource « cust.volumes.acfs » (l’activation des volumes ASM), et lance son démarrage le cas échéant
    • Ne peut s’arrêter qu’après la ressource « cust.volumes.acfs »
    • Compte d’exécution du script : « oracle », Groupe ayant les droits d’exécution : «asmdba», les autres ne les ayant pas

 

5. Création d’un volume ASM

En oracle :

crsctl start res cust.drivers.acfs
asmcmd volcreate -G DATA -s 1G v_test1
asmcmd volinfo -G DATA v_test1
  Diskgroup Name: DATA
  Volume NAME: V_TEST1
  …
  Mountpath:

En root :

mkfs -t acfs /dev/asm/v_test1*
mkdir /media/test1
mount /dev/asm/v_test* /media/test1
umount /media/test1
asmcmd volinfo -G DATA v_test1
  Diskgroup Name: DATA
  Volume NAME: V_TEST1
  …
  Mountpath: /media/test1

En root ou oracle :

crsctl start res cust.mount.acfs
  • On commence par charger les modules ADVM/ACFS, étape obligatoire pour pouvoir créer un volume ASM
  • On crée un volume ASM de 1Go, nommé « V_TEST1 ». Comme il vient d’être créé, « volinfo » ne rapporte aucun point de montage associé
  • On formate au format ACFS le volume qui apparaît dans « /dev/asm ». A noter que depuis la version 12c du GI/Restart, il est possible de formater un volume ASM dans un format non-Cluster (EXT4…)
  • On crée le répertoire de point de montage, on monte puis démonte le volume « V-TEST1 » et on voit que sont attribut de point de montage indique le répertoire utilisé
  • Dorénavant, les volumes au format ACFS seront bien controlés par Restart et démarreront bien automatiquement au boot du serveur, ou au redémarrage de Restart

 

Conclusion

Je vous ai proposé un petit aperçu de ce qu’il est possible de faire avec le GI dans un exemple certes pas très utile, mais concret.

Vous voyez bien que ça n’est qu’une ébauche de ce qu’il faudrait faire, notamment parce que la gestion des volumes ASM/ACFS y est globale, et non pas faite volume par volume (création d’une ressource par volume ASM et par point de montage ACFS). Pour se faire, il faudrait ajouter des attributs non standards à ces ressources, voire créer de nouveaux types de ressources, mais ça n’est pas l’objet de cet article.

Enjoy Oracle