Print this page
XXX Remove nawk(1)
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/brand/shared/zone/uninstall.ksh
+++ new/usr/src/lib/brand/shared/zone/uninstall.ksh
1 1 #
2 2 # CDDL HEADER START
3 3 #
4 4 # The contents of this file are subject to the terms of the
5 5 # Common Development and Distribution License (the "License").
6 6 # You may not use this file except in compliance with the License.
7 7 #
8 8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 # or http://www.opensolaris.org/os/licensing.
10 10 # See the License for the specific language governing permissions
11 11 # and limitations under the License.
12 12 #
13 13 # When distributing Covered Code, include this CDDL HEADER in each
14 14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 # If applicable, add the following below this CDDL HEADER, with the
16 16 # fields enclosed by brackets "[]" replaced with your own identifying
17 17 # information: Portions Copyright [yyyy] [name of copyright owner]
18 18 #
19 19 # CDDL HEADER END
20 20 #
21 21 #
22 22 # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 23 #
24 24
25 25 #
26 26 # get script name (bname)
27 27 #
28 28 bname=`basename $0`
29 29
30 30 #
31 31 # common shell script functions
32 32 #
33 33 . /usr/lib/brand/shared/common.ksh
34 34
35 35 #
36 36 # error messages
37 37 #
38 38 m_usage=$(gettext "Usage: %s: [-hFn]")
39 39
40 40 m_1_zfs_promote=$(gettext "promoting '%s'.")
41 41 m_1_zfs_destroy=$(gettext "destroying '%s'.")
42 42 m_2_zfs_rename=$(gettext "renaming '%s' to '%s'.")
43 43 m_3_zfs_set=$(gettext "setting property %s='%s' for '%s'.")
44 44 m_rm_r=$(gettext "recursively deleting '%s'.")
45 45 m_rm=$(gettext "deleting '%s'.")
46 46
47 47 w_no_ds=$(gettext "Warning: no zonepath dataset found.")
48 48
49 49 f_usage_err=$(gettext "Error: invalid usage")
50 50 f_abort=$(gettext "Error: internal error detected, aborting.")
51 51 f_1_zfs_promote=$(gettext "Error: promoting ZFS dataset '%s'.")
52 52 f_2_zfs_rename=$(gettext "Error: renaming ZFS dataset '%s' to '%s'.")
53 53 f_3_zfs_set=$(gettext "Error: setting ZFS propery %s='%s' for '%s'.")
54 54 f_1_zfs_destroy=$(gettext "Error: destroying ZFS dataset.")
55 55 f_2_zfs_get=$(gettext "Error: reading ZFS dataset property '%s' from '%s'.")
56 56 f_user_snap=$(gettext "Error: user snapshot(s) detected.")
57 57 f_stray_snap=$(gettext "Error: uncloned snapshot(s) detected.")
58 58 f_stray_clone=$(gettext "Error: cloned zone datasets found outsize of zone.")
59 59 f_rm_snap=$(gettext "Error: please delete snapshot(s) and retry uninstall.")
60 60 f_rm_clone=$(gettext "Error: please delete clone(s) and retry uninstall.")
61 61 f_iu_clone=$(gettext "Error: cloned zone dataset(s) in use.")
62 62 f_dis_clone=$(gettext "Error: please stop using clone(s) and retry uninstall.")
63 63
64 64 #
65 65 # functions
66 66 #
67 67 print_array()
68 68 {
69 69 typeset -n pa_array=$1
70 70
71 71 (( pa_i = 0 ))
72 72 while (( $pa_i < ${#pa_array[@]} )); do
73 73 printf "\t${pa_array[$pa_i]}\n"
74 74 (( pa_i = $pa_i + 1 ))
75 75 done
76 76 }
77 77
78 78 usage()
79 79 {
80 80 printf "$m_usage\n" "$bname"
81 81 exit $ZONE_SUBPROC_USAGE
82 82 }
83 83
84 84 usage_err()
85 85 {
86 86 printf "$f_usage_err\n" >&2
87 87 usage >&2
88 88 }
89 89
90 90 rm_zonepath()
91 91 {
92 92 # cleanup stuff we know about and leave any user data alone
93 93
94 94 [[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
95 95 printf "$m_rm\n" "$zonepath/SUNWattached.xml"
96 96 $nop /bin/rm -f "$zonepath/SUNWattached.xml"
97 97
98 98 [[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
99 99 printf "$m_rm_r\n" "$zonepath/lu"
100 100 $nop /bin/rm -rf "$zonepath/lu"
101 101
102 102 [[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
103 103 printf "$m_rm_r\n" "$zonepath/dev"
104 104 $nop /bin/rm -rf "$zonepath/dev"
105 105
106 106 [[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
107 107 printf "$m_rm_r\n" "$zonepath/root"
108 108 $nop /bin/rm -rf "$zonepath/root"
109 109
110 110 [[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
111 111 printf "$m_rm\n" "$zonepath"
112 112 $nop /bin/rmdir "$zonepath" 2>/dev/null
113 113 }
114 114
115 115 zfs_destroy()
116 116 {
117 117 zd_fs1="$1"
118 118
119 119 # first figure out if the target fs has an origin snapshot
120 120 zd_origin=`/sbin/zfs get -H -o value origin "$zd_fs1"`
121 121 if [[ $? != 0 ]]; then
122 122 printf "$f_2_zfs_get\n" origin "$zd_fs1" >&2
123 123 exit $ZONE_SUBPROC_FATAL
124 124 fi
125 125
126 126 [[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
127 127 printf "$m_1_zfs_destroy\n" "$zd_fs1"
128 128
129 129 #
130 130 # note that we specify the '-r' flag so that we destroy any
131 131 # descendants (filesystems and snapshot) of the specified
132 132 # filesystem.
133 133 #
134 134 $nop /sbin/zfs destroy -r "$zd_fs1"
135 135 if [[ $? != 0 ]]; then
136 136 printf "$f_1_zfs_destroy\n" "$zd_fs1" >&2
137 137 exit $ZONE_SUBPROC_FATAL
138 138 fi
139 139
140 140 [[ "$zd_origin" == "-" ]] && return
141 141
142 142 [[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
143 143 printf "$m_1_zfs_destroy\n" "$zd_origin"
144 144
145 145 $nop /sbin/zfs destroy "$zd_origin" 2>/dev/null
146 146 #
147 147 # we ignore errors while trying to destroy the origin since
148 148 # the origin could have been used as the source for other
149 149 # clones
150 150 #
151 151 }
152 152
153 153 zfs_promote()
154 154 {
155 155 zp_fs1="$1"
156 156
157 157 [[ -z "$opt_n" ]] &&
158 158 printf "$m_1_zfs_promote\n" "$zp_fs1"
159 159
160 160 $nop /sbin/zfs promote "$zp_fs1"
161 161 if [[ $? != 0 ]]; then
162 162 printf "$f_1_zfs_promote\n" "$zp_fs1" >&2
163 163 exit $ZONE_SUBPROC_FATAL
164 164 fi
165 165 }
166 166
167 167 zfs_rename()
168 168 {
169 169 zr_fs1="$1"
170 170 zr_fs2="$2"
171 171
172 172 [[ -z "$opt_n" ]] &&
173 173 printf "$m_2_zfs_rename\n" "$zr_fs1" "$zr_fs2"
174 174
175 175 $nop /sbin/zfs rename "$zr_fs1" "$zr_fs2"
176 176 if [[ $? != 0 ]]; then
177 177 printf "$f_2_zfs_rename\n" "$zr_fs1" "$zr_fs2" >&2
178 178 return 1
179 179 fi
180 180 return 0
181 181 }
182 182
183 183 zfs_set()
184 184 {
185 185 zs_prop=$1
186 186 zs_value=$2
187 187 zs_fs1=$3
188 188
189 189 [[ -z "$opt_n" ]] && [[ -n "$opt_v" ]] &&
190 190 printf "$m_3_zfs_set\n" "$zs_prop" "$zs_value" "$zs_fs1"
191 191
192 192 $nop /sbin/zfs set "$zs_prop"="$zs_value" "$zs_fs1"
193 193 if [[ $? != 0 ]]; then
194 194 printf "$f_3_zfs_set\n" "$zs_prop" "$zs_value" "$zs_fs1"
195 195 return 1
196 196 fi
197 197 return 0
198 198 }
199 199
200 200 zfs_set_array()
201 201 {
202 202 zsa_prop=$1
203 203 zsa_value=$2
204 204 typeset -n zsa_array=$3
205 205 zsa_ignore_errors=$4
206 206
207 207 (( zsa_i = 0 ))
208 208 while (( $zsa_i < ${#zsa_array[@]} )); do
209 209 zfs_set "$zsa_prop" "$zsa_value" "${zsa_array[$zsa_i]}"
210 210 [[ $? != 0 ]] && [[ -z "$zsa_ignore_errors" ]] &&
211 211 return 1
212 212 (( zsa_i = $zsa_i + 1 ))
213 213 done
214 214 return 0
215 215 }
216 216
217 217
218 218 (( snap_rename_zbe_i = 1 ))
219 219 (( snap_rename_snap_i = 1 ))
220 220 snap_rename_init()
221 221 {
222 222 (( snap_rename_zbe_i = 1 ))
223 223 (( snap_rename_snap_i = 1 ))
224 224 }
225 225
226 226 snap_rename()
227 227 {
228 228 eval sr_fs=\${$1}
229 229 eval sr_snap=\${$2}
230 230
231 231 if [[ "$sr_snap" == ~(Elr)(zbe-[0-9][0-9]*) ]]; then
232 232 sr_snap="zbe-$snap_rename_zbe_i"
233 233 (( snap_rename_zbe_i = $snap_rename_zbe_i + 1 ))
234 234 elif [[ "$sr_snap" == ~(Er)(_snap[0-9]*) ]]; then
235 235 sr_snap=${sr_snap##~(Er)([0-9]*)}
236 236 sr_snap="${sr_snap}${snap_rename_snap_i}"
237 237 (( snap_rename_snap_i = $snap_rename_snap_i + 1 ))
238 238 else
239 239 printf "$f_user_snap\n" >&2
240 240 printf "\t$sr_fs@$sr_snap\n" >&2
241 241 printf "$f_rm_snap\n" >&2
↓ open down ↓ |
241 lines elided |
↑ open up ↑ |
242 242 exit $ZONE_SUBPROC_FATAL
243 243 fi
244 244
245 245 eval $2="$sr_snap"
246 246 }
247 247
248 248 # find the dataset associated with $zonepath
249 249 uninstall_get_zonepath_ds()
250 250 {
251 251 ZONEPATH_DS=`/sbin/zfs list -t filesystem -o name,mountpoint | \
252 - /bin/nawk -v zonepath=$zonepath '{
252 + /usr/xpg4/bin/awk -v zonepath=$zonepath '{
253 253 if ($2 == zonepath)
254 254 print $1
255 255 }'`
256 256
257 257 if [ -z "$ZONEPATH_DS" ]; then
258 258 # there is no $zonepath dataset
259 259 rm_zonepath
260 260 exit $ZONE_SUBPROC_OK
261 261 fi
262 262 }
263 263
264 264 # find the dataset associated with $ZONEPATH_DS/ROOT
265 265 uninstall_get_zonepath_root_ds()
266 266 {
267 267 ZONEPATH_RDS=`/sbin/zfs list -H -t filesystem -o name \
268 268 $ZONEPATH_DS/ROOT 2>/dev/null`
269 269
270 270 if [ -z "$ZONEPATH_RDS" ]; then
271 271 # there is no $ZONEPATH_DS/ROOT dataset
272 272 c=`/sbin/zfs list -H -t filesystem -r $ZONEPATH_DS | wc -l`
273 273 if [ $c = 1 ]; then
274 274 # $zonepath dataset has no descendents
275 275 zfs_destroy "$ZONEPATH_DS"
276 276 fi
277 277 rm_zonepath
278 278 exit $ZONE_SUBPROC_OK
279 279 fi
280 280 }
281 281
282 282 destroy_zone_dataset()
283 283 {
284 284 fs=$1
285 285
286 286 pool=${fs%%/*}
287 287
288 288 # Fastpath. if there are no snapshots of $fs then just delete it.
289 289 c=`/sbin/zfs list -H -t snapshot -o name -r $fs | grep "^$fs@" |
290 290 LC_ALL=C LANG=C wc -l`
291 291 if (( $c == 0 )) ; then
292 292 zfs_destroy "$fs"
293 293 return
294 294 fi
295 295
296 296 #
297 297 # This zone BE has snapshots. This can happen if a zone has
298 298 # multiple BEs (in which case we have snapshots named "zbe-XXX"),
299 299 # if this zone has been used as the source for a clone of
300 300 # another zone (in which case we have snapshots named
301 301 # "XXX_snap"), or if an administrator has been doing manual
302 302 # snapshotting.
303 303 #
304 304 # To be able to destroy this dataset (which we'll call the
305 305 # origin) we need to get rid of all it's snapshots. The "easiest"
306 306 # way to do this is to:
307 307 #
308 308 # - delete any uncloned origin snapshots
309 309 # - find the oldest clone of the youngest origin snapshot (which
310 310 # we'll call the oldest clone)
311 311 # - check if there are any snapshots naming conflicts between
312 312 # the origin and the oldest clone.
313 313 # - if so, find any clones of those conflicting origin snapshots
314 314 # - make sure that those clones are not zoned an in-use.
315 315 # - if any of those clones are zoned, unzone them.
316 316 # - rename origin snapshots to eliminate naming conflicts
317 317 # - for any clones that we unzoned, rezone them.
318 318 # - promote the oldest clone
319 319 # - destroy the origin and all it's descendants
320 320 #
321 321
322 322 #
323 323 # Get a list of all the cloned datasets within the zpool
324 324 # containing the origin filesystem. Filter out any filesystems
325 325 # that are descendants of origin because we are planning to
326 326 # destroy them anyway.
327 327 #
328 328 unset clones clones_origin
329 329 (( clones_c = 0 ))
330 330 pool=${fs%%/*}
331 331 LANG=C LC_ALL=C /sbin/zfs list -H -t filesystem -s creation \
332 332 -o name,origin -r "$pool" |
333 333 while IFS=" " read name origin; do
334 334
335 335 # skip non-clone filesystems
336 336 [[ "$origin" == "-" ]] &&
337 337 continue
338 338
339 339 # skip desendents of the origin we plan to destroy
340 340 [[ "$name" == ~()(${fs}/*) ]] &&
341 341 continue
342 342
343 343 # record this clone and it's origin
344 344 clones[$clones_c]="$name"
345 345 clones_origin[$clones_c]="$origin"
346 346 (( clones_c = $clones_c + 1 ))
347 347 done
348 348
349 349 #
350 350 # Now do a sanity check. Search for clones of a child datasets
351 351 # of the dataset we want to destroy, that are not themselves
352 352 # children of the dataset we're going to destroy). This should
353 353 # really never happen unless the global zone admin has cloned a
354 354 # snapshot of a zone filesystem to a location outside of that
355 355 # zone. bad admin...
356 356 #
357 357 unset stray_clones
358 358 (( stray_clones_c = 0 ))
359 359 (( j = 0 ))
360 360 while (( $j < $clones_c )); do
361 361 # is the clone origin a descendant of $fs?
362 362 if [[ "${clones_origin[$j]}" != ~()(${fs}/*) ]]; then
363 363 # we don't care.
364 364 (( j = $j + 1 ))
365 365 continue
366 366 fi
367 367 stray_clones[$stray_clones_c]=${clones[$j]}
368 368 (( stray_clones_c = $stray_clones_c + 1 ))
369 369 (( j = $j + 1 ))
370 370 done
371 371 if (( stray_clones_c > 0 )); then
372 372 #
373 373 # sigh. the admin has done something strange.
374 374 # tell them to clean it up and retry.
375 375 #
376 376 printf "$f_stray_clone\n" >&2
377 377 print_array stray_clones >&2
378 378 printf "$f_rm_clone\n" >&2
379 379 exit $ZONE_SUBPROC_FATAL
380 380 fi
381 381
382 382 # Find all the snapshots of the origin filesystem.
383 383 unset s_origin
384 384 (( s_origin_c = 0 ))
385 385 /sbin/zfs list -H -t snapshot -s creation -o name -r $fs |
386 386 grep "^$fs@" | while read name; do
387 387 s_origin[$s_origin_c]=$name
388 388 (( s_origin_c = $s_origin_c + 1 ))
389 389 done
390 390
391 391 #
392 392 # Now go through the origin snapshots and find those which don't
393 393 # have clones. We're going to explicity delete these snapshots
394 394 # before we do the promotion.
395 395 #
396 396 unset s_delete
397 397 (( s_delete_c = 0 ))
398 398 (( j = 0 ))
399 399 while (( $j < $s_origin_c )); do
400 400 (( k = 0 ))
401 401 while (( $k < $clones_c )); do
402 402 # if we have a match then break out of this loop
403 403 [[ "${s_origin[$j]}" == "${clones_origin[$k]}" ]] &&
404 404 break
405 405 (( k = $k + 1 ))
406 406 done
407 407 if (( $k != $clones_c )); then
408 408 # this snapshot has a clone, move on to the next one
409 409 (( j = $j + 1 ))
410 410 continue
411 411 fi
412 412
413 413 # snapshot has no clones so add it to our delete list
414 414 s_delete[$s_delete_c]=${s_origin[$j]}
415 415 (( s_delete_c = $s_delete_c + 1 ))
416 416 # remove it from the origin snapshot list
417 417 (( k = $j + 1 ))
418 418 while (( $k < $s_origin_c )); do
419 419 s_origin[(( $k - 1 ))]=${s_origin[$k]}
420 420 (( k = $k + 1 ))
421 421 done
422 422 (( s_origin_c = $s_origin_c - 1 ))
423 423 done
424 424
425 425 #
426 426 # Fastpath. If there are no remaining snapshots then just
427 427 # delete the origin filesystem (and all it's descendents) and
428 428 # move onto the next zone BE.
429 429 #
430 430 if (( $s_origin_c == 0 )); then
431 431 zfs_destroy "$fs"
432 432 return
433 433 fi
434 434
435 435 # find the youngest snapshot of $fs
436 436 s_youngest=${s_origin[(( $s_origin_c - 1 ))]}
437 437
438 438 # Find the oldest clone of the youngest snapshot of $fs
439 439 unset s_clone
440 440 (( j = $clones_c - 1 ))
441 441 while (( $j >= 0 )); do
442 442 if [[ "$s_youngest" == "${clones_origin[$j]}" ]]; then
443 443 s_clone=${clones[$j]}
444 444 break
445 445 fi
446 446 (( j = $j - 1 ))
447 447 done
448 448 if [[ -z "$s_clone" ]]; then
449 449 # uh oh. something has gone wrong. bail.
450 450 printf "$f_stray_snap\n" >&2
451 451 printf "\t$s_youngest\n" >&2
452 452 printf "$f_rm_snap\n" >&2
453 453 exit $ZONE_SUBPROC_FATAL
454 454 fi
455 455
456 456 # create an array of clone snapshot names
457 457 unset s_clone_s
458 458 (( s_clone_s_c = 0 ))
459 459 /sbin/zfs list -H -t snapshot -s creation -o name -r $s_clone |
460 460 grep "^$s_clone@" | while read name; do
461 461 s_clone_s[$s_clone_s_c]=${name##*@}
462 462 (( s_clone_s_c = $s_clone_s_c + 1 ))
463 463 done
464 464
465 465 # create an arrays of possible origin snapshot renames
466 466 unset s_origin_snap
467 467 unset s_rename
468 468 (( j = 0 ))
469 469 while (( $j < $s_origin_c )); do
470 470 s_origin_snap[$j]=${s_origin[$j]##*@}
471 471 s_rename[$j]=${s_origin[$j]##*@}
472 472 (( j = $j + 1 ))
473 473 done
474 474
475 475 #
476 476 # Search for snapshot name collisions between the origin and
477 477 # oldest clone. If we find one, generate a new name for the
478 478 # origin snapshot and re-do the collision check.
479 479 #
480 480 snap_rename_init
481 481 (( j = 0 ))
482 482 while (( $j < $s_origin_c )); do
483 483 (( k = 0 ))
484 484 while (( $k < $s_clone_s_c )); do
485 485
486 486 # if there's no naming conflict continue
487 487 if [[ "${s_rename[$j]}" != "${s_clone_s[$k]}" ]]; then
488 488 (( k = $k + 1 ))
489 489 continue
490 490 fi
491 491
492 492 #
493 493 # The origin snapshot conflicts with a clone
494 494 # snapshot. Choose a new name and then restart
495 495 # then check that against clone snapshot names.
496 496 #
497 497 snap_rename fs "s_rename[$j]"
498 498 (( k = 0 ))
499 499 continue;
500 500 done
501 501
502 502 # if we didn't rename this snapshot then continue
503 503 if [[ "${s_rename[$j]}" == "${s_origin_snap[$j]}" ]]; then
504 504 (( j = $j + 1 ))
505 505 continue
506 506 fi
507 507
508 508 #
509 509 # We need to rename this origin snapshot because it
510 510 # conflicts with a clone snapshot name. So above we
511 511 # chose a name that didn't conflict with any other clone
512 512 # snapshot names. But we also have to avoid naming
513 513 # conflicts with any other origin snapshot names. So
514 514 # check for that now.
515 515 #
516 516 (( k = 0 ))
517 517 while (( $k < $s_origin_c )); do
518 518
519 519 # don't compare against ourself
520 520 if (( $j == $k )); then
521 521 (( k = $k + 1 ))
522 522 continue
523 523 fi
524 524
525 525 # if there's no naming conflict continue
526 526 if [[ "${s_rename[$j]}" != "${s_rename[$k]}" ]]; then
527 527 (( k = $k + 1 ))
528 528 continue
529 529 fi
530 530
531 531 #
532 532 # The new origin snapshot name conflicts with
533 533 # another origin snapshot name. Choose a new
534 534 # name and then go back to check the new name
535 535 # for uniqueness against all the clone snapshot
536 536 # names.
537 537 #
538 538 snap_rename fs "s_rename[$j]"
539 539 continue 2;
540 540 done
541 541
542 542 #
543 543 # A new unique name has been chosen. Move on to the
544 544 # next origin snapshot.
545 545 #
546 546 (( j = $j + 1 ))
547 547 snap_rename_init
548 548 done
549 549
550 550 #
551 551 # So now we know what snapshots need to be renamed before the
552 552 # promotion. But there's an additional problem. If any of the
553 553 # filesystems cloned from these snapshots have the "zoned"
554 554 # attribute set (which is highly likely) or if they are in use
555 555 # (and can't be unmounted and re-mounted) then the snapshot
556 556 # rename will fail. So now we'll search for all the clones of
557 557 # snapshots we plan to rename and look for ones that are zoned.
558 558 #
559 559 # We'll ignore any snapshot clones that may be in use but are
560 560 # not zoned. If these clones are in-use, the rename will fail
561 561 # and we'll abort, there's not much else we can do about it.
562 562 # But if they are not in use the snapshot rename will unmount
563 563 # and remount the clone. This is ok because when the zoned
564 564 # attribute is off, we know that the clone was originally
565 565 # mounted from the global zone. (So unmounting and remounting
566 566 # it from the global zone is ok.)
567 567 #
568 568 # But we'll abort this whole operation if we find any clones
569 569 # that that are zoned and in use. (This can happen if another
570 570 # zone has been cloned from this one and is now booted.) The
571 571 # reason we do this is because those zoned filesystems could
572 572 # have originally mounted from within the zone. So if we
573 573 # cleared the zone attribute and did the rename, we'd be
574 574 # remounting the filesystem from the global zone. This would
575 575 # result in the zone losing the ability to unmount the
576 576 # filesystem, which would be bad.
577 577 #
578 578 unset zoned_clones zoned_iu_clones
579 579 (( zoned_clones_c = 0 ))
580 580 (( zoned_iu_clones_c = 0 ))
581 581 (( j = 0 ))
582 582 # walk through all the clones
583 583 while (( $j < $clones_c )); do
584 584 # walk through all the origin snapshots
585 585 (( k = 0 ))
586 586 while (( $k < $s_origin_c )); do
587 587 #
588 588 # check if this clone originated from a snapshot that
589 589 # we need to rename.
590 590 #
591 591 [[ "${clones_origin[$j]}" == "${s_origin[$k]}" ]] &&
592 592 [[ "${s_origin_snap[$k]}" != "${s_rename[$k]}" ]] &&
593 593 break
594 594 (( k = $k + 1 ))
595 595 continue
596 596 done
597 597 if (( $k == $s_origin_c )); then
598 598 # This isn't a clone of a snapshot we want to rename.
599 599 (( j = $j + 1 ))
600 600 continue;
601 601 fi
602 602
603 603 # get the zoned attr for this clone.
604 604 zoned=`LC_ALL=C LANG=C \
605 605 /sbin/zfs get -H -o value zoned ${clones[$j]}`
606 606 if [[ "$zoned" != on ]]; then
607 607 # This clone isn't zoned so ignore it.
608 608 (( j = $j + 1 ))
609 609 continue
610 610 fi
611 611
612 612 # remember this clone so we can muck with it's zoned attr.
613 613 zoned_clones[$zoned_clones_c]=${clones[$j]}
614 614 (( zoned_clones_c = $zoned_clones_c + 1 ))
615 615
616 616 # check if it's in use
617 617 mounted=`LC_ALL=C LANG=C \
618 618 /sbin/zfs get -H -o value mounted ${clones[$j]}`
619 619 if [[ "$mounted" != yes ]]; then
620 620 # Good news. This clone isn't in use.
621 621 (( j = $j + 1 ))
622 622 continue
623 623 fi
624 624
625 625 # Sigh. This clone is in use so we're destined to fail.
626 626 zoned_iu_clones[$zoned_iu_clones_c]=${clones[$j]}
627 627 (( zoned_iu_clones_c = $zoned_iu_clones_c + 1 ))
628 628
629 629 # keep looking for errors so we can report them all at once.
630 630 (( j = $j + 1 ))
631 631 done
632 632 if (( zoned_iu_clones_c > 0 )); then
633 633 #
634 634 # Tell the admin
635 635 #
636 636 printf "$f_iu_clone\n" >&2
637 637 print_array zoned_iu_clones >&2
638 638 printf "$f_dis_clone\n" >&2
639 639 exit $ZONE_SUBPROC_FATAL
640 640 fi
641 641
642 642 #
643 643 # Ok. So we're finally done with planning and we can do some
644 644 # damage. We're going to:
645 645 # - destroy unused snapshots
646 646 # - unzone clones which originate from snapshots we need to rename
647 647 # - rename conflicting snapshots
648 648 # - rezone any clones which we unzoned
649 649 # - promote the oldest clone of the youngest snapshot
650 650 # - finally destroy the origin filesystem.
651 651 #
652 652
653 653 # delete any unsed snapshot
654 654 (( j = 0 ))
655 655 while (( $j < $s_delete_c )); do
656 656 zfs_destroy "${s_delete[$j]}"
657 657 (( j = $j + 1 ))
658 658 done
659 659
660 660 # unzone clones
661 661 zfs_set_array zoned off zoned_clones ||
662 662 zfs_set_array zoned on zoned_clones 1
663 663
664 664 # rename conflicting snapshots
665 665 (( j = 0 ))
666 666 while (( $j < $s_origin_c )); do
667 667 if [[ "${s_origin_snap[$j]}" != "${s_rename[$j]}" ]]; then
668 668 zfs_rename "${s_origin[$j]}" "$fs@${s_rename[$j]}"
669 669 if [[ $? != 0 ]]; then
670 670 # re-zone the clones before aborting
671 671 zfs_set_array zoned on zoned_clones 1
672 672 exit $ZONE_SUBPROC_FATAL
673 673 fi
674 674 fi
675 675 (( j = $j + 1 ))
676 676 done
677 677
678 678 # re-zone the clones
679 679 zfs_set_array zoned on zoned_clones 1
680 680
681 681 # promote the youngest clone of the oldest snapshot
682 682 zfs_promote "$s_clone"
683 683
684 684 # destroy the origin filesystem and it's descendants
685 685 zfs_destroy "$fs"
686 686 }
687 687
688 688 #
689 689 # This function expects an array named fs_all to exist which is initialized
690 690 # with the zone's ZFS datasets that should be destroyed. fs_all_c is the
691 691 # count of the number of elements in the array. ZONEPATH_RDS is the
692 692 # zonepath/root dataset and ZONEPATH_DS is the zonepath dataset.
693 693 #
694 694 destroy_zone_datasets()
695 695 {
696 696 # Destroy the zone BEs datasets one by one.
697 697 (( i = 0 ))
698 698 while (( $i < $fs_all_c )); do
699 699 fs=${fs_all[$i]}
700 700
701 701 destroy_zone_dataset "$fs"
702 702 (( i = $i + 1 ))
703 703 done
704 704
705 705 #
706 706 # Check if there are any other datasets left. There may be datasets
707 707 # associated with other GZ BEs, so we need to leave things alone in
708 708 # that case.
709 709 #
710 710 c=`/sbin/zfs list -H -t filesystem -r $ZONEPATH_RDS | wc -l`
711 711 if [ $c = 1 ]; then
712 712 zfs_destroy "$ZONEPATH_RDS"
713 713 fi
714 714 c=`/sbin/zfs list -H -t filesystem -r $ZONEPATH_DS | wc -l`
715 715 if [ $c = 1 ]; then
716 716 zfs_destroy "$ZONEPATH_DS"
717 717 fi
718 718
719 719 rm_zonepath
720 720 }
↓ open down ↓ |
458 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX