def __init__(self, exportName, metaContext, host="localhost", port="10809"): """TODO: to be defined. :host: TODO :port: TODO """ self._host = host self._port = port self._exportName = exportName if metaContext == None: self._metaContext = nbd.CONTEXT_BASE_ALLOCATION else: self._metaContext = metaContext self.maxRequestSize = 33554432 self.minRequestSize = 65536 self._connectionHandle = None self._nbdHandle = nbd.NBD()
def test_get_size(): """ libnbd get_size test 1) create a nbd server by nbdkit 2) check the image size by get_size 3) check the image content by pwrite and pread """ expected_size = int(params.get('image_size', 1048576)) real_size = 0 # must be a bytes-like object for pwrite expected_str = b'hello, world' handle = nbd.NBD() handle.connect_command([ "nbdkit", "--exit-with-parent", "-s", "memory", "size=%d" % expected_size ]) real_size = handle.get_size() if real_size != expected_size: test.fail('get_size failed: expected: %s, real: %s' % (expected_size, real_size)) handle.pwrite(expected_str, 0, nbd.CMD_FLAG_FUA) real_str = handle.pread(len(expected_str), 0) if real_str != expected_str: test.fail('pwrite or pread failed: expected: %s, real: %s' % (expected_str, real_str))
def conn(mode): global exports exports = [] h = nbd.NBD() try: h.set_opt_mode(True) h.connect_command([ "nbdkit", "-s", "--exit-with-parent", "-v", "sh", script, "mode=%d" % mode ]) yield h finally: h.opt_abort() h = None
def shell(): import argparse import code import sys import nbd description = '''Network Block Device (NBD) shell''' parser = argparse.ArgumentParser(prog='nbdsh', description=description) parser.add_argument('--connect', help="connect to NBD URI") parser.add_argument('-c', '--command', action='append', help="run a command") parser.add_argument('-V', '--version', action='version', version=nbd.package_name + ' ' + nbd.__version__) args = parser.parse_args() h = nbd.NBD() sys.ps1 = "nbd> " banner = ''' Welcome to nbdsh, the shell for interacting with Network Block Device (NBD) servers. The ‘nbd’ module has already been imported and there is an open NBD handle called ‘h’. h.connect_tcp ("remote", "10809") # Connect to a remote server. h.get_size () # Get size of the remote disk. buf = h.pread (512, 0, 0) # Read the first sector. exit() or Ctrl-D # Quit the shell help (nbd) # Display documentation ''' if args.connect is not None: h.connect_uri(args.connect) # If there are no -c or --command parameters, go interactive, # otherwise we run the commands and exit. if not args.command: code.interact(banner=banner, local=locals(), exitmsg='') else: for c in args.command: if c != '-': exec(c) else: exec(sys.stdin.read())
def __new__(cls, data): if not data.get('two_phase', False): return None try: import nbd except ImportError: raise RuntimeError('libnbd is not available, it is required for ' 'two-phase conversion') nbd_version = version.parse(nbd.NBD().get_version()) if nbd_version < NBD_MIN_VERSION: raise RuntimeError('libnbd is too old (%s), ' 'minimum version required is %s' % (nbd_version, NBD_MIN_VERSION)) return super(PreCopy, cls).__new__(cls)
def __init__(self, exportName, metaContext, backupSocket): """Parameters: :exportName: name of nbd export :backupSocket: ndb server endpoint """ self._socket = backupSocket self._exportName = exportName if metaContext is None: self._metaContext = nbd.CONTEXT_BASE_ALLOCATION else: self._metaContext = metaContext self.maxRequestSize = 33554432 self.minRequestSize = 65536 self._connectionHandle = None self._nbdHandle = nbd.NBD() self.version()
# documentation and/or other materials provided with the distribution. # # * Neither the name of Red Hat nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # Used by test-readahead.sh to make a linear series of requests # with a constant, known size. import nbd import sys h = nbd.NBD() h.connect_unix(sys.argv[1]) for i in range(0, 512*10, 512): h.pread(512, i)
def sync_disks(self, vm_id, disks_mappings, guestfs_helper, sync_index, last_sync): MAX_PREAD_LEN = 23 << 20 # 23MB (24MB requests fail in VDDK) MAX_AIO_IN_FLIGHT = 2 vm = self._find_vm_by_id(vm_id) snapshot = self.create_snapshot(vm_id, name="conversion-%s" % now.strftime('%Y%m%d-%H%M%S')) self._update_change_ids(vm_id, snapshot, disks_mappings) self._get_changed_extents(vm_id, snapshot, disks_mappings, sync_index, last_sync) for dm in disks_mappings: logging.debug("Opening locally attached disk %s" % dm["destination"]["conversion_host_path"]) fd = os.open(dm["destination"]["conversion_host_path"], os.O_WRONLY | os.O_CREAT) if len(dm["source"]["extents"]) == 0: os.close(fd) continue logging.info("Connecting the source disk %s with NBD", dm["source"]["id"]) nbd_cmd = guestfs_helper.nbd_expose_disk_cmd(dm["source"], None, vm_moref=vm._moId, sync_index=sync_index) logging.debug("NBD Command: %s", nbd_cmd) nbd_handle = nbd.NBD() nbd_handle.add_meta_context("base:allocation") nbd_handle.connect_command(nbd_cmd) logging.info("Getting block info for disk: %s" % dm["source"]["id"]) copied = 0 position = 0 data_blocks = [] for extent in dm["source"]["extents"]: if extent.length < 1 << 20: logging.debug( "Skipping block status for extent of size %d B at offset %d B" % (extent.length, extent.start)) data_blocks.append({ "offset": extent.start, "length": extent.length, "flags": 0 }) continue blocks = self._get_block_status(nbd_handle, extent) logging.debug("Gathered block status of %d: %s" % (len(blocks), blocks)) data_blocks += [ x for x in blocks if not x['flags'] & nbd.STATE_HOLE ] logging.debug("Block status filtered down to %d data blocks" % len(data_blocks)) if len(data_blocks) == 0: logging.debug("No extents have allocated data for disk: %s" % dm["source"]["id"]) os.close(fd) continue to_copy = sum([x['length'] for x in data_blocks]) logging.debug("Copying %d B of data for disk %s" % (to_copy, dm["source"]["id"])) self._state.disks[dm["source"]["id"]]["syncs"].append({ "to_copy": to_copy, "copied": 0 }) self._state.write() for block in data_blocks: logging.debug("Block at offset %s flags: %s", block["offset"], block["flags"]) if block["flags"] & nbd.STATE_ZERO: logging.debug("Writing %d B of zeros to offset %d B" % (block["length"], block["offset"])) # Optimize for memory usage, maybe? os.pwrite(fd, [0] * block["length"], block["offset"]) else: count = 0 while count < block["length"]: length = min(block["length"] - count, MAX_PREAD_LEN) offset = block["offset"] + count logging.debug("Reading %d B from offset %d B" % (length, offset)) buf = nbd.Buffer(length) nbd_handle.aio_pread( buf, offset, lambda err, fd=fd, buf=buf, offset=offset: self. _write_data(fd, buf, offset, err)) count += length while nbd_handle.aio_in_flight() > MAX_AIO_IN_FLIGHT: nbd_handle.poll(-1) guestfs_helper.nbd_process_aio_requests(nbd_handle) copied += length self._state.disks[dm["source"]["id"]]["syncs"][ sync_index]["copied"] = copied self._state.write() guestfs_helper.nbd_wait_for_aio_commands_to_finish(nbd_handle) if copied == 0: logging.debug("Nothing to copy for disk: %s" % dm["source"]["id"]) else: logging.debug("Copied %d B for disk: %s" % (copied, dm["source"]["id"])) nbd_handle.shutdown() os.close(fd) self._remove_all_snapshots(vm_id)
def shell(): import argparse import code import sys import nbd description = '''Network Block Device (NBD) shell''' epilog = '''Please read the nbdsh(1) manual page for full usage.''' parser = argparse.ArgumentParser(prog='nbdsh', description=description, epilog=epilog) short_options = [] long_options = [] parser.add_argument('--base-allocation', action='store_true', help='request the "base:allocation" meta context') long_options.append("--base-allocation") parser.add_argument('-u', '--uri', help="connect to NBD URI") short_options.append("-u") long_options.append("--uri") # For back-compat, provide --connect as an undocumented synonym to --uri parser.add_argument('--connect', dest='uri', help=argparse.SUPPRESS) parser.add_argument('-c', '--command', action='append', help="run a command") short_options.append("-c") long_options.append("--command") parser.add_argument('-V', '--version', action='version', version=nbd.package_name + ' ' + nbd.__version__) short_options.append("-V") long_options.append("--version") # These hidden options are used by bash tab completion. parser.add_argument("--short-options", action='store_true') parser.add_argument("--long-options", action='store_true') args = parser.parse_args() if args.short_options: short_options.sort() print("\n".join(short_options)) exit(0) if args.long_options: long_options.sort() print("\n".join(long_options)) exit(0) h = nbd.NBD() h.set_handle_name("nbdsh") sys.ps1 = "nbd> " banner = ''' Welcome to nbdsh, the shell for interacting with Network Block Device (NBD) servers. The ‘nbd’ module has already been imported and there is an open NBD handle called ‘h’. h.connect_tcp ("remote", "10809") # Connect to a remote server. h.get_size () # Get size of the remote disk. buf = h.pread (512, 0, 0) # Read the first sector. exit() or Ctrl-D # Quit the shell help (nbd) # Display documentation ''' if args.base_allocation: h.add_meta_context(nbd.CONTEXT_BASE_ALLOCATION) if args.uri is not None: h.connect_uri(args.uri) # If there are no -c or --command parameters, go interactive, # otherwise we run the commands and exit. if not args.command: code.interact(banner=banner, local=locals(), exitmsg='') else: # https://stackoverflow.com/a/11754346 d = dict(locals(), **globals()) for c in args.command: if c != '-': exec(c, d, d) else: exec(sys.stdin.read(), d, d)
def setUp(self): self.h = nbd.NBD()
# slept in the select. if fd == sfd and revents & select.POLLIN and \ src.aio_get_direction() & nbd.AIO_DIRECTION_READ: src.aio_notify_read() elif fd == sfd and revents & select.POLLOUT and \ src.aio_get_direction() & nbd.AIO_DIRECTION_WRITE: src.aio_notify_write() elif fd == dfd and revents & select.POLLIN and \ dst.aio_get_direction() & nbd.AIO_DIRECTION_READ: dst.aio_notify_read() elif fd == dfd and revents & select.POLLOUT and \ dst.aio_get_direction() & nbd.AIO_DIRECTION_WRITE: dst.aio_notify_write() src = nbd.NBD() src.set_handle_name("src") dst = nbd.NBD() dst.set_handle_name("dst") src.connect_command([ "nbdkit", "-s", "--exit-with-parent", "-r", "pattern", "size=%d" % disk_size ]) dst.connect_command( ["nbdkit", "-s", "--exit-with-parent", "memory", "size=%d" % disk_size]) asynch_copy(src, dst) print("bytes read: %d written: %d size: %d" % (bytes_read, bytes_written, disk_size)) assert bytes_read == disk_size
def shell(): import argparse import code import os import sys import libnbdmod import nbd description = '''Network Block Device (NBD) shell''' epilog = '''Please read the nbdsh(1) manual page for full usage.''' parser = argparse.ArgumentParser(prog='nbdsh', description=description, epilog=epilog) short_options = [] long_options = [] parser.add_argument('--base-allocation', action='store_true', help='request the "base:allocation" meta context') long_options.append("--base-allocation") parser.add_argument('-c', '--command', action='append', help="run a Python statement " "(may be used multiple times)") short_options.append("-c") long_options.append("--command") parser.add_argument('-n', action='store_true', help="do not create the implicit handle 'h'") short_options.append("-n") parser.add_argument('--opt-mode', action='store_true', help='request opt mode during connection') long_options.append("--opt-mode") parser.add_argument('-u', '--uri', help="connect to NBD URI") short_options.append("-u") long_options.append("--uri") # For back-compat, provide --connect as an undocumented synonym to --uri parser.add_argument('--connect', dest='uri', help=argparse.SUPPRESS) parser.add_argument('-v', '--verbose', action='store_true') short_options.append("-v") long_options.append("--verbose") parser.add_argument('-V', '--version', action='store_true') short_options.append("-V") long_options.append("--version") # These hidden options are used by bash tab completion. parser.add_argument("--short-options", action='store_true', help=argparse.SUPPRESS) parser.add_argument("--long-options", action='store_true', help=argparse.SUPPRESS) args = parser.parse_args() # It's an error if -n is passed with certain other options. if args.n and (args.base_allocation or args.opt_mode or args.uri is not None): print("error: -n option cannot be used with " + "--base-allocation, --opt-mode or --uri", file=sys.stderr) exit(1) # Handle the informational options which exit. if args.version: libnbdmod.display_version("nbdsh") exit(0) if args.short_options: short_options.sort() print("\n".join(short_options)) exit(0) if args.long_options: long_options.sort() print("\n".join(long_options)) exit(0) # Create the banner and prompt. banner = make_banner(args) sys.ps1 = "nbd> " # If verbose, set LIBNBD_DEBUG=1 if args.verbose: os.environ["LIBNBD_DEBUG"] = "1" # Create the handle. if not args.n: h = nbd.NBD() h.set_handle_name("nbdsh") # Set other attributes in the handle. if args.base_allocation: h.add_meta_context(nbd.CONTEXT_BASE_ALLOCATION) if args.opt_mode: h.set_opt_mode(True) # Parse the URI. if args.uri is not None: try: h.connect_uri(args.uri) except nbd.Error as ex: print("nbdsh: unable to connect to uri '%s': %s" % (args.uri, ex.string), file=sys.stderr) sys.exit(1) # If there are no -c or --command parameters, go interactive, # otherwise we run the commands and exit. if not args.command: code.interact(banner=banner, local=locals(), exitmsg='') else: # https://stackoverflow.com/a/11754346 d = dict(locals(), **globals()) try: for c in args.command: if c != '-': exec(c, d, d) else: exec(sys.stdin.read(), d, d) except nbd.Error as ex: if nbd.NBD().get_debug(): traceback.print_exc() else: print("nbdsh: command line script failed: %s" % ex.string, file=sys.stderr) sys.exit(1)