From 5b34e515f376e45755aa9b094c0234acacdef912 Mon Sep 17 00:00:00 2001 From: gbenhaim Date: Wed, 28 Jun 2017 01:38:51 +0300 Subject: [PATCH] export: Backing file resolution fixes 1. If the disk is a layer and the path to his backing file is correct, do nothing. 2. Avoid endless recursion when the disk and its backing file has the same name. 3. Safely parse the name and the version of the backing file. Raise exception if the format of the backing file is not name:version. Signed-off-by: gbenhaim --- lago/prefix.py | 65 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/lago/prefix.py b/lago/prefix.py index 1a6d30f2..24017898 100644 --- a/lago/prefix.py +++ b/lago/prefix.py @@ -25,6 +25,7 @@ import os import shutil import subprocess +from textwrap import dedent import urlparse import urllib import uuid @@ -837,35 +838,55 @@ def resolve_parent(self, disk_path, template_store, template_repo): """ qemu_info = utils.get_qemu_info(disk_path) parent = qemu_info.get('backing-filename') + if not parent: + return + + if os.path.isfile(parent): + if os.path.samefile( + os.path.realpath(parent), + os.path.realpath(os.path.expandvars(disk_path)) + ): + raise LagoInitException( + dedent( + """ + Disk {} and its backing file are the same file. + """.format(disk_path) + ) + ) + # The parent exist and we have the correct pointer + return - if parent: - LOGGER.info('Resolving Parent') + LOGGER.info('Resolving Parent') + try: name, version = os.path.basename(parent).split(':', 1) - if not (name and version): - raise RuntimeError( - 'Unsupported backing-filename: {}' - 'backing-filename should be in the format' - 'name:version'.format(parent) + except ValueError: + raise LagoInitException( + dedent( + """ + Backing file resolution of disk {} failed. + Backing file {} is not a Lago image. + """.format(disk_path, parent) ) - _, _, base = self._handle_lago_template( - '', {'template_name': name, - 'template_version': version}, template_store, - template_repo ) - # The child has the right pointer to his parent - base = os.path.expandvars(base) - if base == parent: - return + _, _, base = self._handle_lago_template( + '', {'template_name': name, + 'template_version': version}, template_store, template_repo + ) - # The child doesn't have the right pointer to his - # parent, We will fix it with a symlink - link_name = os.path.join( - os.path.dirname(disk_path), '{}:{}'.format(name, version) - ) - link_name = os.path.expandvars(link_name) + # The child has the right pointer to his parent + base = os.path.expandvars(base) + if base == parent: + return + + # The child doesn't have the right pointer to his + # parent, We will fix it with a symlink + link_name = os.path.join( + os.path.dirname(disk_path), '{}:{}'.format(name, version) + ) + link_name = os.path.expandvars(link_name) - self._create_link_to_parent(base, link_name) + self._create_link_to_parent(base, link_name) def _create_link_to_parent(self, base, link_name): if not os.path.islink(link_name):