~ubuntu-branches/debian/stretch/resource-agents/stretch

« back to all changes in this revision

Viewing changes to rgmanager/src/resources/vm.sh

  • Committer: Bazaar Package Importer
  • Author(s): Andres Rodriguez
  • Date: 2011-06-10 16:26:35 UTC
  • Revision ID: james.westby@ubuntu.com-20110610162635-yiy0vfopqw4trzgx
Tags: upstream-3.9.0
ImportĀ upstreamĀ versionĀ 3.9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/bin/bash
 
2
#
 
3
# Copyright (C) 1997-2003 Sistina Software, Inc.  All rights reserved.
 
4
# Copyright (C) 2004-2011 Red Hat, Inc.  All rights reserved.
 
5
#
 
6
# This program is free software; you can redistribute it and/or
 
7
# modify it under the terms of the GNU General Public License
 
8
# as published by the Free Software Foundation; either version 2
 
9
# of the License, or (at your option) any later version.
 
10
#
 
11
# This program is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License
 
17
# along with this program; if not, write to the Free Software
 
18
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
19
#
 
20
 
 
21
PATH=/bin:/sbin:/usr/bin:/usr/sbin
 
22
 
 
23
export PATH
 
24
 
 
25
. $(dirname $0)/ocf-shellfuncs || exit 1
 
26
 
 
27
#
 
28
# Virtual Machine start/stop script (requires the virsh command)
 
29
#
 
30
 
 
31
# Indeterminate state: xend/libvirtd is down.
 
32
export OCF_APP_ERR_INDETERMINATE=150
 
33
 
 
34
meta_data()
 
