diff options
| author | Rick Harris <rconradharris@gmail.com> | 2012-06-25 22:49:17 +0000 |
|---|---|---|
| committer | Rick Harris <rconradharris@gmail.com> | 2012-10-03 21:29:46 +0000 |
| commit | 216a83da476f2ea1ca3fcc6af3ac7dce6c20db27 (patch) | |
| tree | c8cf8540f88950e08e0c12bc1d1f9d80258eadd1 /nova | |
| parent | 1d4506c16aec9674be6a3685ba585a8bbd9c1559 (diff) | |
| download | nova-216a83da476f2ea1ca3fcc6af3ac7dce6c20db27.tar.gz nova-216a83da476f2ea1ca3fcc6af3ac7dce6c20db27.tar.xz nova-216a83da476f2ea1ca3fcc6af3ac7dce6c20db27.zip | |
Add ability to download images via BitTorrent.
This patch adds a new dom0 plugin which supports downloading images via
BitTorrent. Torrent metadata files are assumed to be served from a
webserver which is specified by the `torrent_base_url` config.
Under the hood, the dom0 plugins calls out to rasterbar's libtorrent via
Python bindings in order perform the initial download as well as the
seeding thereafter.
Implements BP xenserver-bittorrent-images
Change-Id: I824720a6e3a37317080a22cd7405d2a88172c3ef
Diffstat (limited to 'nova')
| -rw-r--r-- | nova/flags.py | 3 | ||||
| -rw-r--r-- | nova/virt/xenapi/vm_utils.py | 95 |
2 files changed, 87 insertions, 11 deletions
diff --git a/nova/flags.py b/nova/flags.py index 239e45385..9ab59bbe3 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -406,7 +406,8 @@ global_opts = [ 'image_type', 'backup_type', 'min_ram', - 'min_disk'], + 'min_disk', + 'bittorrent'], help='These are image properties which a snapshot should not' ' inherit from an instance'), cfg.BoolOpt('defer_iptables_apply', diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 7a37bcdac..bd8fad474 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -80,6 +80,39 @@ xenapi_vm_utils_opts = [ cfg.IntOpt('xenapi_num_vbd_unplug_retries', default=10, help='Maximum number of retries to unplug VBD'), + cfg.StrOpt('xenapi_torrent_images', + default='none', + help='Whether or not to download images via Bit Torrent ' + '(all|some|none).'), + cfg.StrOpt('xenapi_torrent_base_url', + default=None, + help='Base URL for torrent files.'), + cfg.FloatOpt('xenapi_torrent_seed_chance', + default=1.0, + help='Probability that peer will become a seeder.' + ' (1.0 = 100%)'), + cfg.IntOpt('xenapi_torrent_seed_duration', + default=3600, + help='Number of seconds after downloading an image via' + ' BitTorrent that it should be seeded for other peers.'), + cfg.IntOpt('xenapi_torrent_max_last_accessed', + default=86400, + help='Cached torrent files not accessed within this number of' + ' seconds can be reaped'), + cfg.IntOpt('xenapi_torrent_listen_port_start', + default=6881, + help='Beginning of port range to listen on'), + cfg.IntOpt('xenapi_torrent_listen_port_end', + default=6891, + help='End of port range to listen on'), + cfg.IntOpt('xenapi_torrent_download_stall_cutoff', + default=600, + help='Number of seconds a download can remain at the same' + ' progress percentage w/o being considered a stall'), + cfg.IntOpt('xenapi_torrent_max_seeder_processes_per_host', + default=1, + help='Maximum number of seeder processes to run concurrently' + ' within a given dom0. (-1 = no limit)') ] FLAGS = flags.FLAGS @@ -975,6 +1008,29 @@ def _make_uuid_stack(): return [str(uuid.uuid4()) for i in xrange(MAX_VDI_CHAIN_SIZE)] +def _image_uses_bittorrent(context, instance): + bittorrent = False + xenapi_torrent_images = FLAGS.xenapi_torrent_images.lower() + + if xenapi_torrent_images == 'all': + bittorrent = True + elif xenapi_torrent_images == 'some': + # FIXME(sirp): This should be eager loaded like instance metadata + sys_meta = db.instance_system_metadata_get(context, + instance['uuid']) + try: + bittorrent = utils.bool_from_str(sys_meta['image_bittorrent']) + except KeyError: + pass + elif xenapi_torrent_images == 'none': + pass + else: + LOG.warning(_("Invalid value '%s' for xenapi_torrent_images"), + xenapi_torrent_images) + + return bittorrent + + def _fetch_vhd_image(context, session, instance, image_id): """Tell glance to download an image and put the VHDs into the SR @@ -985,21 +1041,40 @@ def _fetch_vhd_image(context, session, instance, image_id): params = {'image_id': image_id, 'uuid_stack': _make_uuid_stack(), - 'sr_path': get_sr_path(session), - 'auth_token': getattr(context, 'auth_token', None)} + 'sr_path': get_sr_path(session)} + + if _image_uses_bittorrent(context, instance): + plugin_name = 'bittorrent' + callback = None + params['torrent_base_url'] = FLAGS.xenapi_torrent_base_url + params['torrent_seed_duration'] = FLAGS.xenapi_torrent_seed_duration + params['torrent_seed_chance'] = FLAGS.xenapi_torrent_seed_chance + params['torrent_max_last_accessed'] =\ + FLAGS.xenapi_torrent_max_last_accessed + params['torrent_listen_port_start'] =\ + FLAGS.xenapi_torrent_listen_port_start + params['torrent_listen_port_end'] =\ + FLAGS.xenapi_torrent_listen_port_end + params['torrent_download_stall_cutoff'] =\ + FLAGS.xenapi_torrent_download_stall_cutoff + params['torrent_max_seeder_processes_per_host'] =\ + FLAGS.xenapi_torrent_max_seeder_processes_per_host + else: + plugin_name = 'glance' + glance_api_servers = glance.get_api_servers() - glance_api_servers = glance.get_api_servers() + def pick_glance(params): + g_host, g_port, g_use_ssl = glance_api_servers.next() + params['glance_host'] = g_host + params['glance_port'] = g_port + params['glance_use_ssl'] = g_use_ssl + params['auth_token'] = getattr(context, 'auth_token', None) - def pick_glance(params): - glance_host, glance_port, glance_use_ssl = glance_api_servers.next() - params['glance_host'] = glance_host - params['glance_port'] = glance_port - params['glance_use_ssl'] = glance_use_ssl + callback = pick_glance - plugin_name = 'glance' vdis = _fetch_using_dom0_plugin_with_retry( context, session, image_id, plugin_name, params, - callback=pick_glance) + callback=callback) sr_ref = safe_find_sr(session) _scan_sr(session, sr_ref) |
