+++ /dev/null
-From: Josep Puigdemont <josep.puigdemont@enea.com>
-Date: Fri, 6 May 2016 03:28:26 +0200
-Subject: [PATCH] common.py: allow specifying number of attempts in exec_cmd
-
-Some commands executed by exec_cmd may fail because of a temporary
-cause, and it may be desirable to retry the same command several times
-until it succeeds. One example of this are the ipmitool commands, which
-may fail temorarily on some targets if they get too many requests
-simultaneously.
-
-In this patch three new optional parameters are introduced to the
-function signature, which do not break backward compatibility:
- attempts: which indicates how many times the command should be run if
- it returns a non-zero value*, and defaults to 1 (as today).
- delay: which indicates the delay in seconds between attempts, and
- defaults to 5 seconds.
- verbose: It will print the remaining attempts left for the current
- command if set to True.
-
-* It may be desirable to add yet another parameter to indicate what
- return value should be considered an error, but non-zero for now
- seems a reasonable default.
-
-Signed-off-by: Josep Puigdemont <josep.puigdemont@enea.com>
----
- deploy/common.py | 24 +++++++++++++++++-------
- 1 file changed, 17 insertions(+), 7 deletions(-)
-
-diff --git a/deploy/common.py b/deploy/common.py
-index 41b4e27..3cd3e0e 100644
---- a/deploy/common.py
-+++ b/deploy/common.py
-@@ -16,6 +16,7 @@ import argparse
- import shutil
- import stat
- import errno
-+import time
-
- N = {'id': 0, 'status': 1, 'name': 2, 'cluster': 3, 'ip': 4, 'mac': 5,
- 'roles': 6, 'pending_roles': 7, 'online': 8, 'group_id': 9}
-@@ -37,13 +38,22 @@ out_handler.setFormatter(formatter)
- LOG.addHandler(out_handler)
- os.chmod(LOGFILE, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
-
--def exec_cmd(cmd, check=True):
-- process = subprocess.Popen(cmd,
-- stdout=subprocess.PIPE,
-- stderr=subprocess.PIPE,
-- shell=True)
-- (response, stderr) = process.communicate()
-- return_code = process.returncode
-+def exec_cmd(cmd, check=True, attempts=1, delay=5, verbose=False):
-+ # a negative value means forever
-+ while attempts != 0:
-+ attempts = attempts - 1
-+ process = subprocess.Popen(cmd,
-+ stdout=subprocess.PIPE,
-+ stderr=subprocess.PIPE,
-+ shell=True)
-+ (response, stderr) = process.communicate()
-+ return_code = process.returncode
-+ if return_code == 0 or attempts == 0:
-+ break
-+ time.sleep(delay)
-+ if verbose:
-+ log('%d attempts left: %s' % (attempts, cmd))
-+
- response = response.strip()
- if check:
- if return_code > 0:
+++ /dev/null
-From: Josep Puigdemont <josep.puigdemont@enea.com>
-Date: Fri, 6 May 2016 12:09:58 +0200
-Subject: [PATCH] ipmi_adapter: simplify, retry if command fails
-
-The method get_node_state has been added to the the IpmiAdapter class.
-
-In addition, now the power on/off methods will try several times to
-perform their IPMI command before giving up, instead of bailing out at
-the first error.
-
-After the power on/off command is completed, the method will wait until
-the node is in the desired state.
-
-NOTE: a command could potentially take several minutes if the defaults
-are used; each IPMI command can take up to 1 minute, and there can be 3
-commands issued per operation, one of them may be retried 20 times with
-the current defaults. Ideally we would use eventlet or something similar
-to allow each command a limited time to execute, instead:
-
- with eventlet.timeout.Timeout(seconds) as t:
- power_on/off_command
-
-Signed-off-by: Josep Puigdemont <josep.puigdemont@enea.com>
----
- deploy/dha_adapters/ipmi_adapter.py | 101 +++++++++++++++---------------------
- 1 file changed, 42 insertions(+), 59 deletions(-)
-
-diff --git a/deploy/dha_adapters/ipmi_adapter.py b/deploy/dha_adapters/ipmi_adapter.py
-index 8fda4f9..283bd57 100644
---- a/deploy/dha_adapters/ipmi_adapter.py
-+++ b/deploy/dha_adapters/ipmi_adapter.py
-@@ -1,5 +1,6 @@
- ###############################################################################
- # Copyright (c) 2015 Ericsson AB and others.
-+# (c) 2016 Enea Software AB
- # szilard.cserey@ericsson.com
- # All rights reserved. This program and the accompanying materials
- # are made available under the terms of the Apache License, Version 2.0
-@@ -20,8 +21,10 @@ from common import (
-
- class IpmiAdapter(HardwareAdapter):
-
-- def __init__(self, yaml_path):
-+ def __init__(self, yaml_path, attempts=20, delay=3):
- super(IpmiAdapter, self).__init__(yaml_path)
-+ self.attempts = attempts
-+ self.delay = delay
-
- def get_access_info(self, node_id):
- ip = self.get_node_property(node_id, 'ipmiIp')
-@@ -40,69 +43,46 @@ class IpmiAdapter(HardwareAdapter):
- mac_list.append(self.get_node_property(node_id, 'pxeMac').lower())
- return mac_list
-
-+ def node_get_state(self, node_id):
-+ state = exec_cmd('%s chassis power status' % self.ipmi_cmd(node_id),
-+ attempts=self.attempts, delay=self.delay,
-+ verbose=True)
-+ return state
-+
-+ def __node_power_cmd__(self, node_id, cmd):
-+ expected = 'Chassis Power is %s' % cmd
-+ if self.node_get_state(node_id) == expected:
-+ return
-+
-+ pow_cmd = '%s chassis power %s' % (self.ipmi_cmd(node_id), cmd)
-+ exec_cmd(pow_cmd, attempts=self.attempts, delay=self.delay,
-+ verbose=True)
-+
-+ attempts = self.attempts
-+ while attempts:
-+ state = self.node_get_state(node_id)
-+ attempts -= 1
-+ if state == expected:
-+ return
-+ elif attempts != 0:
-+ # reinforce our will, but allow the command to fail,
-+ # we know our message got across once already...
-+ exec_cmd(pow_cmd, check=False)
-+
-+ err('Could not set chassis %s for node %s' % (cmd, node_id))
-+
- def node_power_on(self, node_id):
-- WAIT_LOOP = 200
-- SLEEP_TIME = 3
- log('Power ON Node %s' % node_id)
-- cmd_prefix = self.ipmi_cmd(node_id)
-- state = exec_cmd('%s chassis power status' % cmd_prefix)
-- if state == 'Chassis Power is off':
-- exec_cmd('%s chassis power on' % cmd_prefix)
-- done = False
-- for i in range(WAIT_LOOP):
-- state, _ = exec_cmd('%s chassis power status' % cmd_prefix,
-- False)
-- if state == 'Chassis Power is on':
-- done = True
-- break
-- else:
-- time.sleep(SLEEP_TIME)
-- if not done:
-- err('Could Not Power ON Node %s' % node_id)
-+ self.__node_power_cmd__(node_id, 'on')
-
- def node_power_off(self, node_id):
-- WAIT_LOOP = 200
-- SLEEP_TIME = 3
- log('Power OFF Node %s' % node_id)
-- cmd_prefix = self.ipmi_cmd(node_id)
-- state = exec_cmd('%s chassis power status' % cmd_prefix)
-- if state == 'Chassis Power is on':
-- done = False
-- exec_cmd('%s chassis power off' % cmd_prefix)
-- for i in range(WAIT_LOOP):
-- state, _ = exec_cmd('%s chassis power status' % cmd_prefix,
-- False)
-- if state == 'Chassis Power is off':
-- done = True
-- break
-- else:
-- time.sleep(SLEEP_TIME)
-- if not done:
-- err('Could Not Power OFF Node %s' % node_id)
-+ self.__node_power_cmd__(node_id, 'off')
-
- def node_reset(self, node_id):
-- WAIT_LOOP = 600
- log('RESET Node %s' % node_id)
-- cmd_prefix = self.ipmi_cmd(node_id)
-- state = exec_cmd('%s chassis power status' % cmd_prefix)
-- if state == 'Chassis Power is on':
-- was_shut_off = False
-- done = False
-- exec_cmd('%s chassis power reset' % cmd_prefix)
-- for i in range(WAIT_LOOP):
-- state, _ = exec_cmd('%s chassis power status' % cmd_prefix,
-- False)
-- if state == 'Chassis Power is off':
-- was_shut_off = True
-- elif state == 'Chassis Power is on' and was_shut_off:
-- done = True
-- break
-- time.sleep(1)
-- if not done:
-- err('Could Not RESET Node %s' % node_id)
-- else:
-- err('Cannot RESET Node %s because it\'s not Active, state: %s'
-- % (node_id, state))
-+ cmd = '%s chassis power reset' % self.ipmi_cmd(node_id)
-+ exec_cmd(cmd, attempts=self.attempts, delay=self.delay, verbose=True)
-
- def node_set_boot_order(self, node_id, boot_order_list):
- log('Set boot order %s on Node %s' % (boot_order_list, node_id))
-@@ -111,9 +91,12 @@ class IpmiAdapter(HardwareAdapter):
- for dev in boot_order_list:
- if dev == 'pxe':
- exec_cmd('%s chassis bootdev pxe options=persistent'
-- % cmd_prefix)
-+ % cmd_prefix, attempts=self.attempts, delay=self.delay,
-+ verbose=True)
- elif dev == 'iso':
-- exec_cmd('%s chassis bootdev cdrom' % cmd_prefix)
-+ exec_cmd('%s chassis bootdev cdrom' % cmd_prefix,
-+ attempts=self.attempts, delay=self.delay, verbose=True)
- elif dev == 'disk':
- exec_cmd('%s chassis bootdev disk options=persistent'
-- % cmd_prefix)
-+ % cmd_prefix, attempts=self.attempts, delay=self.delay,
-+ verbose=True)
+++ /dev/null
-From: Josep Puigdemont <josep.puigdemont@enea.com>
-Date: Wed, 4 May 2016 14:27:23 +0200
-Subject: [PATCH] VirtualFuel: Add temp_dir and vm_name attributes
-
-These two variables are defined in one of the methods right now. They
-will be useful to other methods too, so we add them as attributes to the
-object here.
-
-Signed-off-by: Josep Puigdemont <josep.puigdemont@enea.com>
----
- deploy/environments/virtual_fuel.py | 15 +++++++++------
- 1 file changed, 9 insertions(+), 6 deletions(-)
-
-diff --git a/deploy/environments/virtual_fuel.py b/deploy/environments/virtual_fuel.py
-index cb3bc6c..966bb91 100644
---- a/deploy/environments/virtual_fuel.py
-+++ b/deploy/environments/virtual_fuel.py
-@@ -25,6 +25,12 @@ class VirtualFuel(ExecutionEnvironment):
- def __init__(self, storage_dir, pxe_bridge, dha_file, root_dir):
- super(VirtualFuel, self).__init__(storage_dir, dha_file, root_dir)
- self.pxe_bridge = pxe_bridge
-+ self.temp_dir = tempfile.mkdtemp()
-+ self.vm_name = self.dha.get_node_property(self.fuel_node_id,
-+ 'libvirtName')
-+
-+ def __del__(self):
-+ delete(self.temp_dir)
-
- def set_vm_nic(self, temp_vm_file):
- with open(temp_vm_file) as f:
-@@ -46,23 +52,20 @@ class VirtualFuel(ExecutionEnvironment):
- vm_xml.write(f, pretty_print=True, xml_declaration=True)
-
- def create_vm(self):
-- temp_dir = tempfile.mkdtemp()
-- vm_name = self.dha.get_node_property(self.fuel_node_id, 'libvirtName')
- vm_template = '%s/%s' % (self.root_dir,
- self.dha.get_node_property(
- self.fuel_node_id, 'libvirtTemplate'))
- check_file_exists(vm_template)
-- disk_path = '%s/%s.raw' % (self.storage_dir, vm_name)
-+ disk_path = '%s/%s.raw' % (self.storage_dir, self.vm_name)
- disk_sizes = self.dha.get_disks()
- disk_size = disk_sizes['fuel']
- exec_cmd('qemu-img create -f qcow2 %s %s' % (disk_path, disk_size))
-- temp_vm_file = '%s/%s' % (temp_dir, vm_name)
-+ temp_vm_file = '%s/%s' % (self.temp_dir, self.vm_name)
- exec_cmd('cp %s %s' % (vm_template, temp_vm_file))
- self.set_vm_nic(temp_vm_file)
- vm_definition_overwrite = self.dha.get_vm_definition('fuel')
-- self.define_vm(vm_name, temp_vm_file, disk_path,
-+ self.define_vm(self.vm_name, temp_vm_file, disk_path,
- vm_definition_overwrite)
-- delete(temp_dir)
-
- def setup_environment(self):
- check_if_root()
+++ /dev/null
-From: Josep Puigdemont <josep.puigdemont@enea.com>
-Date: Wed, 4 May 2016 14:27:23 +0200
-Subject: [PATCH] virtual_fuel: factor out image creation into a method
-
-Signed-off-by: Josep Puigdemont <josep.puigdemont@enea.com>
----
- deploy/environments/virtual_fuel.py | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/deploy/environments/virtual_fuel.py b/deploy/environments/virtual_fuel.py
-index 966bb91..82c4e47 100644
---- a/deploy/environments/virtual_fuel.py
-+++ b/deploy/environments/virtual_fuel.py
-@@ -51,15 +51,20 @@ class VirtualFuel(ExecutionEnvironment):
- with open(temp_vm_file, 'w') as f:
- vm_xml.write(f, pretty_print=True, xml_declaration=True)
-
-+ def create_image(self, disk_path, disk_size):
-+ exec_cmd('qemu-img create -f qcow2 %s %s' % (disk_path, disk_size))
-+
- def create_vm(self):
- vm_template = '%s/%s' % (self.root_dir,
- self.dha.get_node_property(
- self.fuel_node_id, 'libvirtTemplate'))
- check_file_exists(vm_template)
-+
- disk_path = '%s/%s.raw' % (self.storage_dir, self.vm_name)
- disk_sizes = self.dha.get_disks()
- disk_size = disk_sizes['fuel']
-- exec_cmd('qemu-img create -f qcow2 %s %s' % (disk_path, disk_size))
-+ self.create_image(disk_path, disk_size)
-+
- temp_vm_file = '%s/%s' % (self.temp_dir, self.vm_name)
- exec_cmd('cp %s %s' % (vm_template, temp_vm_file))
- self.set_vm_nic(temp_vm_file)
+++ /dev/null
-From: Josep Puigdemont <josep.puigdemont@enea.com>
-Date: Wed, 4 May 2016 14:27:23 +0200
-Subject: [PATCH] virtual_fuel: make vm_template an attribute
-
-Signed-off-by: Josep Puigdemont <josep.puigdemont@enea.com>
----
- deploy/environments/virtual_fuel.py | 11 +++++------
- 1 file changed, 5 insertions(+), 6 deletions(-)
-
-diff --git a/deploy/environments/virtual_fuel.py b/deploy/environments/virtual_fuel.py
-index 82c4e47..ac5fc53 100644
---- a/deploy/environments/virtual_fuel.py
-+++ b/deploy/environments/virtual_fuel.py
-@@ -28,6 +28,10 @@ class VirtualFuel(ExecutionEnvironment):
- self.temp_dir = tempfile.mkdtemp()
- self.vm_name = self.dha.get_node_property(self.fuel_node_id,
- 'libvirtName')
-+ self.vm_template = '%s/%s' % (self.root_dir,
-+ self.dha.get_node_property(
-+ self.fuel_node_id, 'libvirtTemplate'))
-+ check_file_exists(self.vm_template)
-
- def __del__(self):
- delete(self.temp_dir)
-@@ -55,18 +59,13 @@ class VirtualFuel(ExecutionEnvironment):
- exec_cmd('qemu-img create -f qcow2 %s %s' % (disk_path, disk_size))
-
- def create_vm(self):
-- vm_template = '%s/%s' % (self.root_dir,
-- self.dha.get_node_property(
-- self.fuel_node_id, 'libvirtTemplate'))
-- check_file_exists(vm_template)
--
- disk_path = '%s/%s.raw' % (self.storage_dir, self.vm_name)
- disk_sizes = self.dha.get_disks()
- disk_size = disk_sizes['fuel']
- self.create_image(disk_path, disk_size)
-
- temp_vm_file = '%s/%s' % (self.temp_dir, self.vm_name)
-- exec_cmd('cp %s %s' % (vm_template, temp_vm_file))
-+ exec_cmd('cp %s %s' % (self.vm_template, temp_vm_file))
- self.set_vm_nic(temp_vm_file)
- vm_definition_overwrite = self.dha.get_vm_definition('fuel')
- self.define_vm(self.vm_name, temp_vm_file, disk_path,
+++ /dev/null
-From: Josep Puigdemont <josep.puigdemont@enea.com>
-Date: Wed, 4 May 2016 14:27:23 +0200
-Subject: [PATCH] virtual_fuel: initial support for remote libvirt
-
-With this patch it should be possible to create a fuel VM on a remote
-libvirt server by properly defining the LIBVIRT_DEFAULT_URI [1]
-environment variable. If the variable is not defined, then there should
-be no percievable change in behaviour for the script.
-
-This patch introduces the ability to create volumes (images) on a
-remote libvirt host where the Fuel VM is to be deployed. For now
-the volumes are created by default in a pool named jenkins, but
-the idea is to allow this to be configured, probably in the POD's
-DHA file.
-
-Since all virsh commands honor LIBVIRT_DEFAULT_URI, we use this
-environment variable to detect wheter we should create a volume or not.
-The rationale being that the variable will only be set if the user wants
-to to do the VM deployment on a remote libvirt host.
-
-We need to create a volume because we can not rely on being able to
-access the remote server's file system directly.
-
-The images are then transferred to the libvirt host using virsh
-commands. All this could also be done using scp and a user directory
-on the host machine, but using pools allows us to take advantage of
-libvirt's policies and file permissions.
-
-CHANGE: when LIBVIRT_DEFAULT_URI is defined, the script will not check
-for the presence of the required PXE bridge. This will still be checked
-when the Fuel VM is started and the bridge not found, but this happens
-at a later point than it does today.
-
-CHANGE: before this patch, the file system image was named like the VM:
-vm_name.raw. This patch introduces a change and adds a timestamp suffix
-to the image: vm_name-timestamp.raw. This is so to avoid collisions with
-an image with the same name on the remote pool (two PODs may be using
-the same pool). It may also be useful to keep around old file system
-images.
-
-FIXME: This patch requires a pool named "jenkins" in the remote libvirt
-server, and it will fail if it is not present. This should be
-configurable.
-
-Notice though that we can still define LIBVIRT_DEFAULT_URI as
-"qemu:///system" to create the Fuel VM on the local host.
-
-[1] https://libvirt.org/remote.html#Remote_URI_reference
-
-Change-Id: I40925ed31337d3ad9cf505f284f5c3d14e9129a0
-Signed-off-by: Josep Puigdemont <josep.puigdemont@enea.com>
----
- deploy/deploy.py | 5 +++
- deploy/dha_adapters/libvirt_adapter.py | 31 +++++++++++++++++++
- deploy/environments/virtual_fuel.py | 56 ++++++++++++++++++++++++++++++++--
- deploy/install_fuel_master.py | 8 +++--
- 4 files changed, 95 insertions(+), 5 deletions(-)
-
-diff --git a/deploy/deploy.py b/deploy/deploy.py
-index 742e76b..179ee7b 100755
---- a/deploy/deploy.py
-+++ b/deploy/deploy.py
-@@ -245,6 +245,11 @@ class AutoDeploy(object):
-
-
- def check_bridge(pxe_bridge, dha_path):
-+ # Assume that bridges on remote nodes exists, we could ssh but
-+ # the remote user might not have a login shell.
-+ if os.environ.get('LIBVIRT_DEFAULT_URI'):
-+ return
-+
- with io.open(dha_path) as yaml_file:
- dha_struct = yaml.load(yaml_file)
- if dha_struct['adapter'] != 'libvirt':
-diff --git a/deploy/dha_adapters/libvirt_adapter.py b/deploy/dha_adapters/libvirt_adapter.py
-index 85913ac..466f134 100644
---- a/deploy/dha_adapters/libvirt_adapter.py
-+++ b/deploy/dha_adapters/libvirt_adapter.py
-@@ -11,6 +11,7 @@
- from lxml import etree
- from hardware_adapter import HardwareAdapter
- import tempfile
-+import os
-
- from common import (
- log,
-@@ -23,6 +24,15 @@ DEV = {'pxe': 'network',
- 'disk': 'hd',
- 'iso': 'cdrom'}
-
-+VOL_XML_TEMPLATE = '''<volume type='file'>
-+ <name>{name}</name>
-+ <capacity unit='{unit}'>{size!s}</capacity>
-+ <target>
-+ <format type='{format_type}'/>
-+ </target>
-+</volume>'''
-+
-+DEFAULT_POOL = 'jenkins'
-
- class LibvirtAdapter(HardwareAdapter):
-
-@@ -140,3 +150,24 @@ class LibvirtAdapter(HardwareAdapter):
-
- def get_virt_net_conf_dir(self):
- return self.dha_struct['virtNetConfDir']
-+
-+ def upload_iso(self, iso_file):
-+ size = os.path.getsize(iso_file)
-+ vol_name = os.path.basename(iso_file)
-+ vol_xml = VOL_XML_TEMPLATE.format(name=vol_name, unit='bytes',
-+ size=size, format_type='raw')
-+ fd, fname = tempfile.mkstemp(text=True, suffix='deploy')
-+ os.write(fd, vol_xml)
-+ os.close(fd)
-+
-+ log(vol_xml)
-+ pool = DEFAULT_POOL # FIXME
-+ exec_cmd('virsh vol-create --pool %s %s' % (pool, fname))
-+ vol_path = exec_cmd('virsh vol-path --pool %s %s' % (pool, vol_name))
-+
-+ exec_cmd('virsh vol-upload %s %s' % (vol_path, iso_file),
-+ attempts=5, delay=10, verbose=True)
-+
-+ delete(fname)
-+
-+ return vol_path
-diff --git a/deploy/environments/virtual_fuel.py b/deploy/environments/virtual_fuel.py
-index ac5fc53..f9f9f7a 100644
---- a/deploy/environments/virtual_fuel.py
-+++ b/deploy/environments/virtual_fuel.py
-@@ -11,14 +11,36 @@
- from lxml import etree
- from execution_environment import ExecutionEnvironment
- import tempfile
-+import os
-+import re
-+import time
-
- from common import (
- exec_cmd,
- check_file_exists,
- check_if_root,
- delete,
-+ log,
- )
-
-+VOL_XML_TEMPLATE = '''<volume type='file'>
-+ <name>{name}</name>
-+ <capacity unit='{unit}'>{size!s}</capacity>
-+ <target>
-+ <format type='{format_type}'/>
-+ </target>
-+</volume>'''
-+
-+DEFAULT_POOL = 'jenkins'
-+
-+def get_size_and_unit(s):
-+ p = re.compile('^(\d+)\s*(\D+)')
-+ m = p.match(s)
-+ if m == None:
-+ return None, None
-+ size = m.groups()[0]
-+ unit = m.groups()[1]
-+ return size, unit
-
- class VirtualFuel(ExecutionEnvironment):
-
-@@ -55,14 +77,42 @@ class VirtualFuel(ExecutionEnvironment):
- with open(temp_vm_file, 'w') as f:
- vm_xml.write(f, pretty_print=True, xml_declaration=True)
-
-+ def create_volume(self, pool, name, su, img_type='qcow2'):
-+ log('Creating image using Libvirt volumes in pool %s, name: %s' %
-+ (pool, name))
-+ size, unit = get_size_and_unit(su)
-+ if size == None:
-+ err('Could not determine size and unit of %s' % s)
-+
-+ vol_xml = VOL_XML_TEMPLATE.format(name=name, unit=unit, size=size,
-+ format_type=img_type)
-+ fname = os.path.join(self.temp_dir, '%s_vol.xml' % name)
-+ with file(fname, 'w') as f:
-+ f.write(vol_xml)
-+
-+ exec_cmd('virsh vol-create --pool %s %s' % (pool, fname))
-+ vol_path = exec_cmd('virsh vol-path --pool %s %s' % (pool, name))
-+
-+ delete(fname)
-+
-+ return vol_path
-+
- def create_image(self, disk_path, disk_size):
-- exec_cmd('qemu-img create -f qcow2 %s %s' % (disk_path, disk_size))
-+ if os.environ.get('LIBVIRT_DEFAULT_URI') == None:
-+ exec_cmd('qemu-img create -f qcow2 %s %s' % (disk_path, disk_size))
-+ else:
-+ pool = DEFAULT_POOL # FIXME
-+ name = os.path.basename(disk_path)
-+ disk_path = self.create_volume(pool, name, disk_size)
-+
-+ return disk_path
-
- def create_vm(self):
-- disk_path = '%s/%s.raw' % (self.storage_dir, self.vm_name)
-+ stamp = time.strftime("%Y%m%d%H%M%S")
-+ disk_path = '%s/%s-%s.raw' % (self.storage_dir, self.vm_name, stamp)
- disk_sizes = self.dha.get_disks()
- disk_size = disk_sizes['fuel']
-- self.create_image(disk_path, disk_size)
-+ disk_path = self.create_image(disk_path, disk_size)
-
- temp_vm_file = '%s/%s' % (self.temp_dir, self.vm_name)
- exec_cmd('cp %s %s' % (self.vm_template, temp_vm_file))
-diff --git a/deploy/install_fuel_master.py b/deploy/install_fuel_master.py
-index 631bf99..5adccef 100644
---- a/deploy/install_fuel_master.py
-+++ b/deploy/install_fuel_master.py
-@@ -54,8 +54,12 @@ class InstallFuelMaster(object):
-
- self.dha.node_power_off(self.fuel_node_id)
-
-- log('Zero the MBR')
-- self.dha.node_zero_mbr(self.fuel_node_id)
-+ if os.environ.get('LIBVIRT_DEFAULT_URI'):
-+ log('Upload ISO to pool')
-+ self.iso_file = self.dha.upload_iso(self.iso_file)
-+ else:
-+ log('Zero the MBR')
-+ self.dha.node_zero_mbr(self.fuel_node_id)
-
- self.dha.node_set_boot_order(self.fuel_node_id, ['disk', 'iso'])
-
+++ /dev/null
-From: Stanislaw Kardach <stanislaw.kardach@caviumnetworks.com>
-Date: Sun, 21 Feb 2016 16:28:02 +0100
-Subject: [PATCH] Allow customizing Fuel commit
-
----
- build/config.mk | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/build/config.mk b/build/config.mk
-index 23bda18..af63fcd 100644
---- a/build/config.mk
-+++ b/build/config.mk
-@@ -9,7 +9,7 @@
- ##############################################################################
-
- FUEL_MAIN_REPO := https://github.com/openstack/fuel-main
--FUEL_MAIN_TAG = 9.0
-+FUEL_MAIN_TAG := 9.0
- MOS_VERSION = 9.0
- OPENSTACK_VERSION = mitaka-9.0
-
+++ /dev/null
-From: Stanislaw Kardach <stanislaw.kardach@caviumnetworks.com>
-Date: Wed, 24 Feb 2016 20:02:25 +0100
-Subject: [PATCH] Allow customizing java and fuel-mirror URLs
-
----
- build/f_isoroot/f_odlpluginbuild/config.mk | 2 +-
- build/f_isoroot/f_repobuild/Makefile | 3 ++-
- 2 files changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/build/f_isoroot/f_odlpluginbuild/config.mk b/build/f_isoroot/f_odlpluginbuild/config.mk
-index a5e8a96..e64a05e 100644
---- a/build/f_isoroot/f_odlpluginbuild/config.mk
-+++ b/build/f_isoroot/f_odlpluginbuild/config.mk
-@@ -12,5 +12,5 @@ ODL_CHANGE=ec9474c1178e7451ec75f6e306ac84424a84a28a
-
- export USE_JAVA8=true
--export JAVA8_URL=https://launchpad.net/~openjdk-r/+archive/ubuntu/ppa/+files/openjdk-8-jre-headless_8u72-b15-1~trusty1_amd64.deb
-+export JAVA8_URL:=https://launchpad.net/~openjdk-r/+archive/ubuntu/ppa/+files/openjdk-8-jre-headless_8u72-b15-1~trusty1_amd64.deb
- export ODL_TARBALL_LOCATION=https://nexus.opendaylight.org/content/groups/public/org/opendaylight/integration/distribution-karaf/0.4.2-Beryllium-SR2/distribution-karaf-0.4.2-Beryllium-SR2.tar.gz
- export ODL_VERSION_NUMBER=0.4.2
-diff --git a/build/f_isoroot/f_repobuild/Makefile b/build/f_isoroot/f_repobuild/Makefile
-index e95dbf2..709ca6b 100644
---- a/build/f_isoroot/f_repobuild/Makefile
-+++ b/build/f_isoroot/f_repobuild/Makefile
-@@ -12,6 +12,7 @@ SHELL := /bin/bash
- TOP := $(shell pwd)
- TMP_ROOT_DIR := $(shell echo "$(MIRROR_UBUNTU_ROOT)" | cut -d "/" -f2)
- # Enable use of exact repo commit if defined, else use Fuel main branch
-+FUEL_MIRROR_REPO:=https://github.com/openstack/fuel-mirror
- FUEL_MIRROR_COMMIT?=$(FUEL_MAIN_TAG)
-
- include ../../config.mk
-@@ -26,7 +27,7 @@ nailgun:
- sudo apt-get install -y git libxml2-dev libxslt-dev python-dev python-pip libz-dev libyaml-dev createrepo python-yaml
- rm -Rf nailgun
- sudo mkdir -p /var/www/nailgun
-- git clone https://github.com/openstack/fuel-mirror
-+ git clone $(FUEL_MIRROR_REPO)
- cd fuel-mirror && git checkout -q $(FUEL_MIRROR_COMMIT)
- sudo pip install -U -r ./fuel-mirror/requirements.txt
- sudo pip install ./fuel-mirror