35
{
 
36
    cat <<EOT
 
37
<?xml version="1.0"?>
 
38
<resource-agent version="rgmanager 2.0" name="vm">
 
39
    <version>1.0</version>
 
40
 
 
41
    <longdesc lang="en">
 
42
        Defines a Virtual Machine
 
43
    </longdesc>
 
44
    <shortdesc lang="en">
 
45
        Defines a Virtual Machine
 
46
    </shortdesc>
 
47
 
 
48
    <parameters>
 
49
        <parameter name="name" primary="1">
 
50
            <longdesc lang="en">
 
51
                This is the name of the virtual machine.
 
52
            </longdesc>
 
53
            <shortdesc lang="en">
 
54
                Name
 
55
            </shortdesc>
 
56
            <content type="string"/>
 
57
        </parameter>
 
58
    
 
59
        <parameter name="domain" reconfig="1">
 
60
            <longdesc lang="en">
 
61
                Failover domains define lists of cluster members
 
62
                to try in the event that the host of the virtual machine
 
63
                fails.
 
64
            </longdesc>
 
65
            <shortdesc lang="en">
 
66
                Cluster failover Domain
 
67
            </shortdesc>
 
68
            <content type="string"/>
 
69
        </parameter>
 
70
 
 
71
        <parameter name="autostart" reconfig="1">
 
72
            <longdesc lang="en">
 
73
                If set to yes, this resource group will automatically be started
 
74
                after the cluster forms a quorum.  If set to no, this virtual
 
75
                machine will start in the 'disabled' state after the cluster
 
76
                forms a quorum.
 
77
            </longdesc>
 
78
            <shortdesc lang="en">
 
79
                Automatic start after quorum formation
 
80
            </shortdesc>
 
81
            <content type="boolean" default="1"/>
 
82
        </parameter>
 
83
 
 
84
        <parameter name="exclusive" reconfig="1">
 
85
            <longdesc lang="en">
 
86
                If set, this resource group will only relocate to
 
87
                nodes which have no other resource groups running in the
 
88
                event of a failure.  If no empty nodes are available,
 
89
                this resource group will not be restarted after a failure.
 
90
                Additionally, resource groups will not automatically
 
91
                relocate to the node running this resource group.  This
 
92
                option can be overridden by manual start and/or relocate
 
93
                operations.
 
94
            </longdesc>
 
95
            <shortdesc lang="en">
 
96
                Exclusive resource group
 
97
            </shortdesc>
 
98
            <content type="boolean" default="0"/>
 
99
        </parameter>
 
100
 
 
101
        <parameter name="recovery" reconfig="1">
 
102
            <longdesc lang="en">
 
103
                This currently has three possible options: "restart" tries
 
104
                to restart this virtual machine locally before
 
105
                attempting to relocate (default); "relocate" does not bother
 
106
                trying to restart the VM locally; "disable" disables
 
107
                the VM if it fails.
 
108
            </longdesc>
 
109
            <shortdesc lang="en">
 
110
                Failure recovery policy
 
111
            </shortdesc>
 
112
            <content type="string"/>
 
113
        </parameter>
 
114
 
 
115
       <parameter name="migration_mapping" reconfig="1">
 
116
           <longdesc lang="en">
 
117
               Mapping of the hostname of a target cluster member to a different hostname
 
118
           </longdesc>
 
119
           <shortdesc lang="en">
 
120
               memberhost:targethost,memberhost:targethost ..
 
121
           </shortdesc>
 
122
            <content type="string"/>
 
123
        </parameter>
 
124
 
 
125
        <parameter name="use_virsh">
 
126
            <longdesc lang="en">
 
127
                Force use of virsh instead of xm on Xen machines.
 
128
            </longdesc>
 
129
            <shortdesc lang="en">
 
130
                If set to 1, vm.sh will use the virsh command to manage
 
131
                virtual machines instead of xm.  This is required when
 
132
                using non-Xen virtual machines (e.g. qemu / KVM).
 
133
            </shortdesc>
 
134
            <content type="integer" default=""/>
 
135
        </parameter>
 
136
 
 
137
        <parameter name="xmlfile">
 
138
            <longdesc lang="en">
 
139
                Full path to libvirt XML file describing the domain.
 
140
            </longdesc>
 
141
            <shortdesc lang="en">
 
142
                Full path to libvirt XML file describing the domain.
 
143
            </shortdesc>
 
144
            <content type="string"/>
 
145
        </parameter>
 
146
 
 
147
        <parameter name="migrate">
 
148
            <longdesc lang="en">
 
149
                Migration type (live or pause, default = live).
 
150
            </longdesc>
 
151
            <shortdesc lang="en">
 
152
                Migration type (live or pause, default = live).
 
153
            </shortdesc>
 
154
            <content type="string" default="live"/>
 
155
        </parameter>
 
156
 
 
157
        <parameter name="path">
 
158
            <longdesc lang="en">
 
159
                Path specification vm.sh will search for the specified
 
160
                VM configuration file.  /path1:/path2:...
 
161
            </longdesc>
 
162
            <shortdesc lang="en">
 
163
                Path to virtual machine configuration files.
 
164
            </shortdesc>
 
165
            <content type="string"/>
 
166
        </parameter>
 
167
 
 
168
        <parameter name="snapshot">
 
169
            <longdesc lang="en">
 
170
                Path to the snapshot directory where the virtual machine
 
171
                image will be stored.
 
172
            </longdesc>
 
173
            <shortdesc lang="en">
 
174
                Path to the snapshot directory where the virtual machine
 
175
                image will be stored.
 
176
            </shortdesc>
 
177
            <content type="string" default=""/>
 
178
        </parameter>
 
179
 
 
180
        <parameter name="depend">
 
181
            <longdesc lang="en">
 
182
                Service dependency; will not start without the specified
 
183
                service running.
 
184
            </longdesc>
 
185
            <shortdesc lang="en">
 
186
                Top-level service this depends on, in service:name format.
 
187
            </shortdesc>
 
188
            <content type="string"/>
 
189
        </parameter>
 
190
 
 
191
        <parameter name="depend_mode">
 
192
            <longdesc lang="en">
 
193
                Service dependency mode.
 
194
                hard - This service is stopped/started if its dependency
 
195
                       is stopped/started
 
196
                soft - This service only depends on the other service for
 
197
                       initial startip.  If the other service stops, this
 
198
                       service is not stopped.
 
199
            </longdesc>
 
200
            <shortdesc lang="en">
 
201
                Service dependency mode (soft or hard).
 
202
            </shortdesc>
 
203
            <content type="string" default="hard"/>
 
204
        </parameter>
 
205
 
 
206
        <parameter name="max_restarts" reconfig="1">
 
207
            <longdesc lang="en">
 
208
                Maximum restarts for this service.
 
209
            </longdesc>
 
210
            <shortdesc lang="en">
 
211
                Maximum restarts for this service.
 
212
            </shortdesc>
 
213
            <content type="string" default="0"/>
 
214
        </parameter>
 
215
 
 
216
        <parameter name="restart_expire_time" reconfig="1">
 
217
            <longdesc lang="en">
 
218
                Restart expiration time.  A restart is forgotten
 
219
                after this time.  When combined with the max_restarts
 
220
                option, this lets administrators specify a threshold
 
221
                for when to fail over services.  If max_restarts
 
222
                is exceeded in this given expiration time, the service
 
223
                is relocated instead of restarted again.
 
224
            </longdesc>
 
225
            <shortdesc lang="en">
 
226
                Restart expiration time; amount of time before a restart
 
227
                is forgotten.
 
228
            </shortdesc>
 
229
            <content type="string" default="0"/>
 
230
        </parameter>
 
231
 
 
232
        <parameter name="status_program" reconfig="1">
 
233
            <longdesc lang="en">
 
234
                Ordinarily, only the presence/health of a virtual machine
 
235
                is checked.  If specified, the status_program value is
 
236
                executed during a depth 10 check.  The intent of this 
 
237
                program is to ascertain the status of critical services
 
238
                within a virtual machine.
 
239
            </longdesc>
 
240
            <shortdesc lang="en">
 
241
                Additional status check program
 
242
            </shortdesc>
 
243
            <content type="string" default=""/>
 
244
        </parameter>
 
245
 
 
246
        <parameter name="hypervisor">
 
247
            <shortdesc lang="en">
 
248
                Hypervisor
 
249
            </shortdesc >
 
250
            <longdesc lang="en">
 
251
                Specify hypervisor tricks to use.  Default = auto.
 
252
                Other supported options are xen and qemu.
 
253
            </longdesc>
 
254
            <content type="string" default="auto" />
 
255
        </parameter>
 
256
 
 
257
        <parameter name="hypervisor_uri">
 
258
            <longdesc lang="en">
 
259
                Hypervisor URI.  Generally, this is keyed off of the
 
260
                hypervisor and does not need to be set.
 
261
            </longdesc>
 
262
            <shortdesc lang="en">
 
263
                Hypervisor URI (normally automatic).
 
264
            </shortdesc >
 
265
            <content type="string" default="auto" />
 
266
        </parameter>
 
267
 
 
268
        <parameter name="migration_uri">
 
269
            <longdesc lang="en">
 
270
                Migration URI.  Generally, this is keyed off of the
 
271
                hypervisor and does not need to be set.
 
272
            </longdesc>
 
273
            <shortdesc lang="en">
 
274
                Migration URI (normally automatic).
 
275
            </shortdesc >
 
276
            <content type="string" default="auto" />
 
277
        </parameter>
 
278
 
 
279
    </parameters>
 
280
 
 
281
    <actions>
 
282
        <action name="start" timeout="300"/>
 
283
        <action name="stop" timeout="120"/>
 
284
        
 
285
        <action name="status" timeout="10" interval="30"/>
 
286
        <action name="monitor" timeout="10" interval="30"/>
 
287
 
 
288
        <!-- depth 10 calls the status_program -->
 
289
        <action name="status" depth="10" timeout="20" interval="60"/>
 
290
        <action name="monitor" depth="10" timeout="20" interval="60"/>
 
291
 
 
292
        <!-- reconfigure - reconfigure with new OCF parameters.
 
293
             NOT OCF COMPATIBLE AT ALL -->
 
294
        <action name="reconfig" timeout="10"/>
 
295
 
 
296
        <action name="migrate" timeout="10m"/>
 
297
 
 
298
        <action name="meta-data" timeout="5"/>
 
299
        <action name="validate-all" timeout="5"/>
 
300
 
 
301
    </actions>
 
302
    
 
303
    <special tag="rgmanager">
 
304
        <!-- Destroy_on_delete / init_on_add are currently only
 
305
             supported for migratory resources (no children
 
306
             and the 'migrate' action; see above.  Do not try this
 
307
             with normal services -->
 
308
        <attributes maxinstances="1" destroy_on_delete="0" init_on_add="0"/>
 
309
    </special>
 
310
</resource-agent>
 
311
EOT
 
312
}
 
313
 
 
314
 
 
315
build_virsh_cmdline()
 
316
{
 
317
        declare cmdline=""
 
318
        declare operation=$1
 
319
 
 
320
        if [ -n "$OCF_RESKEY_hypervisor_uri" ]; then
 
321
                cmdline="$cmdline -c $OCF_RESKEY_hypervisor_uri"
 
322
        fi
 
323
 
 
324
        cmdline="$cmdline $operation $OCF_RESKEY_name"
 
325
                
 
326
        echo $cmdline
 
327
}
 
328
 
 
329
 
 
330
# this is only used on startup
 
331
build_xm_cmdline()
 
332
{
 
333
        declare operation=$1
 
334
        #
 
335
        # Virtual domains should never restart themselves when 
 
336
        # controlled externally; the external monitoring app
 
337
        # should.
 
338
        #
 
339
        declare cmdline="on_shutdown=\"destroy\" on_reboot=\"destroy\" on_crash=\"destroy\""
 
340
 
 
341
        if [ -n "$OCF_RESKEY_path" ]; then
 
342
                operation="$operation --path=\"$OCF_RESKEY_path\""
 
343
        fi
 
344
 
 
345
        if [ -n "$OCF_RESKEY_name" ]; then
 
346
                cmdline="$operation $OCF_RESKEY_name $cmdline"
 
347
        fi
 
348
 
 
349
        echo $cmdline
 
350
}
 
351
 
 
352
 
 
353
do_xm_start()
 
354
{
 
355
        # Use /dev/null for the configuration file, if xmdefconfig
 
356
        # doesn't exist...
 
357
        #
 
358
        declare cmdline
 
359
 
 
360
        echo -n "Virtual machine $OCF_RESKEY_name is "
 
361
        do_status && return 0
 
362
 
 
363
        cmdline="`build_xm_cmdline create`"
 
364
 
 
365
        ocf_log debug "xm $cmdline"
 
366
 
 
367
        eval xm $cmdline
 
368
        return $?
 
369
}
 
370
 
 
371
 
 
372
get_timeout()
 
373
{
 
374
        declare -i default_timeout=60
 
375
        declare -i tout=60
 
376
 
 
377
        if [ -n "$OCF_RESKEY_RGMANAGER_meta_timeout" ]; then
 
378
                tout=$OCF_RESKEY_RGMANAGER_meta_timeout
 
379
        elif [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
 
380
                tout=$OCF_RESKEY_CRM_meta_timeout
 
381
        fi
 
382
 
 
383
        if [ $tout -eq 0 ]; then
 
384
                echo $default_timeout
 
385
                return 0
 
386
        fi
 
387
        if [ $tout -lt 0 ]; then
 
388
                echo $default_timeout
 
389
                return 0
 
390
        fi
 
391
 
 
392
        echo $tout
 
393
        return 0
 
394
}
 
395
 
 
396
 
 
397
#
 
398
# Start a virtual machine given the parameters from
 
399
# the environment.
 
400
#
 
401
do_virsh_start()
 
402
{
 
403
        declare cmdline
 
404
        declare snapshotimage
 
405
 
 
406
        echo -n "Virtual machine $OCF_RESKEY_name is "
 
407
        do_status && return 0
 
408
 
 
409
        snapshotimage="$OCF_RESKEY_snapshot/$OCF_RESKEY_name"
 
410
 
 
411
        if [ -n "$OCF_RESKEY_snapshot" -a -f "$snapshotimage" ]; then
 
412
                eval virsh restore $snapshotimage
 
413
                if [ $? -eq 0 ]; then
 
414
                        rm -f $snapshotimage
 
415
                        return 0
 
416
                fi
 
417
                return 1
 
418
        fi
 
419
 
 
420
        if [ -n "$OCF_RESKEY_xmlfile" -a -f "$OCF_RESKEY_xmlfile" ]; then
 
421
                # TODO: try to use build_virsh_cmdline for the hypervisor_uri
 
422
                cmdline="virsh create $OCF_RESKEY_xmlfile"
 
423
        else
 
424
                cmdline="virsh $(build_virsh_cmdline start)"
 
425
        fi
 
426
 
 
427
        ocf_log debug "$cmdline"
 
428
 
 
429
        $cmdline
 
430
        return $?
 
431
}
 
432
 
 
433
 
 
434
do_xm_stop()
 
435
{
 
436
        declare -i timeout=60
 
437
        declare -i ret=1
 
438
        declare st
 
439
 
 
440
        for op in $*; do
 
441
                echo "CMD: xm $op $OCF_RESKEY_name"
 
442
                xm $op $OCF_RESKEY_name
 
443
 
 
444
                timeout=60
 
445
                while [ $timeout -gt 0 ]; do
 
446
                        sleep 5
 
447
                        ((timeout -= 5))
 
448
                        do_status&>/dev/null || return 0
 
449
                        while read dom state; do
 
450
                                #
 
451
                                # State is "stopped".  Kill it.
 
452
                                #
 
453
                                if [ "$dom" != "$OCF_RESKEY_name" ]; then
 
454
                                        continue
 
455
                                fi
 
456
                                if [ "$state" != "---s-" ]; then
 
457
                                        continue
 
458
                                fi
 
459
                                xm destroy $OCF_RESKEY_name
 
460
                        done < <(xm list | awk '{print $1, $5}')
 
461
                done
 
462
        done
 
463
 
 
464
        return 1
 
465
}
 
466
 
 
467
 
 
468
#
 
469
# Stop a VM.  Try to shut it down.  Wait a bit, and if it
 
470
# doesn't shut down, destroy it.
 
471
#
 
472
do_virsh_stop()
 
473
{
 
474
        declare -i timeout=$(get_timeout)
 
475
        declare -i ret=1
 
476
        declare state
 
477
 
 
478
        state=$(do_status)
 
479
        [ $? -eq 0 ] || return 0
 
480
 
 
481
        if [ -n "$OCF_RESKEY_snapshot" ]; then
 
482
                virsh save $OCF_RESKEY_name "$OCF_RESKEY_snapshot/$OCF_RESKEY_name"
 
483
        fi
 
484
 
 
485
        for op in $*; do
 
486
                echo virsh $op $OCF_RESKEY_name ...
 
487
                virsh $op $OCF_RESKEY_name
 
488
 
 
489
                timeout=$(get_timeout)
 
490
                while [ $timeout -gt 0 ]; do
 
491
                        sleep 5
 
492
                        ((timeout -= 5))
 
493
                        state=$(do_status)
 
494
                        [ $? -eq 0 ] || return 0
 
495
 
 
496
                        if [ "$state" = "paused" ]; then
 
497
                                virsh destroy $OCF_RESKEY_name
 
498
                        fi
 
499
                done
 
500
        done
 
501
 
 
502
        return 1
 
503
}
 
504
 
 
505
 
 
506
do_start()
 
507
{
 
508
        if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
 
509
                do_virsh_start $*
 
510
                return $?
 
511
        fi
 
512
 
 
513
        do_xm_start $*
 
514
        return $?
 
515
}
 
516
 
 
517
 
 
518
do_stop()
 
519
{
 
520
        declare domstate rv
 
521
 
 
522
        domstate=$(do_status)
 
523
        rv=$?
 
524
        ocf_log debug "Virtual machine $OCF_RESKEY_name is $domstate"
 
525
        if [ $rv -eq $OCF_APP_ERR_INDETERMINATE ]; then
 
526
                ocf_log crit "xend/libvirtd is dead; cannot stop $OCF_RESKEY_name"
 
527
                return 1
 
528
        fi
 
529
 
 
530
        if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
 
531
                do_virsh_stop $*
 
532
                return $?
 
533
        fi
 
534
 
 
535
        do_xm_stop $*
 
536
        return $?
 
537
}
 
538
 
 
539
 
 
540
#
 
541
# Reconfigure a running VM.
 
542
#
 
543
reconfigure()
 
544
{
 
545
        return 0
 
546
}
 
547
 
 
548
 
 
549
xm_status()
 
550
{
 
551
        service xend status &> /dev/null
 
552
        if [ $? -ne 0 ]; then 
 
553
                # if xend died
 
554
                echo indeterminate
 
555
                return $OCF_APP_ERR_INDETERMINATE
 
556
        fi
 
557
 
 
558
        xm list $OCF_RESKEY_name &> /dev/null
 
559
        if [ $? -eq 0 ]; then
 
560
                echo "running"
 
561
                return 0
 
562
        fi
 
563
        xm list migrating-$OCF_RESKEY_name &> /dev/null
 
564
        if [ $? -eq 0 ]; then
 
565
                echo "running"
 
566
                return 0
 
567
        fi
 
568
        echo "not running"
 
569
        return 1
 
570
}
 
571
 
 
572
 
 
573
virsh_status()
 
574
{
 
575
        declare state pid
 
576
 
 
577
        if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then
 
578
                service xend status &> /dev/null
 
579
                if [ $? -ne 0 ]; then 
 
580
                        echo indeterminate
 
581
                        return $OCF_APP_ERR_INDETERMINATE
 
582
                fi
 
583
        fi
 
584
 
 
585
        #
 
586
        # libvirtd is required when using virsh even though
 
587
        # not specifically when also using Xen.  This is because
 
588
        # libvirtd is required for migration.
 
589
        #
 
590
        pid=$(pidof libvirtd)
 
591
        if [ -z "$pid" ]; then 
 
592
                echo indeterminate
 
593
                return $OCF_APP_ERR_INDETERMINATE
 
594
        fi
 
595
 
 
596
        state=$(virsh domstate $OCF_RESKEY_name)
 
597
 
 
598
        echo $state
 
599
 
 
600
        if [ "$state" = "running" ] || [ "$state" = "paused" ] || [ "$state" = "no state" ] || 
 
601
           [ "$state" = "idle" ]; then
 
602
                return 0
 
603
        fi
 
604
 
 
605
        if [ "$state" = "shut off" ]; then
 
606
                return $OCF_NOT_RUNNING
 
607
        fi
 
608
 
 
609
        return $OCF_ERR_GENERIC
 
610
}
 
611
 
 
612
 
 
613
#
 
614
# Simple status check: Find the VM in the list of running
 
615
# VMs
 
616
#
 
617
do_status()
 
618
{
 
619
        if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
 
620
                virsh_status
 
621
                return $?
 
622
        fi
 
623
 
 
624
        xm_status
 
625
        return $?
 
626
}
 
627
 
 
628
 
 
629
#
 
630
# virsh "path" attribute support
 
631
#
 
632
check_config_file()
 
633
{
 
634
        declare path=$1
 
635
 
 
636
        if [ -f "$path/$OCF_RESKEY_name" ]; then
 
637
                echo $path/$OCF_RESKEY_name
 
638
                return 2
 
639
        elif [ -f "$path/$OCF_RESKEY_name.xml" ]; then
 
640
                echo $path/$OCF_RESKEY_name.xml
 
641
                return 2
 
642
        fi
 
643
 
 
644
        return 0
 
645
}
 
646
 
 
647
 
 
648
parse_input()
 
649
{
 
650
        declare delim=$1
 
651
        declare input=$2
 
652
        declare func=$3
 
653
        declare inp
 
654
        declare value
 
655
 
 
656
        while [ -n "$input" ]; do
 
657
                value=${input/$delim*/}
 
658
                if [ -n "$value" ]; then
 
659
                        eval $func $value
 
660
                        if [ $? -eq 2 ]; then
 
661
                                return 0
 
662
                        fi
 
663
                fi
 
664
                inp=${input/$value$delim/}
 
665
                if [ "$input" = "$inp" ]; then
 
666
                        inp=${input/$value/}
 
667
                fi
 
668
                input=$inp
 
669
        done
 
670
}
 
671
 
 
672
 
 
673
search_config_path()
 
674
{
 
675
        declare config_file=$(parse_input ":" "$OCF_RESKEY_path" check_config_file)
 
676
 
 
677
        if [ -n "$config_file" ]; then
 
678
                export OCF_RESKEY_xmlfile=$config_file
 
679
                return 0
 
680
        fi
 
681
 
 
682
        return 1
 
683
}
 
684
 
 
685
 
 
686
choose_management_tool()
 
687
{
 
688
        declare -i is_xml
 
689
 
 
690
        #
 
691
        # Don't override user value for use_virsh if one is given
 
692
        #
 
693
        if [ -n "$OCF_RESKEY_use_virsh" ]; then
 
694
                return 0
 
695
        fi
 
696
 
 
697
        which xmllint &> /dev/null
 
698
        if [ $? -ne 0 ]; then
 
699
                ocf_log warning "Could not find xmllint; assuming virsh mode"
 
700
                export OCF_RESKEY_use_virsh=1
 
701
                unset OCF_RESKEY_path
 
702
                return 0
 
703
        fi
 
704
 
 
705
        xmllint $OCF_RESKEY_xmlfile &> /dev/null
 
706
        is_xml=$?
 
707
 
 
708
        if [ $is_xml -eq 0 ]; then
 
709
                ocf_log debug "$OCF_RESKEY_xmlfile is XML; using virsh"
 
710
                export OCF_RESKEY_use_virsh=1
 
711
                unset OCF_RESKEY_path
 
712
        else
 
713
                ocf_log debug "$OCF_RESKEY_xmlfile is not XML; using xm"
 
714
                export OCF_RESKEY_use_virsh=0
 
715
                unset OCF_RESKEY_xmlfile
 
716
        fi
 
717
 
 
718
        return 0
 
719
}
 
720
 
 
721
 
 
722
 
 
723
validate_all()
 
724
{
 
725
        if [ "$(id -u)" != "0" ]; then
 
726
               ocf_log err "Cannot control VMs. as non-root user."
 
727
               return 1
 
728
        fi
 
729
 
 
730
        #
 
731
        # If someone selects a hypervisor, honor it.
 
732
        # Otherwise, ask virsh what the hypervisor is.
 
733
        #
 
734
        if [ -z "$OCF_RESKEY_hypervisor" ] ||
 
735
           [ "$OCF_RESKEY_hypervisor" = "auto" ]; then
 
736
                export OCF_RESKEY_hypervisor="`virsh version | grep \"Running hypervisor:\" | awk '{print $3}' | tr A-Z a-z`"
 
737
                if [ -z "$OCF_RESKEY_hypervisor" ]; then
 
738
                        ocf_log err "Could not determine Hypervisor"
 
739
                        return $OCF_ERR_ARGS
 
740
                fi
 
741
                echo Hypervisor: $OCF_RESKEY_hypervisor 
 
742
        fi
 
743
 
 
744
        #
 
745
        # Xen hypervisor only for when use_virsh = 0.
 
746
        #
 
747
        if [ "$OCF_RESKEY_use_virsh" = "0" ]; then
 
748
                if [ "$OCF_RESKEY_hypervisor" != "xen" ]; then
 
749
                        ocf_log err "Cannot use $OCF_RESKEY_hypervisor hypervisor without using virsh"
 
750
                        return $OCF_ERR_ARGS
 
751
                fi
 
752
 
 
753
                if [ -n "$OCF_RESKEY_xmlfile" ]; then
 
754
                        ocf_log err "Cannot use xmlfile if use_virsh is set to 0"
 
755
                        return $OCF_ERR_ARGS
 
756
                fi
 
757
        else
 
758
 
 
759
                #
 
760
                # Virsh path support.
 
761
                #
 
762
                if [ -n "$OCF_RESKEY_path" ] &&
 
763
                   [ "$OCF_RESKEY_path" != "/etc/xen" ]; then
 
764
                        if [ -n "$OCF_RESKEY_xmlfile" ]; then
 
765
                                ocf_log warning "Using $OCF_RESKEY_xmlfile instead of searching $OCF_RESKEY_path"
 
766
                        else
 
767
                                search_config_path
 
768
                                if [ $? -ne 0 ]; then
 
769
                                        ocf_log warning "Could not find $OCF_RESKEY_name or $OCF_RESKEY_name.xml in search path $OCF_RESKEY_path"
 
770
                                        unset OCF_RESKEY_xmlfile
 
771
                                else
 
772
                                        ocf_log debug "Using $OCF_RESKEY_xmlfile"
 
773
                                fi
 
774
                                choose_management_tool
 
775
                        fi
 
776
                else
 
777
                        export OCF_RESKEY_use_virsh=1
 
778
                fi
 
779
        fi
 
780
 
 
781
        if [ "$OCF_RESKEY_use_virsh" = "0" ]; then
 
782
 
 
783
                echo "Management tool: xm"
 
784
                which xm &> /dev/null
 
785
                if [ $? -ne 0 ]; then
 
786
                        ocf_log err "Cannot find 'xm'; is it installed?"
 
787
                        return $OCF_ERR_INSTALLED
 
788
                fi
 
789
 
 
790
                if [ "$OCF_RESKEY_hypervisor" != "xen" ]; then
 
791
                        ocf_log err "Cannot use $OCF_RESKEY_hypervisor hypervisor without using virsh"
 
792
                        return $OCF_ERR_ARGS
 
793
                fi
 
794
        else
 
795
                echo "Management tool: virsh"
 
796
                which virsh &> /dev/null
 
797
                if [ $? -ne 0 ]; then
 
798
                        ocf_log err "Cannot find 'virsh'; is it installed?"
 
799
                        return $OCF_ERR_INSTALLED
 
800
                fi
 
801
        fi
 
802
 
 
803
        #
 
804
        # Set the hypervisor URI
 
805
        #
 
806
        if [ -z "$OCF_RESKEY_hypervisor_uri" -o "$OCF_RESKEY_hypervisor_uri" = "auto" ] &&
 
807
           [ "$OCF_RESKEY_use_virsh" = "1" ]; then
 
808
 
 
809
                # Virsh makes it easier to do this.  Really.
 
810
                if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
 
811
                        OCF_RESKEY_hypervisor_uri="qemu:///system"
 
812
                fi
 
813
 
 
814
                # I just need to believe in it more.
 
815
                if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then
 
816
                        OCF_RESKEY_hypervisor_uri="xen:///"
 
817
                fi
 
818
 
 
819
                echo Hypervisor URI: $OCF_RESKEY_hypervisor_uri
 
820
        fi
 
821
 
 
822
        #
 
823
        # Set the migration URI
 
824
        #
 
825
        if [ -z "$OCF_RESKEY_migration_uri" -o "$OCF_RESKEY_migration_uri" = "auto" ] &&
 
826
           [ "$OCF_RESKEY_use_virsh" = "1" ]; then
 
827
 
 
828
                # Virsh makes it easier to do this.  Really.
 
829
                if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
 
830
                        export OCF_RESKEY_migration_uri="qemu+ssh://%s/system"
 
831
                fi
 
832
 
 
833
                # I just need to believe in it more.
 
834
                if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then
 
835
                        export OCF_RESKEY_migration_uri="xenmigr://%s/"
 
836
                fi
 
837
 
 
838
                [ -n "$OCF_RESKEY_migration_uri" ] && echo Migration URI format: $(printf $OCF_RESKEY_migration_uri target_host)
 
839
        fi
 
840
 
 
841
        if [ -z "$OCF_RESKEY_name" ]; then
 
842
                echo No domain name specified
 
843
                return $OCF_ERR_ARGS
 
844
        fi
 
845
 
 
846
        if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
 
847
                export migrateuriopt="tcp:%s"
 
848
        fi
 
849
 
 
850
        #virsh list --all | awk '{print $2}' | grep -q "^$OCF_RESKEY_name\$"
 
851
        return $?
 
852
}
 
853
 
 
854
 
 
855
virsh_migrate()
 
856
{
 
857
        declare target=$1
 
858
        declare rv=1
 
859
 
 
860
        #
 
861
        # Xen and qemu have different migration mechanisms
 
862
        #
 
863
        if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then 
 
864
                cmd="virsh migrate $migrate_opt $OCF_RESKEY_name $OCF_RESKEY_hypervisor_uri $(printf $OCF_RESKEY_migration_uri $target)"
 
865
                ocf_log debug "$cmd"
 
866
                
 
867
                err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]})
 
868
                rv=$?
 
869
        elif [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
 
870
                cmd="virsh migrate $migrate_opt $OCF_RESKEY_name $(printf $OCF_RESKEY_migration_uri $target) $(printf $migrateuriopt $target)"
 
871
                ocf_log debug "$cmd"
 
872
                
 
873
                err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]})
 
874
                rv=$?
 
875
        fi
 
876
 
 
877
        if [ $rv -ne 0 ]; then
 
878
                ocf_log err "Migrate $OCF_RESKEY_name to $target failed:"
 
879
                ocf_log err "$err"
 
880
 
 
881
                if [ "$err" != "${err/does not exist/}" ]; then
 
882
                        return $OCF_ERR_CONFIGURED
 
883
                fi
 
884
                if [ "$err" != "${err/Domain not found/}" ]; then
 
885
                        return $OCF_ERR_CONFIGURED
 
886
                fi
 
887
 
 
888
                return $OCF_ERR_GENERIC
 
889
        fi
 
890
 
 
891
        return $rv
 
892
}
 
893
 
 
894
 
 
895
#
 
896
# XM migrate
 
897
#
 
898
xm_migrate()
 
899
{
 
900
        declare target=$1
 
901
        declare errstr rv migrate_opt cmd
 
902
 
 
903
        rv=1
 
904
 
 
905
        if [ "$OCF_RESKEY_migrate" = "live" ]; then
 
906
                migrate_opt="-l"
 
907
        fi
 
908
 
 
909
        # migrate() function  sets target using migration_mapping;
 
910
        # no need to do it here anymore
 
911
        cmd="xm migrate $migrate_opt $OCF_RESKEY_name $target"
 
912
        ocf_log debug "$cmd"
 
913
 
 
914
        err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]})
 
