source: src-sh/lpreserver/lpreserver

Last change on this file was 731f0cc, checked in by Kris Moore <kris@…>, 2 weeks ago

Fix a bug with 'lpreserver replicate remove' not cleaning up the
replication DB file

  • Property mode set to 100755
File size: 16.1 KB
Line 
1#!/bin/sh
2# Command-line interaction script for life-preserver
3# Author: Kris Moore
4# License: BSD
5# "Life-Preserver" Copyright 2013 PC-BSD Software (iXsystems)
6######################################################################
7
8# Source external functions
9. /usr/local/share/pcbsd/scripts/functions.sh
10
11# Set a default pager
12PAGER=${PAGER:-more}
13
14require_root() 
15{
16  UTEST="`whoami`"
17  if [ "$UTEST" != "root" ] ; then
18     exit_err "This command must be run as root!"
19  fi
20}
21
22# Source our functions
23PROGDIR="/usr/local/share/lpreserver"
24
25# Source our local functions
26. ${PROGDIR}/backend/functions.sh
27
28title()
29{
30  echo "Life-Preserver
31---------------------------------"
32};
33
34
35# Function to display help information
36help_main()
37{
38  title
39
40cat<<__EOF__
41Available commands
42
43Type in help <command> for information and usage about that command
44
45       help - This help file or the help for the specified command
46
47   cronsnap - Schedule snapshot creation via cron
48  cronscrub - Schedule scrub via cron
49        get - Get list of lpreserver options
50   listcron - Listing of scheduled snapshots and scrubs
51   listsnap - List snapshots of a zpool/dataset
52     mksnap - Create a ZFS snapshot of a zpool/dataset
53  replicate - Sub-command of replication tasks
54 revertsnap - Revert zpool/dataset to a snapshot
55     rmsnap - Remove a snapshot
56        set - Set lpreserver options
57     status - List datasets, along with last snapshot / replication date
58      zpool - Manage a zpool by attaching / detaching disks
59__EOF__
60};
61
62help_zpool()
63{
64 title
65 echo "Help zpool
66
67Life-Preserver zpool sub-system
68
69The 'zpool' sub-command allows you to attach / detach drives to a zpool,
70as well as get status and more.
71
72When a drive is first attached to a zpool, it will be re-formatted with
73a new gpart layout and made bootable with GRUB. For this reason the disk
74must be the same size, or larger, than the first array disk SWAP + ZFS
75partition size.
76
77Available Flags:
78        list - List zpool disks
79      attach - Attach a new zpool disk
80      detach - Remove a zpool disk
81     offline - Mark a disk as offline
82      online - Mark a disk as being online again
83
84Attach Options:
85
86        attach <zpool> <new disk>
87
88        Example 1:
89
90        attach tank1 /dev/da0
91
92        Attach the disk /dev/da0 to tank1 pool. The disk will be
93        auto-partioned with a SWAP / ZFS partition and made bootable.
94
95Detach Options:
96
97        detach <zpool> <disk>
98       
99        Detach a disk from the zpool
100
101        Use 'zpool list' for a list of available disks
102
103Offline Options:
104
105        offline <zpool> <disk> 
106       
107        Mark a disk in the zpool array as 'offline', should be when you
108        want to unplug a device, and anticipate plugging it back in later.
109
110Online Options:
111
112        online <zpool> <disk>   
113       
114        Mark an offline disk in the array as online again. The disk will begin
115        to resilver again automatically.
116
117List Options:
118
119        list <zpool>
120       
121        Lists the connected disks of a zpool
122
123Usage:
124
125  lpreserver zpool <subcmd> <flags>
126
127Example:
128
129  lpreserver zpool list tank1
130"
131};
132
133help_replicate()
134{
135 title
136 echo "Help replicate
137
138Life-Preserver replication sub-system
139
140Replication uses ZFS to send your snapshots to a remote system which also has
141a ZFS pool, such as FreeNAS or another PC-BSD system. The <hostdataset> must
142also be scheduled for snapshots for replication to occur.
143
144On the remote system, you will need to have created the <remotedataset>
145beforehand.
146
147If you plan to replicate to a non-root user, please set the following
148permissions on the remote dataset:
149
150# zfs allow -u <user> \\
151  atime,canmount,clone,compression,create,destroy,hold,mount,mountpoint,promote,receive,rename,send,userprop <remotedataset>
152
153Usage:
154
155  lpreserver replicate <subcmd> <flags>
156
157
158Available Flags:
159
160         add - Add a new replication target
161      expand - Expand the remote iscsi zpool
162      export - Export / Offline an iSCSI zpool
163      import - Import / Online an iSCSI zpool
164        init - Initialize the remote side again
165        list - List replication targets
166      remove - Remove a replication target
167         run - Start a replication manually
168   saveiscsi - Save the iSCSI config data / GELI key
169
170
171add Options:
172
173        add <remotehost> <user> <port> <hostdataset> <remotedataset> <time>
174       
175        add iscsi <*.lps file> <hostdataset> <time> [geli key]
176
177        add iscsi <*.lpiscsi file> <hostdataset> <time> [password file]
178
179        <time> = XX/sync/hour/30min/10min/manual
180            XX= Time to perform replication (in 24 notation)
181          sync= Do replication with snaps (Not recommended for frequent snaps)
182          hour= Replicate hourly
183         30min= Replicate every 30 minutes
184         10min= Replicate every 10 minutes
185        manual= Only replicate when requested by user
186
187        Example 1:
188
189        add freenas.8343 backupuser 22 tank1 tankbackup/backups sync
190
191        Will schedule replication of tank1 to tankbackup/backups with
192        each snapshot
193
194        Example 2:
195
196        add freenas.8343 backupuser 22 tank1 tankbackup/backups 22
197
198        Will schedule replication of tank1 to tankbackup/backups at 10PM,
199        notated in 24hour time
200
201expand Options:
202
203        expand <localdataset/zpool> <target host>
204
205        Will expand the iSCSI-hosted zpool to the new size of the remote volume.
206        For obvious reasons, this should only be done after the remote host has
207        increased the size of the remote iSCSI volume.
208
209        NOTE: This can only be used to grow a zpool, shrinking is not permitted.
210
211export Options:
212
213        export <localdataset/zpool> <target host>
214
215        Exports the backup iSCSI zpool associated with the local dataset or
216        zpool replication specified for <target host>
217
218import Options:
219
220        import <localdataset/zpool> <target host>
221
222        Imports the backup iSCSI zpool associated with the local dataset or
223        zpool replication specified for <target host>
224
225
226init Options:
227
228        init <localdataset/zpool> <target host>
229
230        Will re-init the remote side of the replication. This can be useful
231        when your replication gets stuck. Doing this option will remove
232        all the data on the remote side, and require a full re-sync again.
233
234remove Options:
235
236        remove <dataset> <target host>
237       
238        Remove a replication task indicated by <dataset>
239        Use 'replicate list' for a list of IDs.
240
241run Options:
242
243        run <dataset> <target host>
244
245        Starts a manual replication for <dataset> streaming to <target host>
246
247saveiscsi options:
248
249        saveiscsi <localdataset/zpool> <target host> [password file]
250
251        Creates a GELI encrypted file, which contains all the iSCSI connection
252        information and GELI key for the replication target. Will prompt for
253        the password to set on this GELI encrypted file.
254
255        This file can then be used with the "replicate add" command to import
256        the backup zpool on another system or from the PC-BSD install media.
257
258Examples:
259
260  # lpreserver replicate run tank1 freenas.example.org
261
262 
263  # lpreserver replicate init tank1 freenas.example.org
264
265" | $PAGER
266};
267
268
269help_set()
270{
271 title
272 echo "Help set
273
274Set Life-Preserver options
275
276Usage:
277
278  lpreserver set
279
280Config options
281
282     duwarn - Set to a disk percentage [0-99] at which to warn of low disk space
283
284      email - Set the e-mail address to receive notifications
285                This will require that the \"mail\" command is setup for outgoing mail
286
287  emailopts - (ALL/WARN/ERROR)
288                  ALL - Send mail for every snapshot, plus warnings and errors
289                 WARN - Send mail for warnings and errors (Default)
290                ERROR - Send mail for errors only
291
292  recursive - (ON/OFF)
293                   ON - Will create / destroy snapshots recursively, for all children of
294                        a target zpool/dataset. (Default)
295                  OFF - Will only create / destroy snapshots on the specified dataset. 
296
297Example:
298
299  lpreserver set email "kris@example.org,admin@example.org"
300
301  lpreserver set emailopts ALL
302"
303};
304
305help_get()
306{
307 title
308 echo "Help get
309
310Listing of Life-Preserver options set
311
312Usage:
313
314  lpreserver get
315
316Example:
317
318  lpreserver get
319"
320};
321
322help_listcron()
323{
324 title
325 echo "Help listcron
326
327List scheduled cron snapshots and scrubs
328
329Usage:
330
331  lpreserver listcron <scrub|snap>
332
333Exmaple:
334
335  lpreserver listcron snap
336
337  or
338
339  lpreserver listcron scrub
340 
341  (NOTE: Empty argument list shows both scheduled snapshots
342  and scrubs.)
343
344"
345};
346
347help_status()
348{
349 title
350 echo "Help status
351
352List monitored dataset's last snapshot and replication
353
354Usage:
355
356  lpreserver status
357
358"
359};
360
361
362help_listsnap()
363{
364 title
365 echo "Help listsnap
366
367List ZFS snapshots of a dataset
368
369Usage:
370
371  lpreserver listsnap <dataset>
372
373Example:
374
375  lpreserver listsnap tank0/usr/home/kris
376"
377};
378
379help_cronsnap()
380{
381 title
382 echo "Help cronsnap
383
384Schedule a ZFS snapshot
385
386Usage:
387
388  For a listing of all scheduled snapshots
389
390  # lpreserver listcron
391
392  or
393
394  To start / stop snapshot scheduling
395
396  # lpreserver cronsnap <dataset> <action> <frequency> <numToKeep>
397 
398  action = start / stop
399  frequency = auto / daily@XX / hourly / 30min / 10min / 5min
400                           ^^ Hour to execute
401  numToKeep = Number of snapshots to keep total
402
403  NOTE: When frequency is set to "auto" the following will take place:
404    * Snapshots will be created every 5 minutes and kept for an hour.
405    * A hourly snapshot will be kept for a day.
406    * A daily snapshot will be kept for a month.
407    * A Monthly snapshot will be kept for a year.
408    * The life-preserver daemon will also keep track of the zpool disk space,
409      if the capacity falls below 75%, the oldest snapshot will be auto-pruned.
410
411Example:
412
413  lpreserver cronsnap tank1/usr/home/kris start daily@22 10
414
415  or
416
417  lpreserver cronsnap tank1/usr/home/kris stop
418"
419};
420
421help_cronscrub()
422{
423 title
424 echo "Help cronscrub
425
426Schedule a ZFS scrub
427
428Usage:
429
430  For a listing of all scheduled scrubs
431
432  # lpreserver listcron
433
434  or
435
436  To start / stop scrub scheduling
437
438  # lpreserver cronscrub <dataset> <action> <frequency>
439 
440  action = start / stop
441  frequency = daily@XX / weekly@YY@XX / monthly@ZZ@XX
442      XX = Hour to execute, YY = Day of week to execute, ZZ = Day of month
443
444  NOTE:
445   
446    If 'daily' is given without hour the default is 22.
447    If 'weekly' is given without day or hour the default is day 1 and hour 22.
448    (1 = Mon, 7 = Sun)
449    If 'monthly' is given without day or hour the default is day 1 and hour 22.
450
451Example:
452
453  lpreserver cronscrub tank1 start daily@22
454  (run scrub everyday at 10 AM)
455
456  or
457
458  lpreserver cronscrub tank1 start weekly@5@5
459  (run scrub every Friday at 5 PM)
460
461  or
462
463  lpreserver cronscrub tank1 start monthly@21@13
464  (run scrub on the 21:st every month at 1 AM)
465
466  or
467
468  lpreserver cronscrub tank1 stop
469"
470};
471
472help_revertsnap()
473{
474 title
475 echo "Help revertsnap
476
477Revert ZFS to a snapshot of a dataset
478
479Usage:
480
481  lpreserver revertsnap <dataset> <SNAP>
482
483Example:
484
485  lpreserver revertsnap tank1/usr/home/kris 20130729-140510
486"
487};
488
489help_rmsnap()
490{
491 title
492 echo "Help rmsnap
493
494Remove ZFS snapshot of a dataset
495
496Usage:
497
498  lpreserver rmsnap <dataset> <SNAP>
499
500Example:
501
502  lpreserver rmsnap tank1/usr/home/kris 20130729-140510
503
504NOTE:
505By default snapshots are recursive and will remove snapshots
506of all children datasets automatically. To change this use:
507
508# lpreserver set recursive off
509"
510};
511
512
513help_mksnap()
514{
515 title
516 echo "Help mksnap
517
518Create a new ZFS snapshot of a dataset
519
520Usage:
521
522  lpreserver mksnap <dataset> <snapshotname> <comment>
523
524Example:
525
526  lpreserver mksnap tank1/usr/home/kris mysnapshot
527
528  or
529
530  lpreserver mksnap tank1/usr/home/kris mysnapshot \"Added user bob\"
531
532NOTE:
533By default snapshots are recursive and will create snapshots
534of all children datasets automatically. To change this use:
535
536# lpreserver set recursive off
537"
538};
539
540check_migrate()
541{
542   # Check if we need to update the flags on replication to new format
543   if [ ! -e "${DBDIR}/.replicationng" -a -e "${REPCONF}" ] ; then
544     echo "Updating replication tag system..."
545     echo "Please be patient, this is only done once..."
546     while read repLine
547     do
548       local LDATA=`echo $repLine | cut -d ':' -f 1`
549       local REPHOST=`echo $repLine | cut -d ':' -f 3`
550
551       local lastSEND=`zfs get -d 1 backup:lpreserver ${LDATA} | grep LATEST | awk '{$1=$1}1' OFS=" " | tail -1 | cut -d '@' -f 2 | cut -d ' ' -f 1`
552
553       if [ -z "$lastSEND" ] ; then continue ; fi
554
555       # Remove the old flag format and set the new one
556       zfs set backup:lpreserver=' ' ${LDATA}@${lastSEND}
557       zfs set lpreserver:${REPHOST}=LATEST ${LDATA}@${lastSEND}
558
559     done < ${REPCONF}
560
561     # Touch our marker so we don't need to do this again
562     touch "${DBDIR}/.replicationng"
563   fi
564
565   # Put other migration functionality as needed here
566}
567
568# Check if we need to enable the zfs monitor
569enable_watcher
570
571# See if we need to upgrade flags on replication
572check_migrate
573
574# Check what the user wants to do
575case "$1" in
576
577   help) case "$2" in
578           get) help_get ;;
579           set) help_set ;;
580           mksnap) help_mksnap ;;
581           listcron) help_listcron ;;
582           listsnap) help_listsnap ;;
583           revertsnap) help_revertsnap ;;
584           zpool) help_zpool ;;
585           replicate) help_replicate ;;
586           cronsnap) help_cronsnap ;;
587           cronscrub) help_cronscrub ;;
588           rmsnap) help_rmsnap ;;
589           status) help_status ;;
590           *) help_main ;;
591         esac  ;;
592
593    get) require_root
594         # Display our options 
595         title
596         echo "      Recursive mode: $RECURMODE"
597         echo "E-mail notifications: $EMAILMODE"
598         echo "    E-mail addresses: $EMAILADDY"
599         echo "  Disk space warn at: ${DUWARN}%"
600         exit 0
601         ;;
602
603    set) require_root
604         OPT="${2}" 
605
606         case $OPT in
607        emailopts) case $3 in
608                  ALL|WARN|ERROR) echo "E-Mail mode set to: $3" 
609                                  echo "$3" > ${DBDIR}/emaillevel ;;
610                     *) exit_err "Unknown option" ;;
611                   esac
612                   ;;
613            email) echo "Setting email notification to: $3" 
614                   echo "$3" > ${DBDIR}/emails ;;
615           duwarn) if [ ! $(is_num "$3") ] ; then exit_err "Invalid number, must be 0-99"; fi
616                   echo "Setting disk warning capacity to: ${3}%" 
617                   echo "$3" > ${DBDIR}/duwarn ;;
618        recursive) case $3 in
619                  OFF|Off|off)  echo "Recursive mode disabled" 
620                                touch ${DBDIR}/recursive-off ;;
621                     ON|On|on)  echo "Recursive mode enabled" 
622                                rm ${DBDIR}/recursive-off 2>/dev/null ;;
623                     *) exit_err "Unknown option" ;;
624                   esac
625                   ;;
626                *) exit_err "Invalid option!" ;;
627           esac
628         ;;
629
630   mksnap) require_root
631         DATASET="$2"
632         SNAPNAME="$3"
633         COMMENT="$4"
634         ${PROGDIR}/backend/zfsmksnap.sh "${DATASET}" "$SNAPNAME" "$COMMENT"
635         ;;
636
637 listcron) 
638         if [ -z "$2" ]; then
639             ${PROGDIR}/backend/zfslistcron.sh
640             exit 0
641         fi
642         case ${2} in
643             snap) ${PROGDIR}/backend/zfslistcron.sh snap;;
644             scrub) ${PROGDIR}/backend/zfslistcron.sh scrub;;
645             *) help_listcron;;
646         esac
647         ;;
648       
649 listsnap) require_root
650         DATASET="$2"
651         ${PROGDIR}/backend/zfslistsnap.sh "${DATASET}"
652         ;;
653
654 cronsnap) require_root
655         DATASET="$2"
656         ${PROGDIR}/backend/zfscronsnap.sh "${DATASET}" "$3" "$4" "$5"
657         ;;
658
659cronscrub) require_root
660         DATASET="$2"
661         ${PROGDIR}/backend/zfscronscrub.sh "${DATASET}" "$3" "$4"
662         ;;
663
664revertsnap) require_root
665         DATASET="$2"
666         SNAP="$3"
667         ${PROGDIR}/backend/zfsrevertsnap.sh "${DATASET}" "$SNAP"
668         ;;
669
670    rmsnap) require_root
671         DATASET="$2"
672         SNAP="$3"
673         ${PROGDIR}/backend/zfsrmsnap.sh "${DATASET}" "${SNAP}"
674         ;;
675    status) listStatus
676         ;;
677 replicate) shift
678            case ${1} in
679                add) require_root ;
680                     if [ "$2" = "iscsi" ] ; then
681                       add_rep_iscsi_task "$3" "$4" "$5" "$6"
682                     else
683                       add_rep_task "$2" "$3" "$4" "$5" "$6" "$7"
684                     fi
685                     ;;
686                expand) require_root ; expand_iscsi_zpool "$2" "$3" ;;
687                export) require_root ; export_iscsi_zpool "$2" "$3" ;;
688                import) require_root ; import_iscsi_zpool "$2" "$3" ;;
689                init) require_root ; init_rep_task "$2" "$3" ;;
690                list) list_rep_task ;;
691                remove) require_root
692                        cat ${REPCONF} | grep -q "^${2}:" 
693                        if [ $? -eq 0 ] ; then
694                           rem_rep_task "$2" "$3"
695                           echo "Removed replication task for $2"
696                        else
697                           exit_err "No such replication task for dataset $2"
698                        fi
699                        ;;
700                 run) require_root ;
701                      ${PROGDIR}/backend/runrep.sh "$2" "$3"
702                      exit $?
703                      ;;
704                saveiscsi) require_root ; save_iscsi_zpool_data "$2" "$3" "$4" ;;
705                *) help_replicate ;;
706            esac
707         ;;
708    zpool) require_root
709            shift
710            case ${1} in
711                attach) add_zpool_disk "$2" "$3" ;;
712                detach) rem_zpool_disk "$2" "$3" ;;
713                online) online_zpool_disk "$2" "$3" ;;
714               offline) offline_zpool_disk "$2" "$3" ;;
715                list) list_zpool_disks "$2" ;;
716                *) help_zpool ;;
717            esac
718         ;;
719   *) help_main ;;
720esac
721
722exit 0
Note: See TracBrowser for help on using the repository browser.