Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / ocf / rbd.in
1 #!/bin/sh
2 #
3 #   OCF resource agent for mapping and unmapping
4 #   RADOS Block Devices (RBDs)
5 #
6 #   License:      GNU Lesser General Public License (LGPL) 2.1
7 #   (c) 2012 Florian Haas, hastexo
8 #
9
10 # Initialization:
11 : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
12 . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
13
14 # Convenience variables
15 # When sysconfdir isn't passed in as a configure flag,
16 # it's defined in terms of prefix
17 prefix=@prefix@
18
19 # Defaults
20 OCF_RESKEY_pool_default="rbd"
21 OCF_RESKEY_cephconf_default="@sysconfdir@/@PACKAGE_TARNAME@/@PACKAGE_TARNAME@.conf"
22 : ${OCF_RESKEY_pool=${OCF_RESKEY_pool_default}}
23 : ${OCF_RESKEY_cephconf=${OCF_RESKEY_cephconf_default}}
24
25 rbd_meta_data() {
26     cat <<EOF
27 <?xml version="1.0"?>
28 <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
29 <resource-agent name="rbd" version="0.1">
30   <version>0.1</version>
31   <longdesc lang="en">
32 Manages RADOS Block Devices (RBDs) as a highly available
33 resource. Maps and unmaps RBDs as needed.
34   </longdesc>
35   <shortdesc lang="en">Maps and unmaps RADOS Block Devices</shortdesc>
36   <parameters>
37     <parameter name="name" unique="0" required="1">
38       <longdesc lang="en">
39       Name of the RBD device.
40       </longdesc>
41       <shortdesc lang="en">RBD device name</shortdesc>
42       <content type="string"/>
43     </parameter>
44     <parameter name="pool" unique="0" required="0">
45       <longdesc lang="en">
46       Name of the RADOS pool where the RBD has been created
47       </longdesc>
48       <shortdesc lang="en">RADOS pool name</shortdesc>
49       <content type="string" default="${OCF_RESKEY_pool_default}"/>
50     </parameter>
51     <parameter name="snap" unique="0" required="0">
52       <longdesc lang="en">
53       Name of the device snapshot to map.
54       </longdesc>
55       <shortdesc lang="en">Snapshot name</shortdesc>
56       <content type="string"/>
57     </parameter>
58     <parameter name="cephconf" unique="0" required="0">
59       <longdesc lang="en">
60       Location of the Ceph configuration file
61       </longdesc>
62       <shortdesc lang="en">Ceph configuration file</shortdesc>
63       <content type="string" default="${OCF_RESKEY_cephconf_default}"/>
64     </parameter>
65     <parameter name="mon" unique="0" required="0">
66       <longdesc lang="en">
67       Address (or comma-separated list of addresses) of
68       monitor servers to connect to. Overrides values from
69       configuration file.
70       </longdesc>
71       <shortdesc lang="en">Monitor address(es)</shortdesc>
72       <content type="string"/>
73     </parameter>
74     <parameter name="user" unique="0" required="0">
75       <longdesc lang="en">
76       Username to use when mapping the device. Required
77       if Ceph authentication is enabled on the monitor.
78       </longdesc>
79       <shortdesc lang="en">Authentication username</shortdesc>
80       <content type="string"/>
81     </parameter>
82     <parameter name="secret" unique="0" required="0">
83       <longdesc lang="en">
84       File containing an authentication secret. Required
85       if Ceph authentication is enabled on the monitor.
86       </longdesc>
87       <shortdesc lang="en">Authentication secret file</shortdesc>
88       <content type="string"/>
89     </parameter>
90   </parameters>
91   <actions>
92     <action name="start"        timeout="20" />
93     <action name="stop"         timeout="20" />
94     <action name="monitor"      timeout="20"
95                                 interval="10" depth="0" />
96     <action name="meta-data"    timeout="5" />
97     <action name="validate-all"   timeout="20" />
98   </actions>
99 </resource-agent>
100 EOF
101 }
102
103 rbd_usage() {
104         cat <<EOF
105 usage: $0 {start|stop|status|monitor|validate-all|meta-data}
106
107 Expects to have a fully populated OCF RA-compliant environment set.
108 EOF
109 }
110
111 # rbd command wrapper: builds an option string for invoking RBD based
112 # on resource parameters, and invokes rbd through ocf_run.
113 do_rbd() {
114     local rbd_options
115
116     if [ -n "${OCF_RESKEY_cephconf}" ]; then
117         rbd_options="$rbd_options -c ${OCF_RESKEY_cephconf}"
118     fi
119     if [ -n "${OCF_RESKEY_mon}" ]; then
120         rbd_options="$rbd_options -m ${OCF_RESKEY_mon}"
121     fi
122
123     ocf_run rbd $rbd_options $@
124 }
125
126 # Convenience function that uses "rbd showmapped" to retrieve the
127 # mapped device name from the pool, RBD name, and snapshot.
128 find_rbd_dev() {
129     local sedpat
130
131     # Example output from "rbd showmapped" (tab separated):
132     # id        pool    image   snap    device
133     # 0         rbd     test    -       /dev/rbd0
134
135     # Build the sed pattern, substituting "-" for the snapshot name if
136     # it's unset
137     sedpat="[0-9]\+[ \t]\+${OCF_RESKEY_pool}[ \t]\+${OCF_RESKEY_name}[ \t]\+${OCF_RESKEY_snap:--}[ \t]\+\(/dev/rbd[0-9]\+\).*"
138
139     # Run rbd showmapped, filter out the header line, then try to
140     # extract the device name
141     rbd showmapped | tail -n +2 | sed -n -e "s,$sedpat,\1,p"
142 }
143
144 rbd_validate_all() {
145     # Test for configuration errors first
146     if [ -z "$OCF_RESKEY_name" ]; then
147        ocf_log err 'Required parameter "name" is unset!'
148        exit $OCF_ERR_CONFIGURED
149     fi
150
151     # Test for required binaries
152     check_binary rbd
153
154     return $OCF_SUCCESS
155 }
156
157 rbd_monitor() {
158     local rc
159     local rbd_dev
160
161     if ! [ -d /sys/bus/rbd ]; then
162         ocf_log debug "rbd module is not loaded"
163         return $OCF_NOT_RUNNING
164     fi
165
166     rbd_dev=`find_rbd_dev`
167
168     if [ -z "$rbd_dev" ]; then
169         ocf_log debug "RBD device is unmapped"
170         rc=$OCF_NOT_RUNNING
171     elif [ -b "$rbd_dev" ]; then
172         ocf_log debug "RBD device is mapped to $rbd_dev"
173         rc=$OCF_SUCCESS
174     else
175         # Device is listed, but the corresponding path is not a block
176         # device.
177         ocf_log err "$rbd_dev is not a block device!"
178         rc=$OCF_ERR_GENERIC
179     fi
180
181     return $rc
182 }
183
184 rbd_start() {
185     local rbd_map_options
186     local rbd_name
187
188     # if resource is already running, bail out early
189     if rbd_monitor; then
190         ocf_log info "Resource is already running"
191         return $OCF_SUCCESS
192     fi
193
194     # actually start up the resource here (make sure to immediately
195     # exit with an $OCF_ERR_ error code if anything goes seriously
196     # wrong)
197
198     if [ ! -d /sys/bus/rbd ]; then
199         ocf_run modprobe -v rbd || exit $OCF_ERR_INSTALLED
200     fi
201
202     if [ -n "${OCF_RESKEY_user}" ]; then
203         rbd_map_options="--id ${OCF_RESKEY_user}"
204     fi
205     if [ -n "${OCF_RESKEY_secret}" ]; then
206         rbd_map_options="$rbd_map_options --keyfile ${OCF_RESKEY_secret}"
207     fi
208
209     rbd_name="${OCF_RESKEY_pool}/${OCF_RESKEY_name}"
210     if [ -n "${OCF_RESKEY_snap}" ]; then
211         rbd_name="$rbd_name@${OCF_RESKEY_snap}"
212     fi
213
214     do_rbd map $rbd_name $rbd_map_options || exit $OCF_ERR_GENERIC
215
216     # After the resource has been started, check whether it started up
217     # correctly. If the resource starts asynchronously, the agent may
218     # spin on the monitor function here -- if the resource does not
219     # start up within the defined timeout, the cluster manager will
220     # consider the start action failed
221     while ! rbd_monitor; do
222         ocf_log debug "Resource has not started yet, waiting"
223         sleep 1
224     done
225
226     # only return $OCF_SUCCESS if _everything_ succeeded as expected
227     return $OCF_SUCCESS
228 }
229
230 rbd_stop() {
231     local rc
232     local rbd_dev
233
234     rbd_monitor
235     rc=$?
236     case "$rc" in
237         "$OCF_SUCCESS")
238             # Currently running. Normal, expected behavior.
239             ocf_log debug "Resource is currently running"
240             ;;
241         "$OCF_NOT_RUNNING")
242             # Currently not running. Nothing to do.
243             ocf_log info "Resource is already stopped"
244             return $OCF_SUCCESS
245             ;;
246     esac
247
248     # actually shut down the resource here (make sure to immediately
249     # exit with an $OCF_ERR_ error code if anything goes seriously
250     # wrong)
251     rbd_dev=`find_rbd_dev`
252     do_rbd unmap $rbd_dev || exit $OCF_ERR_GENERIC
253
254     # After the resource has been stopped, check whether it shut down
255     # correctly. If the resource stops asynchronously, the agent may
256     # spin on the monitor function here -- if the resource does not
257     # shut down within the defined timeout, the cluster manager will
258     # consider the stop action failed
259     while rbd_monitor; do
260         ocf_log debug "Resource has not stopped yet, waiting"
261         sleep 1
262     done
263
264     # only return $OCF_SUCCESS if _everything_ succeeded as expected
265     return $OCF_SUCCESS
266
267 }
268
269 # Make sure meta-data and usage always succeed
270 case $__OCF_ACTION in
271 meta-data)      rbd_meta_data
272                 exit $OCF_SUCCESS
273                 ;;
274 usage|help)     rbd_usage
275                 exit $OCF_SUCCESS
276                 ;;
277 esac
278
279 # Anything other than meta-data and usage must pass validation
280 rbd_validate_all || exit $?
281
282 # Translate each action into the appropriate function call
283 case $__OCF_ACTION in
284 start)          rbd_start;;
285 stop)           rbd_stop;;
286 status|monitor) rbd_monitor;;
287 validate-all)   ;;
288 *)              rbd_usage
289                 exit $OCF_ERR_UNIMPLEMENTED
290                 ;;
291 esac
292 rc=$?
293
294 # The resource agent may optionally log a debug message
295 ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION returned $rc"
296 exit $rc