915
        rv=$?
 
916
 
 
917
        if [ $rv -ne 0 ]; then
 
918
                ocf_log err "Migrate $OCF_RESKEY_name to $target failed:"
 
919
                ocf_log err "$err"
 
920
 
 
921
                if [ "$err" != "${err/does not exist/}" ]; then
 
922
                        return $OCF_NOT_RUNNING
 
923
                fi
 
924
                if [ "$err" != "${err/Connection refused/}" ]; then
 
925
                        return $OCF_ERR_CONFIGURED
 
926
                fi
 
927
 
 
928
                return $OCF_ERR_GENERIC
 
929
        fi
 
930
 
 
931
        return $?
 
932
}
 
933
 
 
934
 
935
# Virsh migrate
 
936
#
 
937
migrate()
 
938
{
 
939
        declare target=$1
 
940
        declare rv migrate_opt
 
941
 
 
942
        if [ "$OCF_RESKEY_migrate" = "live" ]; then
 
943
                migrate_opt="--live"
 
944
        fi
 
945
 
 
946
        # Patch from Marcelo Azevedo to migrate over private
 
947
        # LANs instead of public LANs
 
948
        if [ -n "$OCF_RESKEY_migration_mapping" ] ; then
 
949
                target=${OCF_RESKEY_migration_mapping#*$target:} target=${target%%,*}
 
950
        fi
 
951
 
 
952
        if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
 
953
                virsh_migrate $target
 
954
                rv=$?
 
955
        else
 
956
                xm_migrate $target
 
957
                rv=$?
 
958
        fi
 
959
 
 
960
        return $rv
 
961
}
 
962
 
 
963
 
 
964
wait_start()
 
965
{
 
966
        declare -i timeout_remaining=$(get_timeout)
 
967
        declare -i start_time
 
968
        declare -i end_time
 
969
        declare -i delta
 
970
        declare -i sleep_time
 
971
 
 
972
        if [ -z "$OCF_RESKEY_status_program" ]; then
 
973
                return 0
 
974
        fi
 
975
 
 
976
        while [ $timeout_remaining -gt 0 ]; do
 
977
                start_time=$(date +%s)
 
978
                bash -c "$OCF_RESKEY_status_program"
 
979
                if [ $? -eq 0 ]; then
 
980
                        return 0
 
981
                fi
 
982
                end_time=$(date +%s)
 
983
                delta=$(((end_time - start_time)))
 
984
                sleep_time=$(((5 - delta)))
 
985
 
 
986
                ((timeout_remaining -= $delta))
 
987
                if [ $sleep_time -gt 0 ]; then
 
988
                        sleep $sleep_time
 
989
                        ((timeout_remaining -= $sleep_time))
 
990
                fi
 
991
        done
 
992
 
 
993
        ocf_log err "Start of $OCF_RESOURCE_INSTANCE has failed"
 
994
        ocf_log err "Timeout exceeded while waiting for \"$OCF_RESKEY_status_program\""
 
995
 
 
996
        return 1
 
997
}
 
998
 
 
999
#
 
1000
#
 
1001
#
 
1002
 
 
1003
case $1 in
 
1004
        start)
 
1005
                validate_all || exit $OCF_ERR_ARGS
 
1006
                do_start
 
1007
                rv=$?
 
1008
                if [ $rv -ne 0 ]; then
 
1009
                        exit $rv
 
1010
                fi
 
1011
 
 
1012
                wait_start
 
1013
                exit $?
 
1014
                ;;
 
1015
        stop)
 
1016
                validate_all || exit $OCF_ERR_ARGS
 
1017
                do_stop shutdown destroy
 
1018
                exit $?
 
1019
                ;;
 
1020
        kill)
 
1021
                validate_all || exit $OCF_ERR_ARGS
 
1022
                do_stop destroy
 
1023
                exit $?
 
1024
                ;;
 
1025
        recover|restart)
 
1026
                exit 0
 
1027
                ;;
 
1028
        status|monitor)
 
1029
                validate_all || exit $OCF_ERR_ARGS
 
1030
                echo -n "Virtual machine $OCF_RESKEY_name is "
 
1031
                do_status
 
1032
                rv=$?
 
1033
                if [ $rv -ne 0 ]; then
 
1034
                        exit $rv
 
1035
                fi
 
1036
                [ -z "$OCF_RESKEY_status_program" ] && exit 0
 
1037
                [ -z "$OCF_CHECK_LEVEL" ] && exit 0
 
