1#!@BASH_SHELL@ 2 3# 4# NFS/CIFS file system mount/umount/etc. agent 5# 6# 7# Copyright (C) 1997-2003 Sistina Software, Inc. All rights reserved. 8# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. 9# 10# This program is free software; you can redistribute it and/or 11# modify it under the terms of the GNU General Public License 12# as published by the Free Software Foundation; either version 2 13# of the License, or (at your option) any later version. 14# 15# This program is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License for more details. 19# 20# You should have received a copy of the GNU General Public License 21# along with this program; if not, write to the Free Software 22# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23# 24 25. $(dirname $0)/utils/fs-lib.sh 26 27do_metadata() 28{ 29 cat <<EOT 30<?xml version="1.0" ?> 31<!DOCTYPE resource-agent SYSTEM "ra-api-1-modified.dtd"> 32<resource-agent name="netfs" version="rgmanager 2.0"> 33 <version>1.0</version> 34 35 <longdesc lang="en"> 36 This defines an NFS/CIFS mount for use by cluster services. 37 </longdesc> 38 <shortdesc lang="en"> 39 Defines an NFS/CIFS file system mount. 40 </shortdesc> 41 42 <parameters> 43 <parameter name="name" primary="1"> 44 <longdesc lang="en"> 45 Symbolic name for this file system. 46 </longdesc> 47 <shortdesc lang="en"> 48 File System Name 49 </shortdesc> 50 <content type="string"/> 51 </parameter> 52 53 <parameter name="mountpoint" unique="1" required="1"> 54 <longdesc lang="en"> 55 Path in file system heirarchy to mount this file system. 56 </longdesc> 57 <shortdesc lang="en"> 58 Mount Point 59 </shortdesc> 60 <content type="string"/> 61 </parameter> 62 63 <parameter name="host" required="1"> 64 <longdesc lang="en"> 65 Server IP address or hostname 66 </longdesc> 67 <shortdesc lang="en"> 68 IP or Host 69 </shortdesc> 70 <content type="string"/> 71 </parameter> 72 73 <parameter name="export" required="1"> 74 <longdesc lang="en"> 75 NFS Export directory name or CIFS share 76 </longdesc> 77 <shortdesc lang="en"> 78 Export 79 </shortdesc> 80 <content type="string"/> 81 </parameter> 82 83 <parameter name="fstype"> 84 <longdesc lang="en"> 85 File System type (nfs, nfs4 or cifs) 86 </longdesc> 87 <shortdesc lang="en"> 88 File System Type 89 </shortdesc> 90 <content type="string" default="nfs"/> 91 </parameter> 92 93 <parameter name="no_unmount" required="0"> 94 <longdesc lang="en"> 95 Do not unmount the filesystem during a stop or relocation operation 96 </longdesc> 97 <shortdesc lang="en"> 98 Skip unmount opration 99 </shortdesc> 100 <content type="boolean"/> 101 </parameter> 102 103 <parameter name="force_unmount"> 104 <longdesc lang="en"> 105 If set, the cluster will kill all processes using 106 this file system when the resource group is 107 stopped. Otherwise, the unmount will fail, and 108 the resource group will be restarted. 109 </longdesc> 110 <shortdesc lang="en"> 111 Force Unmount 112 </shortdesc> 113 <content type="boolean"/> 114 </parameter> 115 116 <parameter name="self_fence"> 117 <longdesc lang="en"> 118 If set and unmounting the file system fails, the node will 119 immediately reboot. Generally, this is used in conjunction 120 with force_unmount support, but it is not required. 121 </longdesc> 122 <shortdesc lang="en"> 123 Seppuku Unmount 124 </shortdesc> 125 <content type="boolean"/> 126 </parameter> 127 128 <parameter name="options"> 129 <longdesc lang="en"> 130 Provides a list of mount options. If none are specified, 131 the NFS file system is mounted -o sync. 132 </longdesc> 133 <shortdesc lang="en"> 134 Mount Options 135 </shortdesc> 136 <content type="string"/> 137 </parameter> 138 139 <parameter name="use_findmnt"> 140 <longdesc lang="en"> 141 Use findmnt to determine if and where a filesystem is mounted. 142 Disabling this uses the failback method (should be used if autofs 143 maps are located on network storage (ie. nfs, iscsi, etc). 144 </longdesc> 145 <shortdesc lang="en"> 146 Utilize findmnt to detect if and where filesystems are mounted 147 </shortdesc> 148 <content type="boolean"/> 149 </parameter> 150 151 </parameters> 152 153 <actions> 154 <action name="start" timeout="900"/> 155 <action name="stop" timeout="30"/> 156 <!-- Recovery isn't possible; we don't know if resources are using 157 the file system. --> 158 159 <!-- Checks to see if it's mounted in the right place --> 160 <action name="status" interval="1m" timeout="10"/> 161 <action name="monitor" interval="1m" timeout="10"/> 162 163 <!-- Checks to see if we can read from the mountpoint --> 164 <action name="status" depth="10" timeout="30" interval="5m"/> 165 <action name="monitor" depth="10" timeout="30" interval="5m"/> 166 167 <!-- Checks to see if we can write to the mountpoint (if !ROFS) --> 168 <action name="status" depth="20" timeout="30" interval="10m"/> 169 <action name="monitor" depth="20" timeout="30" interval="10m"/> 170 171 <action name="meta-data" timeout="5"/> 172 <action name="validate-all" timeout="5"/> 173 </actions> 174 175 <special tag="rgmanager"> 176 <child type="nfsexport" forbid="1"/> 177 <child type="nfsclient" forbid="1"/> 178 </special> 179</resource-agent> 180EOT 181} 182 183 184verify_host() 185{ 186 if [ -z "$OCF_RESKEY_host" ]; then 187 ocf_log err "No server hostname or IP address specified." 188 return 1 189 fi 190 191 host $OCF_RESKEY_host 2>&1 | grep -vq "not found" 192 if [ $? -eq 0 ]; then 193 return 0 194 fi 195 196 ocf_log err "Hostname or IP address \"$OCF_RESKEY_host\" not valid" 197 198 return $OCF_ERR_ARGS 199} 200 201 202verify_fstype() 203{ 204 # Auto detect? 205 [ -z "$OCF_RESKEY_fstype" ] && return 0 206 207 case $OCF_RESKEY_fstype in 208 nfs|nfs4|cifs) 209 return 0 210 ;; 211 *) 212 ocf_log err "File system type $OCF_RESKEY_fstype not supported" 213 return $OCF_ERR_ARGS 214 ;; 215 esac 216} 217 218 219verify_options() 220{ 221 declare -i ret=0 222 223 # 224 # From mount(1) 225 # 226 for o in `echo $OCF_RESKEY_options | sed -e s/,/\ /g`; do 227 case $o in 228 async|atime|auto|defaults|dev|exec|_netdev|noatime) 229 continue 230 ;; 231 noauto|nodev|noexec|nosuid|nouser|ro|rw|suid|sync) 232 continue 233 ;; 234 dirsync|user|users) 235 continue 236 ;; 237 esac 238 239 case $OCF_RESKEY_fstype in 240 cifs) 241 continue 242 ;; 243 nfs|nfs4) 244 case $o in 245 # 246 # NFS / NFS4 common 247 # 248 rsize=*|wsize=*|timeo=*|retrans=*|acregmin=*) 249 continue 250 ;; 251 acregmax=*|acdirmin=*|acdirmax=*|actimeo=*) 252 continue 253 ;; 254 retry=*|port=*|bg|fg|soft|hard|intr|cto|ac|noac) 255 continue 256 ;; 257 esac 258 259 # 260 # NFS v2/v3 only 261 # 262 if [ "$OCF_RESKEY_fstype" = "nfs" ]; then 263 case $o in 264 mountport=*|mounthost=*) 265 continue 266 ;; 267 mountprog=*|mountvers=*|nfsprog=*|nfsvers=*) 268 continue 269 ;; 270 namelen=*) 271 continue 272 ;; 273 tcp|udp|lock|nolock) 274 continue 275 ;; 276 esac 277 fi 278 279 # 280 # NFS4 only 281 # 282 if [ "$OCF_RESKEY_fstype" = "nfs4" ]; then 283 case $o in 284 proto=*|clientaddr=*|sec=*) 285 continue 286 ;; 287 esac 288 fi 289 290 ;; 291 esac 292 293 ocf_log err "Option $o not supported for $OCF_RESKEY_fstype" 294 ret=$OCF_ERR_ARGS 295 done 296 297 return $ret 298} 299 300 301do_validate() 302{ 303 verify_name || return $OCF_ERR_ARGS 304 verify_fstype|| return $OCF_ERR_ARGS 305 verify_host || return $OCF_ERR_ARGS 306 verify_mountpoint || return $OCF_ERR_ARGS 307 verify_options || return $OCF_ERR_ARGS 308 # verify_target || return $OCF_ERR_ARGS 309} 310 311 312# 313# Override real_device to use fs-lib's functions for start/stop_filesystem 314# 315real_device() { 316 export REAL_DEVICE="$1" 317} 318 319 320# 321# do_mount - nfs / cifs are mounted differently than blockdevs 322# 323do_mount() { 324 declare opts="" 325 declare mount_options="" 326 declare ret_val 327 declare mp="$OCF_RESKEY_mountpoint" 328 329 # 330 # Get the filesystem type, if specified. 331 # 332 fstype_option="" 333 fstype=${OCF_RESKEY_fstype} 334 case "$fstype" in 335 ""|"[ ]*") 336 fstype="" 337 ;; 338 *) # found it 339 fstype_option="-t $fstype" 340 ;; 341 esac 342 343 # 344 # Get the mount options, if they exist. 345 # 346 mount_options="" 347 opts=${OCF_RESKEY_options} 348 case "$opts" in 349 ""|"[ ]*") 350 opts="" 351 ;; 352 *) # found it 353 mount_options="-o $opts" 354 ;; 355 esac 356 357 case $OCF_RESKEY_fstype in 358 nfs|nfs4) 359 mount -t $OCF_RESKEY_fstype $mount_options $OCF_RESKEY_host:"$OCF_RESKEY_export" "$mp" 360 ;; 361 cifs) 362 mount -t $OCF_RESKEY_fstype $mount_options //$OCF_RESKEY_host/"$OCF_RESKEY_export" "$mp" 363 ;; 364 esac 365 366 ret_val=$? 367 if [ $ret_val -ne 0 ]; then 368 ocf_log err "\ 369'mount $fstype_option $mount_options $OCF_RESKEY_host:$OCF_RESKEY_export $mp' failed, error=$ret_val" 370 return 1 371 fi 372 373 return 0 374} 375 376do_nfs_rpc_check() { 377 # see man nfs TRANSPORT PROTOCOL section for defaults 378 local nfsproto=tcp 379 local nfsmountproto=udp 380 381 # follow the same logic as mount.nfs option parser. 382 # the rightmost option wins over previous ones, so don't break when 383 # we find something. 384 385 for o in $(echo ${OCF_RESKEY_options} | sed -e s/,/\ /g); do 386 if echo $o | grep -q "^proto=" ; then 387 nfsproto="$(echo $o | cut -d "=" -f 2)" 388 fi 389 if echo $o | grep -q "^mountproto=" ; then 390 nfsmountproto="$(echo $o | cut -d "=" -f 2)" 391 fi 392 case $o in 393 tcp) nfsproto=tcp;; 394 udp) nfsproto=udp;; 395 rdma) nfsproto=rdma;; 396 esac 397 done 398 399 ocf_log debug "Testing generic rpc access on server ${OCF_RESKEY_host} with protocol $nfsproto" 400 if ! rpcinfo -T $nfsproto ${OCF_RESKEY_host} > /dev/null 2>&1; then 401 ocf_log alert "RPC server on ${OCF_RESKEY_host} with $nfsproto is not responding" 402 return 1 403 fi 404 405 ocf_log debug "Testing nfs rcp access on server ${OCF_RESKEY_host} with protocol $nfsproto" 406 if ! rpcinfo -T $nfsproto ${OCF_RESKEY_host} nfs > /dev/null 2>&1; then 407 ocf_log alert "NFS server on ${OCF_RESKEY_host} with $nfsproto is not responding" 408 return 1 409 fi 410 411 if [ "$OCF_RESKEY_fstype" = nfs ]; then 412 ocf_log debug "Testing mountd rpc access on server ${OCF_RESKEY_host} with protocol $nfsmountproto" 413 if ! rpcinfo -T $nfsmountproto ${OCF_RESKEY_host} mountd; then 414 ocf_log alert "MOUNTD server on ${OCF_RESKEY_host} with $nfsmountproto is not responding" 415 return 1 416 fi 417 fi 418 419 return 0 420} 421 422do_pre_unmount() { 423 case $OCF_RESKEY_fstype in 424 nfs|nfs4) 425 if [ "$self_fence" != $YES ]; then 426 ocf_log debug "Skipping pre unmount checks: self_fence is disabled" 427 return 0 428 fi 429 430 is_mounted "$dev" "$mp" 431 case $? in 432 $NO) 433 ocf_log debug "Skipping pre unmount checks: device is not mounted" 434 return 0 435 ;; 436 esac 437 438 ocf_log info "pre unmount: checking if nfs server ${OCF_RESKEY_host} is alive" 439 if ! do_nfs_rpc_check; then 440 ocf_log alert "NFS server not responding - REBOOTING" 441 sleep 2 442 reboot -fn 443 fi 444 ;; 445 esac 446 447 return 0 448} 449 450do_force_unmount() { 451 case $OCF_RESKEY_fstype in 452 nfs|nfs4) 453 ocf_log warning "Calling 'umount -f $mp'" 454 umount -f "$OCF_RESKEY_mountpoint" 455 return $? 456 ;; 457 *) 458 ;; 459 esac 460 461 return 1 # Returning 1 lets stop_filesystem do add'l checks 462} 463 464 465populate_defaults() 466{ 467 case $OCF_RESKEY_fstype in 468 nfs|nfs4) 469 export OCF_RESKEY_device="$OCF_RESKEY_host:$OCF_RESKEY_export" 470 if [ -z "$OCF_RESKEY_options" ]; then 471 export OCF_RESKEY_options=sync,soft,noac 472 fi 473 ;; 474 cifs) 475 export OCF_RESKEY_device="//$OCF_RESKEY_host/$OCF_RESKEY_export" 476 if [ -z "$OCF_RESKEY_options" ]; then 477 export OCF_RESKEY_options=guest 478 fi 479 ;; 480 esac 481} 482 483 484# 485# Main... 486# 487populate_defaults 488main $* 489