1# SPDX-License-Identifier: Apache-2.0 2# 3# Copyright 2015 ClusterHQ 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18""" 19Python wrappers for libzfs_core interfaces. 20 21As a rule, there is a Python function for each C function. 22The signatures of the Python functions generally follow those of the 23functions, but the argument types are natural to Python. 24nvlists are wrapped as dictionaries or lists depending on their usage. 25Some parameters have default values depending on typical use for 26increased convenience. Output parameters are not used and return values 27are directly returned. Error conditions are signalled by exceptions 28rather than by integer error codes. 29""" 30from __future__ import absolute_import, division, print_function 31 32import errno 33import os 34import threading 35from . import exceptions 36from . import _error_translation as errors 37from .bindings import libzfs_core 38from ._constants import ( # noqa: F401 39 MAXNAMELEN, 40 ZCP_DEFAULT_INSTRLIMIT, 41 ZCP_DEFAULT_MEMLIMIT, 42 WRAPPING_KEY_LEN, 43 zfs_key_location, 44 zfs_keyformat, 45 zio_encrypt 46) 47from .ctypes import uint64_t 48from ._nvlist import nvlist_in, nvlist_out 49 50 51def lzc_create(name, ds_type='zfs', props=None, key=None): 52 ''' 53 Create a ZFS filesystem or a ZFS volume ("zvol"). 54 55 :param bytes name: a name of the dataset to be created. 56 :param str ds_type: the type of the dataset to be created, 57 currently supported types are "zfs" (the default) for a filesystem and 58 "zvol" for a volume. 59 :param props: a `dict` of ZFS dataset property name-value pairs 60 (empty by default). 61 :type props: dict of bytes:Any 62 :param key: dataset encryption key data (empty by default). 63 :type key: bytes 64 65 :raises FilesystemExists: if a dataset with the given name already exists. 66 :raises ParentNotFound: if a parent dataset of the requested dataset does 67 not exist. 68 :raises PropertyInvalid: if one or more of the specified properties is 69 invalid or has an invalid type or value. 70 :raises NameInvalid: if the name is not a valid dataset name. 71 :raises NameTooLong: if the name is too long. 72 :raises WrongParent: if the parent dataset of the requested dataset is not 73 a filesystem (e.g. ZVOL) 74 ''' 75 if props is None: 76 props = {} 77 if key is None: 78 key = b"" 79 else: 80 key = bytes(key) 81 if ds_type == 'zfs': 82 ds_type = _lib.DMU_OST_ZFS 83 elif ds_type == 'zvol': 84 ds_type = _lib.DMU_OST_ZVOL 85 else: 86 raise exceptions.DatasetTypeInvalid(ds_type) 87 nvlist = nvlist_in(props) 88 ret = _lib.lzc_create(name, ds_type, nvlist, key, len(key)) 89 errors.lzc_create_translate_error(ret, name, ds_type, props) 90 91 92def lzc_clone(name, origin, props=None): 93 ''' 94 Clone a ZFS filesystem or a ZFS volume ("zvol") from a given snapshot. 95 96 :param bytes name: a name of the dataset to be created. 97 :param bytes origin: a name of the origin snapshot. 98 :param props: a `dict` of ZFS dataset property name-value pairs 99 (empty by default). 100 :type props: dict of bytes:Any 101 102 :raises FilesystemExists: if a dataset with the given name already exists. 103 :raises DatasetNotFound: if either a parent dataset of the requested 104 dataset or the origin snapshot does not exist. 105 :raises PropertyInvalid: if one or more of the specified properties is 106 invalid or has an invalid type or value. 107 :raises FilesystemNameInvalid: if the name is not a valid dataset name. 108 :raises SnapshotNameInvalid: if the origin is not a valid snapshot name. 109 :raises NameTooLong: if the name or the origin name is too long. 110 :raises PoolsDiffer: if the clone and the origin have different pool names. 111 112 .. note:: 113 Because of a deficiency of the underlying C interface 114 :exc:`.DatasetNotFound` can mean that either a parent filesystem of 115 the target or the origin snapshot does not exist. 116 It is currently impossible to distinguish between the cases. 117 :func:`lzc_hold` can be used to check that the snapshot exists and 118 ensure that it is not destroyed before cloning. 119 ''' 120 if props is None: 121 props = {} 122 nvlist = nvlist_in(props) 123 ret = _lib.lzc_clone(name, origin, nvlist) 124 errors.lzc_clone_translate_error(ret, name, origin, props) 125 126 127def lzc_rollback(name): 128 ''' 129 Roll back a filesystem or volume to its most recent snapshot. 130 131 Note that the latest snapshot may change if a new one is concurrently 132 created or the current one is destroyed. lzc_rollback_to can be used 133 to roll back to a specific latest snapshot. 134 135 :param bytes name: a name of the dataset to be rolled back. 136 :return: a name of the most recent snapshot. 137 :rtype: bytes 138 139 :raises FilesystemNotFound: if the dataset does not exist. 140 :raises SnapshotNotFound: if the dataset does not have any snapshots. 141 :raises NameInvalid: if the dataset name is invalid. 142 :raises NameTooLong: if the dataset name is too long. 143 ''' 144 # Account for terminating NUL in C strings. 145 snapnamep = _ffi.new('char[]', MAXNAMELEN + 1) 146 ret = _lib.lzc_rollback(name, snapnamep, MAXNAMELEN + 1) 147 errors.lzc_rollback_translate_error(ret, name) 148 return _ffi.string(snapnamep) 149 150 151def lzc_rollback_to(name, snap): 152 ''' 153 Roll back this filesystem or volume to the specified snapshot, if possible. 154 155 :param bytes name: a name of the dataset to be rolled back. 156 :param bytes snap: a name of the snapshot to be rolled back. 157 158 :raises FilesystemNotFound: if the dataset does not exist. 159 :raises SnapshotNotFound: if the dataset does not have any snapshots. 160 :raises NameInvalid: if the dataset name is invalid. 161 :raises NameTooLong: if the dataset name is too long. 162 :raises SnapshotNotLatest: if the snapshot is not the latest. 163 ''' 164 ret = _lib.lzc_rollback_to(name, snap) 165 errors.lzc_rollback_to_translate_error(ret, name, snap) 166 167 168def lzc_snapshot(snaps, props=None): 169 ''' 170 Create snapshots. 171 172 All snapshots must be in the same pool. 173 174 Optionally snapshot properties can be set on all snapshots. 175 Currently only user properties (prefixed with "user:") are supported. 176 177 Either all snapshots are successfully created or none are created if 178 an exception is raised. 179 180 :param snaps: a list of names of snapshots to be created. 181 :type snaps: list of bytes 182 :param props: a `dict` of ZFS dataset property name-value pairs 183 (empty by default). 184 :type props: dict of bytes:bytes 185 186 :raises SnapshotFailure: if one or more snapshots could not be created. 187 188 .. note:: 189 :exc:`.SnapshotFailure` is a compound exception that provides at least 190 one detailed error object in :attr:`SnapshotFailure.errors` `list`. 191 192 .. warning:: 193 The underlying implementation reports an individual, per-snapshot error 194 only for :exc:`.SnapshotExists` condition and *sometimes* for 195 :exc:`.NameTooLong`. 196 In all other cases a single error is reported without connection to any 197 specific snapshot name(s). 198 199 This has the following implications: 200 201 * if multiple error conditions are encountered only one of them is 202 reported 203 204 * unless only one snapshot is requested then it is impossible to tell 205 how many snapshots are problematic and what they are 206 207 * only if there are no other error conditions :exc:`.SnapshotExists` 208 is reported for all affected snapshots 209 210 * :exc:`.NameTooLong` can behave either in the same way as 211 :exc:`.SnapshotExists` or as all other exceptions. 212 The former is the case where the full snapshot name exceeds the 213 maximum allowed length but the short snapshot name (after '@') is 214 within the limit. 215 The latter is the case when the short name alone exceeds the maximum 216 allowed length. 217 ''' 218 snaps_dict = {name: None for name in snaps} 219 errlist = {} 220 snaps_nvlist = nvlist_in(snaps_dict) 221 if props is None: 222 props = {} 223 props_nvlist = nvlist_in(props) 224 with nvlist_out(errlist) as errlist_nvlist: 225 ret = _lib.lzc_snapshot(snaps_nvlist, props_nvlist, errlist_nvlist) 226 errors.lzc_snapshot_translate_errors(ret, errlist, snaps, props) 227 228 229lzc_snap = lzc_snapshot 230 231 232def lzc_destroy_snaps(snaps, defer): 233 ''' 234 Destroy snapshots. 235 236 They must all be in the same pool. 237 Snapshots that do not exist will be silently ignored. 238 239 If 'defer' is not set, and a snapshot has user holds or clones, the 240 destroy operation will fail and none of the snapshots will be 241 destroyed. 242 243 If 'defer' is set, and a snapshot has user holds or clones, it will be 244 marked for deferred destruction, and will be destroyed when the last hold 245 or clone is removed/destroyed. 246 247 The operation succeeds if all snapshots were destroyed (or marked for 248 later destruction if 'defer' is set) or didn't exist to begin with. 249 250 :param snaps: a list of names of snapshots to be destroyed. 251 :type snaps: list of bytes 252 :param bool defer: whether to mark busy snapshots for deferred destruction 253 rather than immediately failing. 254 255 :raises SnapshotDestructionFailure: if one or more snapshots could not be 256 created. 257 258 .. note:: 259 :exc:`.SnapshotDestructionFailure` is a compound exception that 260 provides at least one detailed error object in 261 :attr:`SnapshotDestructionFailure.errors` `list`. 262 263 Typical error is :exc:`SnapshotIsCloned` if `defer` is `False`. 264 The snapshot names are validated quite loosely and invalid names are 265 typically ignored as nonexisting snapshots. 266 267 A snapshot name referring to a filesystem that doesn't exist is 268 ignored. 269 However, non-existent pool name causes :exc:`PoolNotFound`. 270 ''' 271 snaps_dict = {name: None for name in snaps} 272 errlist = {} 273 snaps_nvlist = nvlist_in(snaps_dict) 274 with nvlist_out(errlist) as errlist_nvlist: 275 ret = _lib.lzc_destroy_snaps(snaps_nvlist, defer, errlist_nvlist) 276 errors.lzc_destroy_snaps_translate_errors(ret, errlist, snaps, defer) 277 278 279def lzc_bookmark(bookmarks): 280 ''' 281 Create bookmarks. 282 283 :param bookmarks: a dict that maps names of wanted bookmarks to names of 284 existing snapshots or bookmarks. 285 :type bookmarks: dict of bytes to bytes 286 :raises BookmarkFailure: if any of the bookmarks can not be created for any 287 reason. 288 289 The bookmarks `dict` maps from name of the bookmark 290 (e.g. :file:`{pool}/{fs}#{bmark}`) to the name of the snapshot 291 (e.g. :file:`{pool}/{fs}@{snap}`) or existint bookmark 292 :file:`{pool}/{fs}@{snap}`. All the bookmarks and snapshots must 293 be in the same pool. 294 ''' 295 errlist = {} 296 nvlist = nvlist_in(bookmarks) 297 with nvlist_out(errlist) as errlist_nvlist: 298 ret = _lib.lzc_bookmark(nvlist, errlist_nvlist) 299 errors.lzc_bookmark_translate_errors(ret, errlist, bookmarks) 300 301 302def lzc_get_bookmarks(fsname, props=None): 303 ''' 304 Retrieve a listing of bookmarks for the given file system. 305 306 :param bytes fsname: a name of the filesystem. 307 :param props: a `list` of properties that will be returned for each 308 bookmark. 309 :type props: list of bytes 310 :return: a `dict` that maps the bookmarks' short names to their properties. 311 :rtype: dict of bytes:dict 312 313 :raises FilesystemNotFound: if the filesystem is not found. 314 315 The following are valid properties on bookmarks: 316 317 guid : integer 318 globally unique identifier of the snapshot the bookmark refers to 319 createtxg : integer 320 txg when the snapshot the bookmark refers to was created 321 creation : integer 322 timestamp when the snapshot the bookmark refers to was created 323 324 Any other properties passed in ``props`` are ignored without reporting 325 any error. 326 Values in the returned dictionary map the names of the requested properties 327 to their respective values. 328 ''' 329 bmarks = {} 330 if props is None: 331 props = [] 332 props_dict = {name: None for name in props} 333 nvlist = nvlist_in(props_dict) 334 with nvlist_out(bmarks) as bmarks_nvlist: 335 ret = _lib.lzc_get_bookmarks(fsname, nvlist, bmarks_nvlist) 336 errors.lzc_get_bookmarks_translate_error(ret, fsname, props) 337 return bmarks 338 339 340def lzc_destroy_bookmarks(bookmarks): 341 ''' 342 Destroy bookmarks. 343 344 :param bookmarks: a list of the bookmarks to be destroyed. The bookmarks 345 are specified as :file:`{fs}#{bmark}`. 346 :type bookmarks: list of bytes 347 348 :raises BookmarkDestructionFailure: if any of the bookmarks may not be 349 destroyed. 350 351 The bookmarks must all be in the same pool. 352 Bookmarks that do not exist will be silently ignored. 353 This also includes the case where the filesystem component of the bookmark 354 name does not exist. 355 However, an invalid bookmark name will cause :exc:`.NameInvalid` error 356 reported in :attr:`SnapshotDestructionFailure.errors`. 357 358 Either all bookmarks that existed are destroyed or an exception is raised. 359 ''' 360 errlist = {} 361 bmarks_dict = {name: None for name in bookmarks} 362 nvlist = nvlist_in(bmarks_dict) 363 with nvlist_out(errlist) as errlist_nvlist: 364 ret = _lib.lzc_destroy_bookmarks(nvlist, errlist_nvlist) 365 errors.lzc_destroy_bookmarks_translate_errors(ret, errlist, bookmarks) 366 367 368def lzc_snaprange_space(firstsnap, lastsnap): 369 ''' 370 Calculate a size of data referenced by snapshots in the inclusive range 371 between the ``firstsnap`` and the ``lastsnap`` and not shared with any 372 other datasets. 373 374 :param bytes firstsnap: the name of the first snapshot in the range. 375 :param bytes lastsnap: the name of the last snapshot in the range. 376 :return: the calculated stream size, in bytes. 377 :rtype: `int` or `long` 378 379 :raises SnapshotNotFound: if either of the snapshots does not exist. 380 :raises NameInvalid: if the name of either snapshot is invalid. 381 :raises NameTooLong: if the name of either snapshot is too long. 382 :raises SnapshotMismatch: if ``fromsnap`` is not an ancestor snapshot of 383 ``snapname``. 384 :raises PoolsDiffer: if the snapshots belong to different pools. 385 386 ``lzc_snaprange_space`` calculates total size of blocks that exist 387 because they are referenced only by one or more snapshots in the given 388 range but no other dataset. 389 In other words, this is the set of blocks that were born after the snap 390 before firstsnap, and died before the snap after the last snap. 391 Yet another interpretation is that the result of ``lzc_snaprange_space`` 392 is the size of the space that would be freed if the snapshots in the range 393 are destroyed. 394 395 If the same snapshot is given as both the ``firstsnap`` and the 396 ``lastsnap``. 397 In that case ``lzc_snaprange_space`` calculates space used by the snapshot. 398 ''' 399 valp = _ffi.new('uint64_t *') 400 ret = _lib.lzc_snaprange_space(firstsnap, lastsnap, valp) 401 errors.lzc_snaprange_space_translate_error(ret, firstsnap, lastsnap) 402 return int(valp[0]) 403 404 405def lzc_hold(holds, fd=None): 406 ''' 407 Create *user holds* on snapshots. If there is a hold on a snapshot, 408 the snapshot can not be destroyed. (However, it can be marked for 409 deletion by :func:`lzc_destroy_snaps` ( ``defer`` = `True` ).) 410 411 :param holds: the dictionary of names of the snapshots to hold mapped to 412 the hold names. 413 :type holds: dict of bytes : bytes 414 :type fd: int or None 415 :param fd: if not None then it must be the result of :func:`os.open` 416 called as ``os.open("/dev/zfs", O_EXCL)``. 417 :type fd: int or None 418 :return: a list of the snapshots that do not exist. 419 :rtype: list of bytes 420 421 :raises HoldFailure: if a hold was impossible on one or more of the 422 snapshots. 423 :raises BadHoldCleanupFD: if ``fd`` is not a valid file descriptor 424 associated with :file:`/dev/zfs`. 425 426 The snapshots must all be in the same pool. 427 428 If ``fd`` is not None, then when the ``fd`` is closed (including on process 429 termination), the holds will be released. If the system is shut down 430 uncleanly, the holds will be released when the pool is next opened 431 or imported. 432 433 Holds for snapshots which don't exist will be skipped and have an entry 434 added to the return value, but will not cause an overall failure. 435 No exceptions is raised if all holds, for snapshots that existed, were 436 successfully created. 437 Otherwise :exc:`.HoldFailure` exception is raised and no holds will be 438 created. 439 :attr:`.HoldFailure.errors` may contain a single element for an error that 440 is not specific to any hold / snapshot, or it may contain one or more 441 elements detailing specific error per each affected hold. 442 ''' 443 errlist = {} 444 if fd is None: 445 fd = -1 446 nvlist = nvlist_in(holds) 447 with nvlist_out(errlist) as errlist_nvlist: 448 ret = _lib.lzc_hold(nvlist, fd, errlist_nvlist) 449 errors.lzc_hold_translate_errors(ret, errlist, holds, fd) 450 # If there is no error (no exception raised by _handleErrList), but errlist 451 # is not empty, then it contains missing snapshots. 452 assert all(errlist[x] == errno.ENOENT for x in errlist) 453 return list(errlist.keys()) 454 455 456def lzc_release(holds): 457 ''' 458 Release *user holds* on snapshots. 459 460 If the snapshot has been marked for 461 deferred destroy (by lzc_destroy_snaps(defer=B_TRUE)), it does not have 462 any clones, and all the user holds are removed, then the snapshot will be 463 destroyed. 464 465 The snapshots must all be in the same pool. 466 467 :param holds: a ``dict`` where keys are snapshot names and values are 468 lists of hold tags to remove. 469 :type holds: dict of bytes : list of bytes 470 :return: a list of any snapshots that do not exist and of any tags that do 471 not exist for existing snapshots. 472 Such tags are qualified with a corresponding snapshot name using the 473 following format :file:`{pool}/{fs}@{snap}#{tag}` 474 :rtype: list of bytes 475 476 :raises HoldReleaseFailure: if one or more existing holds could not be 477 released. 478 479 Holds which failed to release because they didn't exist will have an entry 480 added to errlist, but will not cause an overall failure. 481 482 This call is success if ``holds`` was empty or all holds that 483 existed, were successfully removed. 484 Otherwise an exception will be raised. 485 ''' 486 errlist = {} 487 holds_dict = {} 488 for snap in holds: 489 hold_list = holds[snap] 490 if not isinstance(hold_list, list): 491 raise TypeError('holds must be in a list') 492 holds_dict[snap] = {hold: None for hold in hold_list} 493 nvlist = nvlist_in(holds_dict) 494 with nvlist_out(errlist) as errlist_nvlist: 495 ret = _lib.lzc_release(nvlist, errlist_nvlist) 496 errors.lzc_release_translate_errors(ret, errlist, holds) 497 # If there is no error (no exception raised by _handleErrList), but errlist 498 # is not empty, then it contains missing snapshots and tags. 499 assert all(errlist[x] == errno.ENOENT for x in errlist) 500 return list(errlist.keys()) 501 502 503def lzc_get_holds(snapname): 504 ''' 505 Retrieve list of *user holds* on the specified snapshot. 506 507 :param bytes snapname: the name of the snapshot. 508 :return: holds on the snapshot along with their creation times 509 in seconds since the epoch 510 :rtype: dict of bytes : int 511 ''' 512 holds = {} 513 with nvlist_out(holds) as nvlist: 514 ret = _lib.lzc_get_holds(snapname, nvlist) 515 errors.lzc_get_holds_translate_error(ret, snapname) 516 return holds 517 518 519def lzc_send(snapname, fromsnap, fd, flags=None): 520 ''' 521 Generate a zfs send stream for the specified snapshot and write it to 522 the specified file descriptor. 523 524 :param bytes snapname: the name of the snapshot to send. 525 :param fromsnap: if not None the name of the starting snapshot 526 for the incremental stream. 527 :type fromsnap: bytes or None 528 :param int fd: the file descriptor to write the send stream to. 529 :param flags: the flags that control what enhanced features can be used in 530 the stream. 531 :type flags: list of bytes 532 533 :raises SnapshotNotFound: if either the starting snapshot is not `None` and 534 does not exist, or if the ending snapshot does not exist. 535 :raises NameInvalid: if the name of either snapshot is invalid. 536 :raises NameTooLong: if the name of either snapshot is too long. 537 :raises SnapshotMismatch: if ``fromsnap`` is not an ancestor snapshot of 538 ``snapname``. 539 :raises PoolsDiffer: if the snapshots belong to different pools. 540 :raises IOError: if an input / output error occurs while writing to ``fd``. 541 :raises UnknownStreamFeature: if the ``flags`` contain an unknown flag 542 name. 543 544 If ``fromsnap`` is None, a full (non-incremental) stream will be sent. 545 If ``fromsnap`` is not None, it must be the full name of a snapshot or 546 bookmark to send an incremental from, e.g. 547 :file:`{pool}/{fs}@{earlier_snap}` or :file:`{pool}/{fs}#{earlier_bmark}`. 548 549 The specified snapshot or bookmark must represent an earlier point in the 550 history of ``snapname``. 551 It can be an earlier snapshot in the same filesystem or zvol as 552 ``snapname``, or it can be the origin of ``snapname``'s filesystem, or an 553 earlier snapshot in the origin, etc. 554 ``fromsnap`` must be strictly an earlier snapshot, specifying the same 555 snapshot as both ``fromsnap`` and ``snapname`` is an error. 556 557 If ``flags`` contains *"large_blocks"*, the stream is permitted 558 to contain ``DRR_WRITE`` records with ``drr_length`` > 128K, 559 and ``DRR_OBJECT`` records with ``drr_blksz`` > 128K. 560 561 If ``flags`` contains *"embedded_data"*, the stream is permitted 562 to contain ``DRR_WRITE_EMBEDDED`` records with 563 ``drr_etype`` == ``BP_EMBEDDED_TYPE_DATA``, 564 which the receiving system must support (as indicated by support 565 for the *embedded_data* feature). 566 567 If ``flags`` contains *"compress"*, the stream is generated by using 568 compressed WRITE records for blocks which are compressed on disk and 569 in memory. If the *lz4_compress* feature is active on the sending 570 system, then the receiving system must have that feature enabled as well. 571 572 If ``flags`` contains *"raw"*, the stream is generated, for encrypted 573 datasets, by sending data exactly as it exists on disk. This allows 574 backups to be taken even if encryption keys are not currently loaded. 575 576 .. note:: 577 ``lzc_send`` can actually accept a filesystem name as the ``snapname``. 578 In that case ``lzc_send`` acts as if a temporary snapshot was created 579 after the start of the call and before the stream starts being 580 produced. 581 582 .. note:: 583 ``lzc_send`` does not return until all of the stream is written to 584 ``fd``. 585 586 .. note:: 587 ``lzc_send`` does *not* close ``fd`` upon returning. 588 ''' 589 if fromsnap is not None: 590 c_fromsnap = fromsnap 591 else: 592 c_fromsnap = _ffi.NULL 593 c_flags = 0 594 if flags is None: 595 flags = [] 596 for flag in flags: 597 c_flag = { 598 'embedded_data': _lib.LZC_SEND_FLAG_EMBED_DATA, 599 'large_blocks': _lib.LZC_SEND_FLAG_LARGE_BLOCK, 600 'compress': _lib.LZC_SEND_FLAG_COMPRESS, 601 'raw': _lib.LZC_SEND_FLAG_RAW, 602 }.get(flag) 603 if c_flag is None: 604 raise exceptions.UnknownStreamFeature(flag) 605 c_flags |= c_flag 606 607 ret = _lib.lzc_send(snapname, c_fromsnap, fd, c_flags) 608 errors.lzc_send_translate_error(ret, snapname, fromsnap, fd, flags) 609 610 611def lzc_send_space(snapname, fromsnap=None, flags=None): 612 ''' 613 Estimate size of a full or incremental backup stream 614 given the optional starting snapshot and the ending snapshot. 615 616 :param bytes snapname: the name of the snapshot for which the estimate 617 should be done. 618 :param fromsnap: the optional starting snapshot name. 619 If not `None` then an incremental stream size is estimated, otherwise 620 a full stream is estimated. 621 :type fromsnap: `bytes` or `None` 622 :param flags: the flags that control what enhanced features can be used 623 in the stream. 624 :type flags: list of bytes 625 626 :return: the estimated stream size, in bytes. 627 :rtype: `int` or `long` 628 629 :raises SnapshotNotFound: if either the starting snapshot is not `None` and 630 does not exist, or if the ending snapshot does not exist. 631 :raises NameInvalid: if the name of either snapshot is invalid. 632 :raises NameTooLong: if the name of either snapshot is too long. 633 :raises SnapshotMismatch: if ``fromsnap`` is not an ancestor snapshot of 634 ``snapname``. 635 :raises PoolsDiffer: if the snapshots belong to different pools. 636 637 ``fromsnap``, if not ``None``, must be strictly an earlier snapshot, 638 specifying the same snapshot as both ``fromsnap`` and ``snapname`` is an 639 error. 640 ''' 641 if fromsnap is not None: 642 c_fromsnap = fromsnap 643 else: 644 c_fromsnap = _ffi.NULL 645 c_flags = 0 646 if flags is None: 647 flags = [] 648 for flag in flags: 649 c_flag = { 650 'embedded_data': _lib.LZC_SEND_FLAG_EMBED_DATA, 651 'large_blocks': _lib.LZC_SEND_FLAG_LARGE_BLOCK, 652 'compress': _lib.LZC_SEND_FLAG_COMPRESS, 653 'raw': _lib.LZC_SEND_FLAG_RAW, 654 }.get(flag) 655 if c_flag is None: 656 raise exceptions.UnknownStreamFeature(flag) 657 c_flags |= c_flag 658 valp = _ffi.new('uint64_t *') 659 660 ret = _lib.lzc_send_space(snapname, c_fromsnap, c_flags, valp) 661 errors.lzc_send_space_translate_error(ret, snapname, fromsnap) 662 return int(valp[0]) 663 664 665def lzc_receive(snapname, fd, force=False, raw=False, origin=None, props=None): 666 ''' 667 Receive from the specified ``fd``, creating the specified snapshot. 668 669 :param bytes snapname: the name of the snapshot to create. 670 :param int fd: the file descriptor from which to read the stream. 671 :param bool force: whether to roll back or destroy the target filesystem 672 if that is required to receive the stream. 673 :param bool raw: whether this is a "raw" stream. 674 :param origin: the optional origin snapshot name if the stream is for a 675 clone. 676 :type origin: bytes or None 677 :param props: the properties to set on the snapshot as *received* 678 properties. 679 :type props: dict of bytes : Any 680 681 :raises IOError: if an input / output error occurs while reading from the 682 ``fd``. 683 :raises DatasetExists: if the snapshot named ``snapname`` already exists. 684 :raises DatasetExists: if the stream is a full stream and the destination 685 filesystem already exists. 686 :raises DatasetExists: if ``force`` is `True` but the destination 687 filesystem could not be rolled back to a matching snapshot because a 688 newer snapshot exists and it is an origin of a cloned filesystem. 689 :raises StreamMismatch: if an incremental stream is received and the latest 690 snapshot of the destination filesystem does not match the source 691 snapshot of the stream. 692 :raises StreamMismatch: if a full stream is received and the destination 693 filesystem already exists and it has at least one snapshot, and 694 ``force`` is `False`. 695 :raises StreamMismatch: if an incremental clone stream is received but the 696 specified ``origin`` is not the actual received origin. 697 :raises DestinationModified: if an incremental stream is received and the 698 destination filesystem has been modified since the last snapshot and 699 ``force`` is `False`. 700 :raises DestinationModified: if a full stream is received and the 701 destination filesystem already exists and it does not have any 702 snapshots, and ``force`` is `False`. 703 :raises DatasetNotFound: if the destination filesystem and its parent do 704 not exist. 705 :raises DatasetNotFound: if the ``origin`` is not `None` and does not 706 exist. 707 :raises DatasetBusy: if ``force`` is `True` but the destination filesystem 708 could not be rolled back to a matching snapshot because a newer 709 snapshot is held and could not be destroyed. 710 :raises DatasetBusy: if another receive operation is being performed on the 711 destination filesystem. 712 :raises BadStream: if the stream is corrupt or it is not recognized or it 713 is a compound stream or it is a clone stream, but ``origin`` is `None`. 714 :raises BadStream: if a clone stream is received and the destination 715 filesystem already exists. 716 :raises StreamFeatureNotSupported: if the stream has a feature that is not 717 supported on this side. 718 :raises NameInvalid: if the name of either snapshot is invalid. 719 :raises NameTooLong: if the name of either snapshot is too long. 720 :raises WrongParent: if the parent dataset of the received destination is 721 not a filesystem (e.g. ZVOL) 722 723 .. note:: 724 The ``origin`` is ignored if the actual stream is an incremental stream 725 that is not a clone stream and the destination filesystem exists. 726 If the stream is a full stream and the destination filesystem does not 727 exist then the ``origin`` is checked for existence: if it does not 728 exist :exc:`.DatasetNotFound` is raised, otherwise 729 :exc:`.StreamMismatch` is raised, because that snapshot can not have 730 any relation to the stream. 731 732 .. note:: 733 If ``force`` is `True` and the stream is incremental then the 734 destination filesystem is rolled back to a matching source snapshot if 735 necessary. Intermediate snapshots are destroyed in that case. 736 737 However, none of the existing snapshots may have the same name as 738 ``snapname`` even if such a snapshot were to be destroyed. 739 The existing ``snapname`` snapshot always causes 740 :exc:`.SnapshotExists` to be raised. 741 742 If ``force`` is `True` and the stream is a full stream then the 743 destination filesystem is replaced with the received filesystem unless 744 the former has any snapshots. This prevents the destination filesystem 745 from being rolled back / replaced. 746 747 .. note:: 748 This interface does not work on dedup'd streams 749 (those with ``DMU_BACKUP_FEATURE_DEDUP``). 750 751 .. note:: 752 ``lzc_receive`` does not return until all of the stream is read from 753 ``fd`` and applied to the pool. 754 755 .. note:: 756 ``lzc_receive`` does *not* close ``fd`` upon returning. 757 ''' 758 759 if origin is not None: 760 c_origin = origin 761 else: 762 c_origin = _ffi.NULL 763 if props is None: 764 props = {} 765 nvlist = nvlist_in(props) 766 ret = _lib.lzc_receive(snapname, nvlist, c_origin, force, raw, fd) 767 errors.lzc_receive_translate_errors( 768 ret, snapname, fd, force, raw, False, False, origin, None 769 ) 770 771 772lzc_recv = lzc_receive 773 774 775def lzc_exists(name): 776 ''' 777 Check if a dataset (a filesystem, or a volume, or a snapshot) 778 with the given name exists. 779 780 :param bytes name: the dataset name to check. 781 :return: `True` if the dataset exists, `False` otherwise. 782 :rtype: bool 783 784 .. note:: 785 ``lzc_exists`` can not be used to check for existence of bookmarks. 786 ''' 787 ret = _lib.lzc_exists(name) 788 return bool(ret) 789 790 791def lzc_change_key(fsname, crypt_cmd, props=None, key=None): 792 ''' 793 Change encryption key on the specified dataset. 794 795 :param bytes fsname: the name of the dataset. 796 :param str crypt_cmd: the encryption "command" to be executed, currently 797 supported values are "new_key", "inherit", "force_new_key" and 798 "force_inherit". 799 :param props: a `dict` of encryption-related property name-value pairs; 800 only "keyformat", "keylocation" and "pbkdf2iters" are supported 801 (empty by default). 802 :type props: dict of bytes:Any 803 :param key: dataset encryption key data (empty by default). 804 :type key: bytes 805 806 :raises PropertyInvalid: if ``props`` contains invalid values. 807 :raises FilesystemNotFound: if the dataset does not exist. 808 :raises UnknownCryptCommand: if ``crypt_cmd`` is invalid. 809 :raises EncryptionKeyNotLoaded: if the encryption key is not currently 810 loaded and therefore cannot be changed. 811 ''' 812 if props is None: 813 props = {} 814 if key is None: 815 key = b"" 816 else: 817 key = bytes(key) 818 cmd = { 819 'new_key': _lib.DCP_CMD_NEW_KEY, 820 'inherit': _lib.DCP_CMD_INHERIT, 821 'force_new_key': _lib.DCP_CMD_FORCE_NEW_KEY, 822 'force_inherit': _lib.DCP_CMD_FORCE_INHERIT, 823 }.get(crypt_cmd) 824 if cmd is None: 825 raise exceptions.UnknownCryptCommand(crypt_cmd) 826 nvlist = nvlist_in(props) 827 ret = _lib.lzc_change_key(fsname, cmd, nvlist, key, len(key)) 828 errors.lzc_change_key_translate_error(ret, fsname) 829 830 831def lzc_load_key(fsname, noop, key): 832 ''' 833 Load or verify encryption key on the specified dataset. 834 835 :param bytes fsname: the name of the dataset. 836 :param bool noop: if `True` the encryption key will only be verified, 837 not loaded. 838 :param key: dataset encryption key data. 839 :type key: bytes 840 841 :raises FilesystemNotFound: if the dataset does not exist. 842 :raises EncryptionKeyAlreadyLoaded: if the encryption key is already 843 loaded. 844 :raises EncryptionKeyInvalid: if the encryption key provided is incorrect. 845 ''' 846 ret = _lib.lzc_load_key(fsname, noop, key, len(key)) 847 errors.lzc_load_key_translate_error(ret, fsname, noop) 848 849 850def lzc_unload_key(fsname): 851 ''' 852 Unload encryption key from the specified dataset. 853 854 :param bytes fsname: the name of the dataset. 855 856 :raises FilesystemNotFound: if the dataset does not exist. 857 :raises DatasetBusy: if the encryption key is still being used. This 858 usually occurs when the dataset is mounted. 859 :raises EncryptionKeyNotLoaded: if the encryption key is not currently 860 loaded. 861 ''' 862 ret = _lib.lzc_unload_key(fsname) 863 errors.lzc_unload_key_translate_error(ret, fsname) 864 865 866def lzc_channel_program( 867 poolname, program, instrlimit=ZCP_DEFAULT_INSTRLIMIT, 868 memlimit=ZCP_DEFAULT_MEMLIMIT, params=None 869): 870 ''' 871 Executes a script as a ZFS channel program on pool ``poolname``. 872 873 :param bytes poolname: the name of the pool. 874 :param bytes program: channel program text. 875 :param int instrlimit: execution time limit, in milliseconds. 876 :param int memlimit: execution memory limit, in bytes. 877 :param bytes params: a `list` of parameters passed to the channel program 878 (empty by default). 879 :type params: dict of bytes:Any 880 :return: a dictionary of result values procuced by the channel program, 881 if any. 882 :rtype: dict 883 884 :raises PoolNotFound: if the pool does not exist. 885 :raises ZCPLimitInvalid: if either instruction or memory limit are invalid. 886 :raises ZCPSyntaxError: if the channel program contains syntax errors. 887 :raises ZCPTimeout: if the channel program took too long to execute. 888 :raises ZCPSpaceError: if the channel program exhausted the memory limit. 889 :raises ZCPMemoryError: if the channel program return value was too large. 890 :raises ZCPPermissionError: if the user lacks the permission to run the 891 channel program. Channel programs must be run as root. 892 :raises ZCPRuntimeError: if the channel program encountered a runtime 893 error. 894 ''' 895 output = {} 896 params_nv = nvlist_in({b"argv": params}) 897 with nvlist_out(output) as outnvl: 898 ret = _lib.lzc_channel_program( 899 poolname, program, instrlimit, memlimit, params_nv, outnvl) 900 errors.lzc_channel_program_translate_error( 901 ret, poolname, output.get(b"error")) 902 return output.get(b"return") 903 904 905def lzc_channel_program_nosync( 906 poolname, program, instrlimit=ZCP_DEFAULT_INSTRLIMIT, 907 memlimit=ZCP_DEFAULT_MEMLIMIT, params=None 908): 909 ''' 910 Executes a script as a read-only ZFS channel program on pool ``poolname``. 911 A read-only channel program works programmatically the same way as a 912 normal channel program executed with 913 :func:`lzc_channel_program`. The only difference is it runs exclusively in 914 open-context and therefore can return faster. 915 The downside to that, is that the program cannot change on-disk state by 916 calling functions from the zfs.sync submodule. 917 918 :param bytes poolname: the name of the pool. 919 :param bytes program: channel program text. 920 :param int instrlimit: execution time limit, in milliseconds. 921 :param int memlimit: execution memory limit, in bytes. 922 :param bytes params: a `list` of parameters passed to the channel program 923 (empty by default). 924 :type params: dict of bytes:Any 925 :return: a dictionary of result values procuced by the channel program, 926 if any. 927 :rtype: dict 928 929 :raises PoolNotFound: if the pool does not exist. 930 :raises ZCPLimitInvalid: if either instruction or memory limit are invalid. 931 :raises ZCPSyntaxError: if the channel program contains syntax errors. 932 :raises ZCPTimeout: if the channel program took too long to execute. 933 :raises ZCPSpaceError: if the channel program exhausted the memory limit. 934 :raises ZCPMemoryError: if the channel program return value was too large. 935 :raises ZCPPermissionError: if the user lacks the permission to run the 936 channel program. Channel programs must be run as root. 937 :raises ZCPRuntimeError: if the channel program encountered a runtime 938 error. 939 ''' 940 output = {} 941 params_nv = nvlist_in({b"argv": params}) 942 with nvlist_out(output) as outnvl: 943 ret = _lib.lzc_channel_program_nosync( 944 poolname, program, instrlimit, memlimit, params_nv, outnvl) 945 errors.lzc_channel_program_translate_error( 946 ret, poolname, output.get(b"error")) 947 return output.get(b"return") 948 949 950def lzc_receive_resumable( 951 snapname, fd, force=False, raw=False, origin=None, props=None 952): 953 ''' 954 Like :func:`lzc_receive`, but if the receive fails due to premature stream 955 termination, the intermediate state will be preserved on disk. In this 956 case, ECKSUM will be returned. The receive may subsequently be resumed 957 with a resuming send stream generated by lzc_send_resume(). 958 959 :param bytes snapname: the name of the snapshot to create. 960 :param int fd: the file descriptor from which to read the stream. 961 :param bool force: whether to roll back or destroy the target filesystem 962 if that is required to receive the stream. 963 :param bool raw: whether this is a "raw" stream. 964 :param origin: the optional origin snapshot name if the stream is for a 965 clone. 966 :type origin: bytes or None 967 :param props: the properties to set on the snapshot as *received* 968 properties. 969 :type props: dict of bytes : Any 970 971 :raises IOError: if an input / output error occurs while reading from the 972 ``fd``. 973 :raises DatasetExists: if the snapshot named ``snapname`` already exists. 974 :raises DatasetExists: if the stream is a full stream and the destination 975 filesystem already exists. 976 :raises DatasetExists: if ``force`` is `True` but the destination 977 filesystem could not be rolled back to a matching snapshot because a 978 newer snapshot exists and it is an origin of a cloned filesystem. 979 :raises StreamMismatch: if an incremental stream is received and the latest 980 snapshot of the destination filesystem does not match the source 981 snapshot of the stream. 982 :raises StreamMismatch: if a full stream is received and the destination 983 filesystem already exists and it has at least one snapshot, and 984 ``force`` is `False`. 985 :raises StreamMismatch: if an incremental clone stream is received but the 986 specified ``origin`` is not the actual received origin. 987 :raises DestinationModified: if an incremental stream is received and the 988 destination filesystem has been modified since the last snapshot and 989 ``force`` is `False`. 990 :raises DestinationModified: if a full stream is received and the 991 destination filesystem already exists and it does not have any 992 snapshots, and ``force`` is `False`. 993 :raises DatasetNotFound: if the destination filesystem and its parent do 994 not exist. 995 :raises DatasetNotFound: if the ``origin`` is not `None` and does not 996 exist. 997 :raises DatasetBusy: if ``force`` is `True` but the destination filesystem 998 could not be rolled back to a matching snapshot because a newer 999 snapshot is held and could not be destroyed. 1000 :raises DatasetBusy: if another receive operation is being performed on the 1001 destination filesystem. 1002 :raises BadStream: if the stream is corrupt or it is not recognized or it 1003 is a compound stream or it is a clone stream, but ``origin`` is `None`. 1004 :raises BadStream: if a clone stream is received and the destination 1005 filesystem already exists. 1006 :raises StreamFeatureNotSupported: if the stream has a feature that is not 1007 supported on this side. 1008 :raises NameInvalid: if the name of either snapshot is invalid. 1009 :raises NameTooLong: if the name of either snapshot is too long. 1010 ''' 1011 1012 if origin is not None: 1013 c_origin = origin 1014 else: 1015 c_origin = _ffi.NULL 1016 if props is None: 1017 props = {} 1018 nvlist = nvlist_in(props) 1019 ret = _lib.lzc_receive_resumable( 1020 snapname, nvlist, c_origin, force, raw, fd) 1021 errors.lzc_receive_translate_errors( 1022 ret, snapname, fd, force, raw, False, False, origin, None) 1023 1024 1025def lzc_receive_with_header( 1026 snapname, fd, begin_record, force=False, resumable=False, raw=False, 1027 origin=None, props=None 1028): 1029 ''' 1030 Like :func:`lzc_receive`, but allows the caller to read the begin record 1031 and then to pass it in. 1032 1033 That could be useful if the caller wants to derive, for example, 1034 the snapname or the origin parameters based on the information contained in 1035 the begin record. 1036 :func:`receive_header` can be used to receive the begin record from the 1037 file descriptor. 1038 1039 :param bytes snapname: the name of the snapshot to create. 1040 :param int fd: the file descriptor from which to read the stream. 1041 :param begin_record: the stream's begin record. 1042 :type begin_record: ``cffi`` `CData` representing the dmu_replay_record_t 1043 structure. 1044 :param bool force: whether to roll back or destroy the target filesystem 1045 if that is required to receive the stream. 1046 :param bool resumable: whether this stream should be treated as resumable. 1047 If the receive fails due to premature stream termination, the 1048 intermediate state will be preserved on disk and may subsequently be 1049 resumed with :func:`lzc_send_resume`. 1050 :param bool raw: whether this is a "raw" stream. 1051 :param origin: the optional origin snapshot name if the stream is for a 1052 clone. 1053 :type origin: bytes or None 1054 :param props: the properties to set on the snapshot as *received* 1055 properties. 1056 :type props: dict of bytes : Any 1057 1058 :raises IOError: if an input / output error occurs while reading from the 1059 ``fd``. 1060 :raises DatasetExists: if the snapshot named ``snapname`` already exists. 1061 :raises DatasetExists: if the stream is a full stream and the destination 1062 filesystem already exists. 1063 :raises DatasetExists: if ``force`` is `True` but the destination 1064 filesystem could not be rolled back to a matching snapshot because a 1065 newer snapshot exists and it is an origin of a cloned filesystem. 1066 :raises StreamMismatch: if an incremental stream is received and the latest 1067 snapshot of the destination filesystem does not match the source 1068 snapshot of the stream. 1069 :raises StreamMismatch: if a full stream is received and the destination 1070 filesystem already exists and it has at least one snapshot, and 1071 ``force`` is `False`. 1072 :raises StreamMismatch: if an incremental clone stream is received but the 1073 specified ``origin`` is not the actual received origin. 1074 :raises DestinationModified: if an incremental stream is received and the 1075 destination filesystem has been modified since the last snapshot and 1076 ``force`` is `False`. 1077 :raises DestinationModified: if a full stream is received and the 1078 destination filesystem already exists and it does not have any 1079 snapshots, and ``force`` is `False`. 1080 :raises DatasetNotFound: if the destination filesystem and its parent do 1081 not exist. 1082 :raises DatasetNotFound: if the ``origin`` is not `None` and does not 1083 exist. 1084 :raises DatasetBusy: if ``force`` is `True` but the destination filesystem 1085 could not be rolled back to a matching snapshot because a newer 1086 snapshot is held and could not be destroyed. 1087 :raises DatasetBusy: if another receive operation is being performed on the 1088 destination filesystem. 1089 :raises BadStream: if the stream is corrupt or it is not recognized or it 1090 is a compound stream or it is a clone stream, but ``origin`` is `None`. 1091 :raises BadStream: if a clone stream is received and the destination 1092 filesystem already exists. 1093 :raises StreamFeatureNotSupported: if the stream has a feature that is not 1094 supported on this side. 1095 :raises NameInvalid: if the name of either snapshot is invalid. 1096 :raises NameTooLong: if the name of either snapshot is too long. 1097 ''' 1098 1099 if origin is not None: 1100 c_origin = origin 1101 else: 1102 c_origin = _ffi.NULL 1103 if props is None: 1104 props = {} 1105 nvlist = nvlist_in(props) 1106 ret = _lib.lzc_receive_with_header( 1107 snapname, nvlist, c_origin, force, resumable, raw, fd, begin_record) 1108 errors.lzc_receive_translate_errors( 1109 ret, snapname, fd, force, raw, False, False, origin, None) 1110 1111 1112def receive_header(fd): 1113 ''' 1114 Read the begin record of the ZFS backup stream from the given file 1115 descriptor. 1116 1117 This is a helper function for :func:`lzc_receive_with_header`. 1118 1119 :param int fd: the file descriptor from which to read the stream. 1120 :return: a tuple with two elements where the first one is a Python `dict` 1121 representing the fields of the begin record and the second one is an 1122 opaque object suitable for passing to :func:`lzc_receive_with_header`. 1123 :raises IOError: if an input / output error occurs while reading from the 1124 ``fd``. 1125 1126 At present the following fields can be of interest in the header: 1127 1128 drr_toname : bytes 1129 the name of the snapshot for which the stream has been created 1130 drr_toguid : integer 1131 the GUID of the snapshot for which the stream has been created 1132 drr_fromguid : integer 1133 the GUID of the starting snapshot in the case the stream is 1134 incremental, zero otherwise 1135 drr_flags : integer 1136 the flags describing the stream's properties 1137 drr_type : integer 1138 the type of the dataset for which the stream has been created 1139 (volume, filesystem) 1140 ''' 1141 # read sizeof(dmu_replay_record_t) bytes directly into the memory backing 1142 # 'record' 1143 record = _ffi.new("dmu_replay_record_t *") 1144 _ffi.buffer(record)[:] = os.read(fd, _ffi.sizeof(record[0])) 1145 # get drr_begin member and its representation as a Python dict 1146 drr_begin = record.drr_u.drr_begin 1147 header = {} 1148 for field, descr in _ffi.typeof(drr_begin).fields: 1149 if descr.type.kind == 'primitive': 1150 header[field] = getattr(drr_begin, field) 1151 elif descr.type.kind == 'enum': 1152 header[field] = getattr(drr_begin, field) 1153 elif descr.type.kind == 'array' and descr.type.item.cname == 'char': 1154 header[field] = _ffi.string(getattr(drr_begin, field)) 1155 else: 1156 raise TypeError( 1157 'Unexpected field type in drr_begin: ' + str(descr.type)) 1158 return (header, record) 1159 1160 1161def lzc_receive_one( 1162 snapname, fd, begin_record, force=False, resumable=False, raw=False, 1163 origin=None, props=None, cleanup_fd=-1, action_handle=0 1164): 1165 ''' 1166 Like :func:`lzc_receive`, but allows the caller to pass all supported 1167 arguments and retrieve all values returned. The only additional input 1168 parameter is 'cleanup_fd' which is used to set a cleanup-on-exit file 1169 descriptor. 1170 1171 :param bytes snapname: the name of the snapshot to create. 1172 :param int fd: the file descriptor from which to read the stream. 1173 :param begin_record: the stream's begin record. 1174 :type begin_record: ``cffi`` `CData` representing the dmu_replay_record_t 1175 structure. 1176 :param bool force: whether to roll back or destroy the target filesystem 1177 if that is required to receive the stream. 1178 :param bool resumable: whether this stream should be treated as resumable. 1179 If the receive fails due to premature stream termination, the 1180 intermediate state will be preserved on disk and may subsequently be 1181 resumed with :func:`lzc_send_resume`. 1182 :param bool raw: whether this is a "raw" stream. 1183 :param origin: the optional origin snapshot name if the stream is for a 1184 clone. 1185 :type origin: bytes or None 1186 :param props: the properties to set on the snapshot as *received* 1187 properties. 1188 :type props: dict of bytes : Any 1189 :param int cleanup_fd: file descriptor used to set a cleanup-on-exit file 1190 descriptor. 1191 :param int action_handle: variable used to pass the handle for guid/ds 1192 mapping: this should be set to zero on first call and will contain an 1193 updated handle on success, which should be passed in subsequent calls. 1194 1195 :return: a tuple with two elements where the first one is the number of 1196 bytes read from the file descriptor and the second one is the 1197 action_handle return value. 1198 1199 :raises IOError: if an input / output error occurs while reading from the 1200 ``fd``. 1201 :raises DatasetExists: if the snapshot named ``snapname`` already exists. 1202 :raises DatasetExists: if the stream is a full stream and the destination 1203 filesystem already exists. 1204 :raises DatasetExists: if ``force`` is `True` but the destination 1205 filesystem could not be rolled back to a matching snapshot because a 1206 newer snapshot exists and it is an origin of a cloned filesystem. 1207 :raises StreamMismatch: if an incremental stream is received and the latest 1208 snapshot of the destination filesystem does not match the source 1209 snapshot of the stream. 1210 :raises StreamMismatch: if a full stream is received and the destination 1211 filesystem already exists and it has at least one snapshot, and 1212 ``force`` is `False`. 1213 :raises StreamMismatch: if an incremental clone stream is received but the 1214 specified ``origin`` is not the actual received origin. 1215 :raises DestinationModified: if an incremental stream is received and the 1216 destination filesystem has been modified since the last snapshot and 1217 ``force`` is `False`. 1218 :raises DestinationModified: if a full stream is received and the 1219 destination filesystem already exists and it does not have any 1220 snapshots, and ``force`` is `False`. 1221 :raises DatasetNotFound: if the destination filesystem and its parent do 1222 not exist. 1223 :raises DatasetNotFound: if the ``origin`` is not `None` and does not 1224 exist. 1225 :raises DatasetBusy: if ``force`` is `True` but the destination filesystem 1226 could not be rolled back to a matching snapshot because a newer 1227 snapshot is held and could not be destroyed. 1228 :raises DatasetBusy: if another receive operation is being performed on the 1229 destination filesystem. 1230 :raises BadStream: if the stream is corrupt or it is not recognized or it 1231 is a compound stream or it is a clone stream, but ``origin`` is `None`. 1232 :raises BadStream: if a clone stream is received and the destination 1233 filesystem already exists. 1234 :raises StreamFeatureNotSupported: if the stream has a feature that is not 1235 supported on this side. 1236 :raises ReceivePropertyFailure: if one or more of the specified properties 1237 is invalid or has an invalid type or value. 1238 :raises NameInvalid: if the name of either snapshot is invalid. 1239 :raises NameTooLong: if the name of either snapshot is too long. 1240 ''' 1241 1242 if origin is not None: 1243 c_origin = origin 1244 else: 1245 c_origin = _ffi.NULL 1246 if action_handle is not None: 1247 c_action_handle = _ffi.new("uint64_t *") 1248 else: 1249 c_action_handle = _ffi.NULL 1250 c_read_bytes = _ffi.new("uint64_t *") 1251 c_errflags = _ffi.new("uint64_t *") 1252 if props is None: 1253 props = {} 1254 nvlist = nvlist_in(props) 1255 properrs = {} 1256 with nvlist_out(properrs) as c_errors: 1257 ret = _lib.lzc_receive_one( 1258 snapname, nvlist, c_origin, force, resumable, raw, fd, 1259 begin_record, cleanup_fd, c_read_bytes, c_errflags, 1260 c_action_handle, c_errors) 1261 errors.lzc_receive_translate_errors( 1262 ret, snapname, fd, force, raw, False, False, origin, properrs) 1263 return (int(c_read_bytes[0]), action_handle) 1264 1265 1266def lzc_receive_with_cmdprops( 1267 snapname, fd, begin_record, force=False, resumable=False, raw=False, 1268 origin=None, props=None, cmdprops=None, key=None, cleanup_fd=-1, 1269 action_handle=0 1270): 1271 ''' 1272 Like :func:`lzc_receive_one`, but allows the caller to pass an additional 1273 'cmdprops' argument. The 'cmdprops' nvlist contains both override 1274 ('zfs receive -o') and exclude ('zfs receive -x') properties. 1275 1276 :param bytes snapname: the name of the snapshot to create. 1277 :param int fd: the file descriptor from which to read the stream. 1278 :param begin_record: the stream's begin record. 1279 :type begin_record: ``cffi`` `CData` representing the dmu_replay_record_t 1280 structure. 1281 :param bool force: whether to roll back or destroy the target filesystem 1282 if that is required to receive the stream. 1283 :param bool resumable: whether this stream should be treated as resumable. 1284 If the receive fails due to premature stream termination, the 1285 intermediate state will be preserved on disk and may subsequently be 1286 resumed with :func:`lzc_send_resume`. 1287 :param bool raw: whether this is a "raw" stream. 1288 :param origin: the optional origin snapshot name if the stream is for a 1289 clone. 1290 :type origin: bytes or None 1291 :param props: the properties to set on the snapshot as *received* 1292 properties. 1293 :type props: dict of bytes : Any 1294 :param cmdprops: the properties to set on the snapshot as local overrides 1295 to *received* properties. `bool` values are forcefully inherited while 1296 every other value is set locally as if the command "zfs set" was 1297 invoked immediately before the receive. 1298 :type cmdprops: dict of bytes : Any 1299 :param key: raw bytes representing user's wrapping key 1300 :type key: bytes 1301 :param int cleanup_fd: file descriptor used to set a cleanup-on-exit file 1302 descriptor. 1303 :param int action_handle: variable used to pass the handle for guid/ds 1304 mapping: this should be set to zero on first call and will contain an 1305 updated handle on success, it should be passed in subsequent calls. 1306 1307 :return: a tuple with two elements where the first one is the number of 1308 bytes read from the file descriptor and the second one is the 1309 action_handle return value. 1310 1311 :raises IOError: if an input / output error occurs while reading from the 1312 ``fd``. 1313 :raises DatasetExists: if the snapshot named ``snapname`` already exists. 1314 :raises DatasetExists: if the stream is a full stream and the destination 1315 filesystem already exists. 1316 :raises DatasetExists: if ``force`` is `True` but the destination 1317 filesystem could not be rolled back to a matching snapshot because a 1318 newer snapshot exists and it is an origin of a cloned filesystem. 1319 :raises StreamMismatch: if an incremental stream is received and the latest 1320 snapshot of the destination filesystem does not match the source 1321 snapshot of the stream. 1322 :raises StreamMismatch: if a full stream is received and the destination 1323 filesystem already exists and it has at least one snapshot, and 1324 ``force`` is `False`. 1325 :raises StreamMismatch: if an incremental clone stream is received but the 1326 specified ``origin`` is not the actual received origin. 1327 :raises DestinationModified: if an incremental stream is received and the 1328 destination filesystem has been modified since the last snapshot and 1329 ``force`` is `False`. 1330 :raises DestinationModified: if a full stream is received and the 1331 destination filesystem already exists and it does not have any 1332 snapshots, and ``force`` is `False`. 1333 :raises DatasetNotFound: if the destination filesystem and its parent do 1334 not exist. 1335 :raises DatasetNotFound: if the ``origin`` is not `None` and does not 1336 exist. 1337 :raises DatasetBusy: if ``force`` is `True` but the destination filesystem 1338 could not be rolled back to a matching snapshot because a newer 1339 snapshot is held and could not be destroyed. 1340 :raises DatasetBusy: if another receive operation is being performed on the 1341 destination filesystem. 1342 :raises BadStream: if the stream is corrupt or it is not recognized or it 1343 is a compound stream or it is a clone stream, but ``origin`` is `None`. 1344 :raises BadStream: if a clone stream is received and the destination 1345 filesystem already exists. 1346 :raises StreamFeatureNotSupported: if the stream has a feature that is not 1347 supported on this side. 1348 :raises ReceivePropertyFailure: if one or more of the specified properties 1349 is invalid or has an invalid type or value. 1350 :raises NameInvalid: if the name of either snapshot is invalid. 1351 :raises NameTooLong: if the name of either snapshot is too long. 1352 ''' 1353 1354 if origin is not None: 1355 c_origin = origin 1356 else: 1357 c_origin = _ffi.NULL 1358 if action_handle is not None: 1359 c_action_handle = _ffi.new("uint64_t *") 1360 else: 1361 c_action_handle = _ffi.NULL 1362 c_read_bytes = _ffi.new("uint64_t *") 1363 c_errflags = _ffi.new("uint64_t *") 1364 if props is None: 1365 props = {} 1366 if cmdprops is None: 1367 cmdprops = {} 1368 if key is None: 1369 key = b"" 1370 else: 1371 key = bytes(key) 1372 1373 nvlist = nvlist_in(props) 1374 cmdnvlist = nvlist_in(cmdprops) 1375 properrs = {} 1376 with nvlist_out(properrs) as c_errors: 1377 ret = _lib.lzc_receive_with_cmdprops( 1378 snapname, nvlist, cmdnvlist, key, len(key), c_origin, 1379 force, resumable, raw, fd, begin_record, cleanup_fd, c_read_bytes, 1380 c_errflags, c_action_handle, c_errors) 1381 errors.lzc_receive_translate_errors( 1382 ret, snapname, fd, force, raw, False, False, origin, properrs) 1383 return (int(c_read_bytes[0]), action_handle) 1384 1385 1386def lzc_receive_with_heal( 1387 snapname, fd, begin_record, force=False, corrective=True, resumable=False, 1388 raw=False, origin=None, props=None, cmdprops=None, key=None, cleanup_fd=-1, 1389 action_handle=0 1390): 1391 ''' 1392 Like :func:`lzc_receive_cmdprops`, but allows the caller to pass an 1393 additional 'corrective' argument. The 'corrective' boolean set to true 1394 indicates that a corruption healing receive should be performed. 1395 1396 :param bytes snapname: the name of the snapshot to create. 1397 :param int fd: the file descriptor from which to read the stream. 1398 :param begin_record: the stream's begin record. 1399 :type begin_record: ``cffi`` `CData` representing the dmu_replay_record_t 1400 structure. 1401 :param bool force: whether to roll back or destroy the target filesystem 1402 if that is required to receive the stream. 1403 :param bool corrective: whether this stream should be used to heal data. 1404 :param bool resumable: whether this stream should be treated as resumable. 1405 If the receive fails due to premature stream termination, the 1406 intermediate state will be preserved on disk and may subsequently be 1407 resumed with :func:`lzc_send_resume`. 1408 :param bool raw: whether this is a "raw" stream. 1409 :param origin: the optional origin snapshot name if the stream is for a 1410 clone. 1411 :type origin: bytes or None 1412 :param props: the properties to set on the snapshot as *received* 1413 properties. 1414 :type props: dict of bytes : Any 1415 :param cmdprops: the properties to set on the snapshot as local overrides 1416 to *received* properties. `bool` values are forcefully inherited while 1417 every other value is set locally as if the command "zfs set" was 1418 invoked immediately before the receive. 1419 :type cmdprops: dict of bytes : Any 1420 :param key: raw bytes representing user's wrapping key 1421 :type key: bytes 1422 :param int cleanup_fd: file descriptor used to set a cleanup-on-exit file 1423 descriptor. 1424 :param int action_handle: variable used to pass the handle for guid/ds 1425 mapping: this should be set to zero on first call and will contain an 1426 updated handle on success, it should be passed in subsequent calls. 1427 1428 :return: a tuple with two elements where the first one is the number of 1429 bytes read from the file descriptor and the second one is the 1430 action_handle return value. 1431 1432 :raises IOError: if an input / output error occurs while reading from the 1433 ``fd``. 1434 :raises DatasetExists: if the snapshot named ``snapname`` already exists. 1435 :raises DatasetExists: if the stream is a full stream and the destination 1436 filesystem already exists. 1437 :raises DatasetExists: if ``force`` is `True` but the destination 1438 filesystem could not be rolled back to a matching snapshot because a 1439 newer snapshot exists and it is an origin of a cloned filesystem. 1440 :raises StreamMismatch: if an incremental stream is received and the latest 1441 snapshot of the destination filesystem does not match the source 1442 snapshot of the stream. 1443 :raises StreamMismatch: if a full stream is received and the destination 1444 filesystem already exists and it has at least one snapshot, and 1445 ``force`` is `False`. 1446 :raises StreamMismatch: if an incremental clone stream is received but the 1447 specified ``origin`` is not the actual received origin. 1448 :raises DestinationModified: if an incremental stream is received and the 1449 destination filesystem has been modified since the last snapshot and 1450 ``force`` is `False`. 1451 :raises DestinationModified: if a full stream is received and the 1452 destination filesystem already exists and it does not have any 1453 snapshots, and ``force`` is `False`. 1454 :raises DatasetNotFound: if the destination filesystem and its parent do 1455 not exist. 1456 :raises DatasetNotFound: if the ``origin`` is not `None` and does not 1457 exist. 1458 :raises DatasetBusy: if ``force`` is `True` but the destination filesystem 1459 could not be rolled back to a matching snapshot because a newer 1460 snapshot is held and could not be destroyed. 1461 :raises DatasetBusy: if another receive operation is being performed on the 1462 destination filesystem. 1463 :raises EncryptionKeyNotLoaded: if corrective is set to true indicates the 1464 key must be loaded to do a non-raw corrective recv on an encrypted 1465 dataset. 1466 :raises BadStream: if corrective is set to true indicates that 1467 corrective recv was not able to reconstruct a corrupted block. 1468 :raises BadStream: if the stream is corrupt or it is not recognized or it 1469 is a compound stream or it is a clone stream, but ``origin`` is `None`. 1470 :raises BadStream: if a clone stream is received and the destination 1471 filesystem already exists. 1472 :raises StreamFeatureNotSupported: if corrective is set to true indicates 1473 stream is not compatible with the data in the pool. 1474 :raises StreamFeatureNotSupported: if the stream has a feature that is not 1475 supported on this side. 1476 :raises ReceivePropertyFailure: if one or more of the specified properties 1477 is invalid or has an invalid type or value. 1478 :raises NameInvalid: if the name of either snapshot is invalid. 1479 :raises NameTooLong: if the name of either snapshot is too long. 1480 ''' 1481 1482 if origin is not None: 1483 c_origin = origin 1484 else: 1485 c_origin = _ffi.NULL 1486 if action_handle is not None: 1487 c_action_handle = _ffi.new("uint64_t *") 1488 else: 1489 c_action_handle = _ffi.NULL 1490 c_read_bytes = _ffi.new("uint64_t *") 1491 c_errflags = _ffi.new("uint64_t *") 1492 if props is None: 1493 props = {} 1494 if cmdprops is None: 1495 cmdprops = {} 1496 if key is None: 1497 key = b"" 1498 else: 1499 key = bytes(key) 1500 1501 nvlist = nvlist_in(props) 1502 cmdnvlist = nvlist_in(cmdprops) 1503 properrs = {} 1504 with nvlist_out(properrs) as c_errors: 1505 ret = _lib.lzc_receive_with_heal( 1506 snapname, nvlist, cmdnvlist, key, len(key), c_origin, 1507 force, corrective, resumable, raw, fd, begin_record, cleanup_fd, 1508 c_read_bytes, c_errflags, c_action_handle, c_errors) 1509 errors.lzc_receive_translate_errors( 1510 ret, snapname, fd, force, raw, False, False, origin, properrs) 1511 return (int(c_read_bytes[0]), action_handle) 1512 1513 1514def lzc_reopen(poolname, restart=True): 1515 ''' 1516 Reopen a pool 1517 1518 :param bytes poolname: the name of the pool. 1519 :param bool restart: whether to restart an in-progress scrub operation. 1520 1521 :raises PoolNotFound: if the pool does not exist. 1522 ''' 1523 ret = _lib.lzc_reopen(poolname, restart) 1524 errors.lzc_reopen_translate_error(ret, poolname) 1525 1526 1527def lzc_send_resume( 1528 snapname, fromsnap, fd, flags=None, resumeobj=0, resumeoff=0 1529): 1530 ''' 1531 Resume a previously interrupted send operation generating a zfs send stream 1532 for the specified snapshot and writing it to the specified file descriptor. 1533 1534 :param bytes snapname: the name of the snapshot to send. 1535 :param fromsnap: if not None the name of the starting snapshot 1536 for the incremental stream. 1537 :type fromsnap: bytes or None 1538 :param int fd: the file descriptor to write the send stream to. 1539 :param flags: the flags that control what enhanced features can be used in 1540 the stream. 1541 :type flags: list of bytes 1542 :param int resumeobj: the object number where this send stream should 1543 resume from. 1544 :param int resumeoff: the offset where this send stream should resume from. 1545 1546 :raises SnapshotNotFound: if either the starting snapshot is not `None` and 1547 does not exist, or if the ending snapshot does not exist. 1548 :raises NameInvalid: if the name of either snapshot is invalid. 1549 :raises NameTooLong: if the name of either snapshot is too long. 1550 :raises SnapshotMismatch: if ``fromsnap`` is not an ancestor snapshot of 1551 ``snapname``. 1552 :raises PoolsDiffer: if the snapshots belong to different pools. 1553 :raises IOError: if an input / output error occurs while writing to ``fd``. 1554 :raises UnknownStreamFeature: if the ``flags`` contain an unknown flag 1555 name. 1556 1557 .. note:: 1558 See :func:`lzc_send` for more information. 1559 ''' 1560 if fromsnap is not None: 1561 c_fromsnap = fromsnap 1562 else: 1563 c_fromsnap = _ffi.NULL 1564 c_flags = 0 1565 if flags is None: 1566 flags = [] 1567 for flag in flags: 1568 c_flag = { 1569 'embedded_data': _lib.LZC_SEND_FLAG_EMBED_DATA, 1570 'large_blocks': _lib.LZC_SEND_FLAG_LARGE_BLOCK, 1571 'compress': _lib.LZC_SEND_FLAG_COMPRESS, 1572 'raw': _lib.LZC_SEND_FLAG_RAW, 1573 }.get(flag) 1574 if c_flag is None: 1575 raise exceptions.UnknownStreamFeature(flag) 1576 c_flags |= c_flag 1577 1578 ret = _lib.lzc_send_resume( 1579 snapname, c_fromsnap, fd, c_flags, uint64_t(resumeobj), 1580 uint64_t(resumeoff)) 1581 errors.lzc_send_translate_error(ret, snapname, fromsnap, fd, flags) 1582 1583 1584def lzc_sync(poolname, force=False): 1585 ''' 1586 Forces all in-core dirty data to be written to the primary pool storage 1587 and not the ZIL. 1588 1589 :param bytes poolname: the name of the pool. 1590 :param bool force: whether to force uberblock update even if there is no 1591 dirty data. 1592 1593 :raises PoolNotFound: if the pool does not exist. 1594 1595 .. note:: 1596 This method signature is different from its C libzfs_core counterpart: 1597 `innvl` has been replaced by the `force` boolean and `outnvl` has been 1598 conveniently removed since it's not used. 1599 ''' 1600 innvl = nvlist_in({b"force": force}) 1601 with nvlist_out({}) as outnvl: 1602 ret = _lib.lzc_sync(poolname, innvl, outnvl) 1603 errors.lzc_sync_translate_error(ret, poolname) 1604 1605 1606def is_supported(func): 1607 ''' 1608 Check whether C *libzfs_core* provides implementation required 1609 for the given Python wrapper. 1610 1611 If `is_supported` returns ``False`` for the function, then 1612 calling the function would result in :exc:`NotImplementedError`. 1613 1614 :param function func: the function to check. 1615 :return bool: whether the function can be used. 1616 ''' 1617 fname = func.__name__ 1618 if fname not in globals(): 1619 raise ValueError(fname + ' is not from libzfs_core') 1620 if not callable(func): 1621 raise ValueError(fname + ' is not a function') 1622 if not fname.startswith("lzc_"): 1623 raise ValueError(fname + ' is not a libzfs_core API function') 1624 check_func = getattr(func, "_check_func", None) 1625 if check_func is not None: 1626 return is_supported(check_func) 1627 return getattr(_lib, fname, None) is not None 1628 1629 1630def lzc_promote(name): 1631 ''' 1632 Promotes the ZFS dataset. 1633 1634 :param bytes name: the name of the dataset to promote. 1635 :raises NameInvalid: if the dataset name is invalid. 1636 :raises NameTooLong: if the dataset name is too long. 1637 :raises NameTooLong: if the dataset's origin has a snapshot that, if 1638 transferred to the dataset, would get a too long name. 1639 :raises NotClone: if the dataset is not a clone. 1640 :raises FilesystemNotFound: if the dataset does not exist. 1641 :raises SnapshotExists: if the dataset already has a snapshot with the same 1642 name as one of the origin's snapshots. 1643 ''' 1644 ret = _lib.lzc_promote(name, _ffi.NULL, _ffi.NULL) 1645 errors.lzc_promote_translate_error(ret, name) 1646 1647 1648def lzc_pool_checkpoint(name): 1649 ''' 1650 Creates a checkpoint for the specified pool. 1651 1652 :param bytes name: the name of the pool to create a checkpoint for. 1653 :raises CheckpointExists: if the pool already has a checkpoint. 1654 :raises CheckpointDiscarding: if ZFS is in the middle of discarding a 1655 checkpoint for this pool. 1656 :raises DeviceRemovalRunning: if a vdev is currently being removed. 1657 :raises DeviceTooBig: if one or more top-level vdevs exceed the maximum 1658 vdev size. 1659 ''' 1660 ret = _lib.lzc_pool_checkpoint(name) 1661 errors.lzc_pool_checkpoint_translate_error(ret, name) 1662 1663 1664def lzc_pool_checkpoint_discard(name): 1665 ''' 1666 Discard the checkpoint from the specified pool. 1667 1668 :param bytes name: the name of the pool to discard the checkpoint from. 1669 :raises CheckpointNotFound: if pool does not have a checkpoint. 1670 :raises CheckpointDiscarding: if ZFS is in the middle of discarding a 1671 checkpoint for this pool. 1672 ''' 1673 ret = _lib.lzc_pool_checkpoint_discard(name) 1674 errors.lzc_pool_checkpoint_discard_translate_error(ret, name) 1675 1676 1677def lzc_rename(source, target): 1678 ''' 1679 Rename the ZFS dataset. 1680 1681 :param source name: the current name of the dataset to rename. 1682 :param target name: the new name of the dataset. 1683 :raises NameInvalid: if either the source or target name is invalid. 1684 :raises NameTooLong: if either the source or target name is too long. 1685 :raises NameTooLong: if a snapshot of the source would get a too long name 1686 after renaming. 1687 :raises FilesystemNotFound: if the source does not exist. 1688 :raises FilesystemNotFound: if the target's parent does not exist. 1689 :raises FilesystemExists: if the target already exists. 1690 :raises PoolsDiffer: if the source and target belong to different pools. 1691 :raises WrongParent: if the "new" parent dataset is not a filesystem 1692 (e.g. ZVOL) 1693 ''' 1694 ret = _lib.lzc_rename(source, target) 1695 errors.lzc_rename_translate_error(ret, source, target) 1696 1697 1698def lzc_destroy(name): 1699 ''' 1700 Destroy the ZFS dataset. 1701 1702 :param bytes name: the name of the dataset to destroy. 1703 :raises NameInvalid: if the dataset name is invalid. 1704 :raises NameTooLong: if the dataset name is too long. 1705 :raises FilesystemNotFound: if the dataset does not exist. 1706 ''' 1707 ret = _lib.lzc_destroy(name) 1708 errors.lzc_destroy_translate_error(ret, name) 1709 1710 1711# TODO: a better way to init and uninit the library 1712def _initialize(): 1713 class LazyInit(object): 1714 1715 def __init__(self, lib): 1716 self._lib = lib 1717 self._inited = False 1718 self._lock = threading.Lock() 1719 1720 def __getattr__(self, name): 1721 if not self._inited: 1722 with self._lock: 1723 if not self._inited: 1724 ret = self._lib.libzfs_core_init() 1725 if ret != 0: 1726 raise exceptions.ZFSInitializationFailed(ret) 1727 self._inited = True 1728 return getattr(self._lib, name) 1729 1730 return LazyInit(libzfs_core.lib) 1731 1732 1733_ffi = libzfs_core.ffi 1734_lib = _initialize() 1735 1736 1737# vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4 1738