1038
                [ $OCF_CHECK_LEVEL -lt 10 ] && exit 0
 
1039
 
 
1040
                bash -c "$OCF_RESKEY_status_program" &> /dev/null
 
1041
                exit $?
 
1042
                ;;
 
1043
        migrate)
 
1044
                validate_all || exit $OCF_ERR_ARGS
 
1045
                migrate $2 # Send VM to this node
 
1046
                rv=$?
 
1047
                if [ $rv -eq $OCF_ERR_GENERIC ]; then
 
1048
                        # Catch-all: If migration failed with
 
1049
                        # an unhandled error, do a status check
 
1050
                        # to see if the VM is really dead.
 
1051
                        #
 
1052
                        # If the VM is still in good health, return
 
1053
                        # a value to rgmanager to indicate the 
 
1054
                        # non-critical error
 
1055
                        #
 
1056
                        # OCF states that codes 150-199 are reserved
 
1057
                        # for application use, so we'll use 150
 
1058
                        #
 
1059
                        do_status > /dev/null
 
1060
                        if [ $? -eq 0 ]; then
 
1061
                                rv=150
 
1062
                        fi
 
1063
                fi
 
1064
                exit $rv
 
1065
                ;;
 
1066
        reload)
 
1067
                exit 0
 
1068
                ;;
 
1069
        reconfig)
 
1070
                validate_all || exit $OCF_ERR_ARGS
 
1071
                echo "$0 RECONFIGURING $OCF_RESKEY_memory"
 
1072
                reconfigure
 
1073
                exit $?
 
1074
                ;;
 
1075
        meta-data)
 
1076
                meta_data
 
1077
                exit 0
 
1078
                ;;
 
1079
        validate-all)
 
1080
                validate_all
 
1081
                exit $?
 
1082
                ;;
 
1083
        *)
 
1084
                echo "usage: $0 {start|stop|restart|status|reload|reconfig|meta-data|validate-all}"
 
1085
                exit 1
 
1086
                ;;
 
1087
esac