Alon Bar-Lev has uploaded a new change for review.

Change subject: host-deploy: split logic and infra
......................................................................

host-deploy: split logic and infra

Change-Id: If6055fc395765f054634afe2b06fd56158217154
Signed-off-by: Alon Bar-Lev <alo...@redhat.com>
---
M backend/manager/modules/bll/exclude-filters.xml
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdeploy/VdsDeploy.java
A 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdeploy/VdsDeployBase.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
4 files changed, 690 insertions(+), 594 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/64/39964/6

diff --git a/backend/manager/modules/bll/exclude-filters.xml 
b/backend/manager/modules/bll/exclude-filters.xml
index 2cd6340..99a5335 100644
--- a/backend/manager/modules/bll/exclude-filters.xml
+++ b/backend/manager/modules/bll/exclude-filters.xml
@@ -121,7 +121,7 @@
     </Match>
 
     <Match>
-       <Class name="org.ovirt.engine.core.bll.hostdeploy.VdsDeploy" />
+       <Class name="org.ovirt.engine.core.bll.hostdeploy.VdsDeployBase" />
        <Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD" />
     </Match>
 
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdeploy/VdsDeploy.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdeploy/VdsDeploy.java
index a89eba5..8e3a101 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdeploy/VdsDeploy.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdeploy/VdsDeploy.java
@@ -1,33 +1,12 @@
 package org.ovirt.engine.core.bll.hostdeploy;
 
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.Method;
-import java.security.KeyPair;
-import java.security.KeyStoreException;
-import java.text.SimpleDateFormat;
 import java.util.Arrays;
-import java.util.Calendar;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
-import java.util.TimeZone;
 import java.util.concurrent.Callable;
-
-import javax.naming.TimeLimitExceededException;
 
 import org.apache.commons.lang.StringUtils;
 import org.ovirt.engine.core.bll.network.cluster.ManagementNetworkUtil;
-import org.ovirt.engine.core.bll.utils.EngineSSHDialog;
 import 
org.ovirt.engine.core.common.businessentities.OpenstackNetworkProviderProperties;
 import 
org.ovirt.engine.core.common.businessentities.OpenstackNetworkProviderProperties.MessagingConfiguration;
 import org.ovirt.engine.core.common.businessentities.VDS;
@@ -42,22 +21,17 @@
 import org.ovirt.engine.core.utils.EngineLocalConfig;
 import org.ovirt.engine.core.utils.NetworkUtils;
 import org.ovirt.engine.core.utils.PKIResources;
-import org.ovirt.engine.core.utils.archivers.tar.CachedTar;
 import org.ovirt.engine.core.utils.crypt.EngineEncryptionUtils;
 import org.ovirt.engine.core.utils.hostinstall.OpenSslCAWrapper;
 import org.ovirt.engine.core.utils.linq.LinqUtils;
 import org.ovirt.engine.core.utils.linq.Predicate;
 import org.ovirt.engine.core.utils.transaction.TransactionMethod;
 import org.ovirt.engine.core.utils.transaction.TransactionSupport;
-import org.ovirt.engine.core.uutils.ssh.SSHDialog;
-import org.ovirt.otopi.constants.BaseEnv;
 import org.ovirt.otopi.constants.Confirms;
 import org.ovirt.otopi.constants.CoreEnv;
 import org.ovirt.otopi.constants.NetEnv;
-import org.ovirt.otopi.constants.Queries;
 import org.ovirt.otopi.constants.SysEnv;
 import org.ovirt.otopi.dialog.Event;
-import org.ovirt.otopi.dialog.MachineDialogParser;
 import org.ovirt.otopi.dialog.SoftError;
 import org.ovirt.ovirt_host_deploy.constants.Const;
 import org.ovirt.ovirt_host_deploy.constants.Displays;
@@ -85,33 +59,25 @@
  * The installer environment is set according to the ovirt-host-deploy
  * documentation.
  */
-public class VdsDeploy implements SSHDialog.Sink, Closeable {
+public class VdsDeploy extends VdsDeployBase {
 
     public static enum DeployStatus {Complete, Incomplete, Failed, Reboot};
-    private static final int THREAD_JOIN_TIMEOUT = 20 * 1000; // milliseconds
+
     private static final String IPTABLES_CUSTOM_RULES_PLACE_HOLDER = 
"@CUSTOM_RULES@";
     private static final String IPTABLES_VDSM_PORT_PLACE_HOLDER = 
"@VDSM_PORT@";
     private static final String IPTABLES_SSH_PORT_PLACE_HOLDER = "@SSH_PORT@";
-    private static final String BOOTSTRAP_CUSTOM_ENVIRONMENT_PLACE_HOLDER = 
"@ENVIRONMENT@";
+
+    private static final String COND_IPTABLES_OVERRIDE = "IPTABLES_OVERRIDE";
+    private static final String COND_NEUTRON_SETUP = "NEUTRON_SETUP";
+    private static final String COND_NEUTRON_LINUX_BRIDGE_SETUP = 
"NEUTRON_LINUX_BRIDGE_SETUP";
+    private static final String COND_NEUTRON_OPEN_VSWITCH_SETUP = 
"NEUTRON_OPEN_VSWITCH_SETUP";
 
     private static final Logger log = LoggerFactory.getLogger(VdsDeploy.class);
-    private static volatile CachedTar s_deployPackage;
 
-    private SSHDialog.Control _control;
-    private Thread _thread;
-    private EngineSSHDialog _dialog;
-    private MachineDialogParser _parser;
-    private final InstallerMessages _messages;
-
-    private VDS _vds;
     private boolean _isNode = false;
     private boolean _isLegacyNode = false;
     private boolean _reboot = false;
-    private String _correlationId = null;
-    private Exception _failException = null;
-    private boolean _resultError = false;
     private boolean _goingToReboot = false;
-    private boolean _aborted = false;
     private boolean _installIncomplete = false;
     private String _managementNetwork = null;
     private DeployStatus _deployStatus = DeployStatus.Failed;
@@ -241,44 +207,7 @@
      * Customization dialog.
      */
 
-    /**
-     * Values to determine when customization should be performed.
-     */
-    private static enum CustomizationCondition {
-        IPTABLES_OVERRIDE,
-        NEUTRON_SETUP,
-        NEUTRON_LINUX_BRIDGE_SETUP,
-        NEUTRON_OPEN_VSWITCH_SETUP
-    };
-    /**
-     * Special annotation to specify when the customization is necessary.
-     */
-    @Target(ElementType.METHOD)
-    @Retention(RetentionPolicy.RUNTIME)
-    private @interface CallWhen {
-        /**
-         * @return A condition that determines if the customization should run.
-         */
-        CustomizationCondition[] value();
-    }
-    /**
-     * A set of conditions under which the conditional customizations should 
run.
-     */
-    private Set<CustomizationCondition> _customizationConditions = new 
HashSet<>();
-    /**
-     * Customization tick.
-     */
-    private int _customizationIndex = 0;
-    /**
-     * Customization aborting.
-     */
-    private boolean _customizationShouldAbort = false;
-    /**
-     * Customization vector.
-     * This is tick based vector, every event execute the next
-     * tick.
-     */
-    private final List<Callable<Boolean>> _customizationDialog = Arrays.asList(
+    private final List<Callable<Boolean>> _deployCustomizationDialog = 
Arrays.asList(
         new Callable<Boolean>() { public Boolean call() throws Exception {
             _parser.cliEnvironmentSet(
                 "OVIRT_ENGINE/correlationId",
@@ -351,7 +280,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.IPTABLES_OVERRIDE)
+        new Callable<Boolean>() {@CallWhen(COND_IPTABLES_OVERRIDE)
         public Boolean call() throws Exception {
             _parser.cliEnvironmentSet(
                 NetEnv.IPTABLES_ENABLE,
@@ -359,7 +288,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.IPTABLES_OVERRIDE)
+        new Callable<Boolean>() {@CallWhen(COND_IPTABLES_OVERRIDE)
         public Boolean call() throws Exception {
             _parser.cliEnvironmentSet(
                 NetEnv.IPTABLES_RULES,
@@ -506,7 +435,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_SETUP)
         public Boolean call() throws Exception {
             _parser.cliEnvironmentSet(
                 OpenStackEnv.NEUTRON_ENABLE,
@@ -514,7 +443,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_SETUP)
         public Boolean call() throws Exception {
             _parser.cliEnvironmentSet(
                     OpenStackEnv.NEUTRON_CONFIG_PREFIX + "DEFAULT/host",
@@ -522,7 +451,7 @@
                 );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_SETUP)
         public Boolean call() throws Exception {
             _setCliEnvironmentIfNecessary(
                 OpenStackEnv.NEUTRON_CONFIG_PREFIX + "DEFAULT/" + 
_messagingConfiguration.getBrokerType().getHostKey(),
@@ -530,7 +459,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_SETUP)
         public Boolean call() throws Exception {
             _setCliEnvironmentIfNecessary(
                 OpenStackEnv.NEUTRON_CONFIG_PREFIX + "DEFAULT/" + 
_messagingConfiguration.getBrokerType().getPortKey(),
@@ -538,7 +467,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_SETUP)
         public Boolean call() throws Exception {
             _setCliEnvironmentIfNecessary(
                 OpenStackEnv.NEUTRON_CONFIG_PREFIX + "DEFAULT/" +
@@ -547,7 +476,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_SETUP)
         public Boolean call() throws Exception {
             _setCliEnvironmentIfNecessary(OpenStackEnv.NEUTRON_CONFIG_PREFIX + 
"DEFAULT/" +
                             
_messagingConfiguration.getBrokerType().getPasswordKey(),
@@ -555,7 +484,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_SETUP)
         public Boolean call() throws Exception {
             _parser.cliEnvironmentSet(
                 OpenStackEnv.NEUTRON_CONFIG_PREFIX + "DEFAULT/rpc_backend",
@@ -563,7 +492,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_LINUX_BRIDGE_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_LINUX_BRIDGE_SETUP)
         public Boolean call() throws Exception {
             _parser.cliEnvironmentSet(
                 OpenStackEnv.NEUTRON_LINUXBRIDGE_ENABLE,
@@ -571,7 +500,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_LINUX_BRIDGE_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_LINUX_BRIDGE_SETUP)
         public Boolean call() throws Exception {
             _setCliEnvironmentIfNecessary(
                 OpenStackEnv.NEUTRON_LINUXBRIDGE_CONFIG_PREFIX + 
"LINUX_BRIDGE/physical_interface_mappings",
@@ -579,7 +508,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_OPEN_VSWITCH_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_OPEN_VSWITCH_SETUP)
         public Boolean call() throws Exception {
             _parser.cliEnvironmentSet(
                 OpenStackEnv.NEUTRON_OPENVSWITCH_ENABLE,
@@ -587,7 +516,7 @@
             );
             return true;
         }},
-        new Callable<Boolean>() 
{@CallWhen(CustomizationCondition.NEUTRON_OPEN_VSWITCH_SETUP)
+        new Callable<Boolean>() {@CallWhen(COND_NEUTRON_OPEN_VSWITCH_SETUP)
         public Boolean call() throws Exception {
             _setCliEnvironmentIfNecessary(
                 OpenStackEnv.NEUTRON_OPENVSWITCH_CONFIG_PREFIX + 
"OVS/bridge_mappings",
@@ -641,12 +570,9 @@
                     
Config.<Integer>getValue(ConfigValues.FenceKdumpMessageInterval)
             );
             return true;
-        }},
-        new Callable<Boolean>() { public Boolean call() throws Exception {
-            _parser.cliInstall();
-            return true;
         }}
     );
+
     /**
      * Set the CLI environment variable if it's not <code>null</code>, 
otherwise perform a no-op so the dialog can
      * advance.
@@ -662,75 +588,8 @@
             _parser.cliEnvironmentSet(name, value);
         }
     }
-    /**
-     * Execute the next customization vector entry.
-     */
-    private void _nextCustomizationEntry() throws Exception {
-        try {
-            if (_customizationShouldAbort) {
-                _parser.cliAbort();
-            }
-            else {
-                boolean skip = false;
-                Callable<Boolean> customizationStep = 
_customizationDialog.get(_customizationIndex);
-                Method callMethod = 
customizationStep.getClass().getDeclaredMethod("call");
-                if (callMethod != null) {
-                    CallWhen ann = callMethod.getAnnotation(CallWhen.class);
-                    skip = ann != null && 
!_customizationConditions.containsAll(Arrays.asList(ann.value()));
-                }
 
-                if (skip) {
-                    _customizationIndex++;
-                    _parser.cliNoop();
-                }
-                else {
-                    if (customizationStep.call()) {
-                        _customizationIndex++;
-                    }
-                }
-            }
-        }
-        catch (ArrayIndexOutOfBoundsException e) {
-            throw new RuntimeException("Protocol violation", e);
-        }
-        catch (SoftError e) {
-            log.error(
-                "Soft error during host {} customization dialog: {}",
-                _vds.getHostName(),
-                e.getMessage()
-            );
-            log.debug("Exception", e);
-            _failException = e;
-            _customizationShouldAbort = true;
-        }
-    }
-
-    /*
-     * Termination dialog.
-     */
-
-    /**
-     * Termination dialog tick.
-     */
-    private int _terminationIndex = 0;
-    /**
-     * Termination vector.
-     * This is tick based vector, every event execute the next
-     * tick.
-     */
-    private final List<Callable<Boolean>> _terminationDialog = Arrays.asList(
-        new Callable<Boolean>() { public Boolean call() throws Exception {
-            _resultError = (Boolean)_parser.cliEnvironmentGet(
-                BaseEnv.ERROR
-            );
-            return true;
-        }},
-        new Callable<Boolean>() { public Boolean call() throws Exception {
-            _aborted = (Boolean)_parser.cliEnvironmentGet(
-                BaseEnv.ABORTED
-            );
-            return true;
-        }},
+    private final List<Callable<Boolean>> _deployTerminationDialog = 
Arrays.asList(
         new Callable<Boolean>() { public Boolean call() throws Exception {
             _installIncomplete = (Boolean)_parser.cliEnvironmentGet(
                 
org.ovirt.ovirt_host_deploy.constants.CoreEnv.INSTALL_INCOMPLETE
@@ -769,262 +628,74 @@
                 );
             }
             return true;
-        }},
-        new Callable<Boolean>() { public Boolean call() throws Exception {
-            File logFile = new File(
-                EngineLocalConfig.getInstance().getLogDir(),
-                String.format(
-                    "%1$s%2$sovirt-%3$s-%4$s-%5$s.log",
-                    "host-deploy",
-                    File.separator,
-                    new SimpleDateFormat("yyyyMMddHHmmss").format(
-                        Calendar.getInstance().getTime()
-                    ),
-                    _vds.getHostName(),
-                    _correlationId
-                )
-            );
-            _messages.post(
-                InstallerMessages.Severity.INFO,
-                String.format(
-                    "Retrieving installation logs to: '%1$s'",
-                    logFile
-                )
-            );
-            try (final OutputStream os = new FileOutputStream(logFile)) {
-                _parser.cliDownloadLog(os);
-            }
-            catch (IOException e) {
-                throw e;
-            }
-            catch (Exception e) {
-                log.error("Unexpected exception", e);
-                throw new RuntimeException(e);
-            }
-            return true;
-        }},
-        new Callable<Boolean>() { public Boolean call() throws Exception {
-            _parser.cliEnvironmentSet(
-                CoreEnv.LOG_REMOVE_AT_EXIT,
-                true
-            );
-            return true;
-        }},
-        new Callable<Boolean>() { public Boolean call() throws Exception {
-            _parser.cliQuit();
-            return true;
         }}
     );
-    /**
-     * Execute the next termination vector entry.
-     */
-    private void _nextTerminationEntry() throws Exception {
-        try {
-            if (_terminationDialog.get(_terminationIndex).call()) {
-                _terminationIndex++;
+
+    protected boolean processEvent(Event.Base bevent) throws IOException {
+        boolean unknown = true;
+
+        if (bevent instanceof Event.Confirm) {
+            Event.Confirm event = (Event.Confirm)bevent;
+
+            if (Confirms.GPG_KEY.equals(event.what)) {
+                _messages.post(InstallerMessages.Severity.WARNING, 
event.description);
+                event.reply = true;
+                unknown = false;
+            }
+            else if 
(org.ovirt.ovirt_host_deploy.constants.Confirms.DEPLOY_PROCEED.equals(event.what))
 {
+                event.reply = true;
+                unknown = false;
             }
         }
-        catch (ArrayIndexOutOfBoundsException e) {
-            throw new RuntimeException("Protocol violation", e);
+        else if (bevent instanceof Event.QueryMultiString) {
+            Event.QueryMultiString event = (Event.QueryMultiString)bevent;
+
+            if 
(org.ovirt.ovirt_host_deploy.constants.Queries.CERTIFICATE_CHAIN.equals(event.name))
 {
+                event.value = (
+                    
PKIResources.Resource.CACertificate.toString(PKIResources.Format.X509_PEM) +
+                    _certificate
+                ).split("\n");
+                unknown = false;
+            }
         }
-    }
+        else if (bevent instanceof Event.DisplayMultiString) {
+            Event.DisplayMultiString event = (Event.DisplayMultiString)bevent;
 
-    /**
-     * Dialog implementation.
-     * Handle events incoming from host.
-     */
-    private void _threadMain() {
-        try {
-            boolean terminate = false;
-
-            while(!terminate) {
-                Event.Base bevent = _parser.nextEvent();
-
-                log.debug(
-                    "Installation of {}: Event {}",
-                    _vds.getHostName(),
-                    bevent
+            if (Displays.CERTIFICATE_REQUEST.equals(event.name)) {
+                _messages.post(
+                    InstallerMessages.Severity.INFO,
+                    "Enrolling certificate"
                 );
-
-                if (bevent instanceof Event.Terminate) {
-                    terminate = true;
-                }
-                else if (bevent instanceof Event.Log) {
-                    Event.Log event = (Event.Log)bevent;
-                    InstallerMessages.Severity severity;
-                    switch (event.severity) {
-                    case INFO:
-                        severity = InstallerMessages.Severity.INFO;
-                        break;
-                    case WARNING:
-                        severity = InstallerMessages.Severity.WARNING;
-                        break;
-                    default:
-                        severity = InstallerMessages.Severity.ERROR;
-                        break;
-                    }
-                    _messages.post(severity, event.record);
-                }
-                else if (bevent instanceof Event.Confirm) {
-                    Event.Confirm event = (Event.Confirm)bevent;
-
-                    if (Confirms.GPG_KEY.equals(event.what)) {
-                        _messages.post(InstallerMessages.Severity.WARNING, 
event.description);
-                        event.reply = true;
-                    }
-                    else if 
(org.ovirt.ovirt_host_deploy.constants.Confirms.DEPLOY_PROCEED.equals(event.what))
 {
-                        event.reply = true;
-                    }
-                    else {
-                        log.warn(
-                            "Installation of {}: Not confirming {}: {}",
-                            _vds.getHostName(),
-                            event.what,
-                            event.description
-                        );
-                    }
-
-                    _parser.sendResponse(event);
-                }
-                else if (bevent instanceof Event.QueryString) {
-                    Event.QueryString event = (Event.QueryString)bevent;
-
-                    if (Queries.CUSTOMIZATION_COMMAND.equals(event.name)) {
-                        _nextCustomizationEntry();
-                    }
-                    else if (Queries.TERMINATION_COMMAND.equals(event.name)) {
-                        _nextTerminationEntry();
-                    }
-                    else {
-                        throw new Exception(
-                            String.format(
-                                "Unexpected query %1$s",
-                                event
-                            )
-                        );
-                    }
-                }
-                else if (bevent instanceof Event.QueryValue) {
-                    Event.QueryValue event = (Event.QueryValue)bevent;
-
-                    if (Queries.TIME.equals(event.name)) {
-                        _messages.post(
-                            InstallerMessages.Severity.INFO,
-                            "Setting time"
-                        );
-                        SimpleDateFormat format = new 
SimpleDateFormat("yyyyMMddHHmmssZ");
-                        format.setTimeZone(TimeZone.getTimeZone("UTC"));
-                        event.value = 
format.format(Calendar.getInstance().getTime());
-                    }
-                    else {
-                        event.abort = true;
-                    }
-                    _parser.sendResponse(event);
-                }
-                else if (bevent instanceof Event.QueryMultiString) {
-                    Event.QueryMultiString event = 
(Event.QueryMultiString)bevent;
-
-                    if 
(org.ovirt.ovirt_host_deploy.constants.Queries.CERTIFICATE_CHAIN.equals(event.name))
 {
-                        event.value = (
-                            
PKIResources.Resource.CACertificate.toString(PKIResources.Format.X509_PEM) +
-                            _certificate
-                        ).split("\n");
-                        _parser.sendResponse(event);
-                    }
-                    else {
-                        event.abort = true;
-                        _parser.sendResponse(event);
-                    }
-                }
-                else if (bevent instanceof Event.DisplayMultiString) {
-                    Event.DisplayMultiString event = 
(Event.DisplayMultiString)bevent;
-
-                    if (Displays.CERTIFICATE_REQUEST.equals(event.name)) {
-                        _messages.post(
-                            InstallerMessages.Severity.INFO,
-                            "Enrolling certificate"
-                        );
-                        _certificate = OpenSslCAWrapper.signCertificateRequest(
-                            StringUtils.join(event.value, "\n"),
-                            _vds.getHostName()
-                        );
-                    }
-                }
-                else {
-                    throw new SoftError(
-                        String.format(
-                            "Unexpected event '%1$s'",
-                            bevent
-                        )
-                    );
-                }
+                _certificate = OpenSslCAWrapper.signCertificateRequest(
+                    StringUtils.join(event.value, "\n"),
+                    _vds.getHostName()
+                );
+                unknown = false;
             }
         }
-        catch (Exception e) {
-            _failException = e;
-            log.error("Error during deploy dialog", e);
-            try {
-                _control.close();
-            }
-            catch (IOException ee) {
-                log.error("Error during close", e);
-            }
-        }
+
+        return unknown;
     }
 
-    /*
-     * Constructor.
-     * @param vds vds to install.
-     */
-    public VdsDeploy(VDS vds) {
-        _vds = vds;
-
-        _messages = new InstallerMessages(_vds);
-        _dialog = new EngineSSHDialog();
-        _parser = new MachineDialogParser();
-        _thread = new Thread(
-            new Runnable() {
-                @Override
-                public void run() {
-                    _threadMain();
-                }
-            },
-            "VdsDeploy"
-        );
-
-        if (s_deployPackage == null) {
-            s_deployPackage = new CachedTar(
-                new File(
-                    EngineLocalConfig.getInstance().getCacheDir(),
-                    Config.<String> getValue(ConfigValues.BootstrapPackageName)
-                ),
-                new File(Config.<String> 
getValue(ConfigValues.BootstrapPackageDirectory))
-            );
-        }
-    }
-
-    /**
-     * Destructor.
-     */
     @Override
-    protected void finalize() {
-        try {
-            close();
+    protected void postExecute() {
+        if (_goingToReboot) {
+            _deployStatus = DeployStatus.Reboot;
         }
-        catch (IOException e) {
-            log.error("Exception during finalize", e);
+        else if (_installIncomplete) {
+            _deployStatus = DeployStatus.Incomplete;
+        } else {
+            _deployStatus = DeployStatus.Complete;
         }
     }
 
-    /**
-     * Release resources.
-     */
-    public void close() throws IOException {
-        stop();
-        if (_dialog != null) {
-            _dialog.close();
-            _dialog = null;
-        }
+    public VdsDeploy(VDS vds) {
+        super("host-deploy", "ovirt-host-deploy", vds);
+        addCustomizationDialog(_deployCustomizationDialog);
+        addCustomizationDialog(CUSTOMIZATION_DIALOG_EPILOG);
+        addTerminationDialog(TERMINATION_DIALOG_PROLOG);
+        addTerminationDialog(_deployTerminationDialog);
+        addTerminationDialog(TERMINATION_DIALOG_EPILOG);
     }
 
     /**
@@ -1045,42 +716,6 @@
         _managementNetwork = managementNetwork;
     }
 
-    public void setCorrelationId(String correlationId) {
-        _correlationId = correlationId;
-        _messages.setCorrelationId(_correlationId);
-    }
-
-    /**
-     * Set user.
-     * @param user user.
-     */
-    public void setUser(String user) {
-        _dialog.setUser(user);
-    }
-
-    /**
-     * Set key pair.
-     * @param keyPair key pair.
-     */
-    public void setKeyPair(KeyPair keyPair) {
-        _dialog.setKeyPair(keyPair);
-    }
-
-    /**
-     * Use engine default key pairs.
-     */
-    public void useDefaultKeyPair() throws KeyStoreException {
-        _dialog.useDefaultKeyPair();
-    }
-
-    /**
-     * Set password.
-     * @param password password.
-     */
-    public void setPassword(String password) {
-        _dialog.setPassword(password);
-    }
-
     /**
      * Enable firewall setup.
      * @param doFirewall enable.
@@ -1088,7 +723,7 @@
     public void setFirewall(boolean doFirewall) {
         if (doFirewall) {
             _iptables = _getIpTables();
-            
_customizationConditions.add(CustomizationCondition.IPTABLES_OVERRIDE);
+            addCustomizationCondition(COND_IPTABLES_OVERRIDE);
         }
     }
 
@@ -1101,164 +736,16 @@
         return _deployStatus;
     }
 
-    /**
-     * Main method.
-     * Execute the command and initiate the dialog.
-     */
-    public void execute() throws Exception {
-        try {
-            _dialog.setVds(_vds);
-            _dialog.connect();
-            _messages.post(
-                InstallerMessages.Severity.INFO,
-                String.format(
-                    "Connected to host %1$s with SSH key fingerprint: %2$s",
-                    _vds.getHostName(),
-                    _dialog.getHostFingerprint()
-                )
-            );
-            _dialog.authenticate();
-
-            String command = Config.<String> 
getValue(ConfigValues.BootstrapCommand);
-
-            // in future we should set here LANG, LC_ALL
-            command = command.replace(
-                BOOTSTRAP_CUSTOM_ENVIRONMENT_PLACE_HOLDER,
-                ""
-            );
-
-            log.info(
-                "Installation of {}. Executing command via SSH {} < {}",
-                _vds.getHostName(),
-                command,
-                s_deployPackage.getFileNoUse()
-            );
-
-            try (final InputStream in = new 
FileInputStream(s_deployPackage.getFile())) {
-                _dialog.executeCommand(
-                    this,
-                    command,
-                    new InputStream[] {in}
-                );
-            }
-
-            if (_failException != null) {
-                throw _failException;
-            }
-
-            if (_resultError) {
-                // This is unlikeley as the ssh command will exit with failure.
-                throw new RuntimeException(
-                    "Installation failed, please refer to installation logs"
-                );
-            }
-            else if (_goingToReboot) {
-                _deployStatus = DeployStatus.Reboot;
-            }
-            else if (_installIncomplete) {
-                _deployStatus = DeployStatus.Incomplete;
-            } else {
-                _deployStatus = DeployStatus.Complete;
-            }
-        }
-        catch (TimeLimitExceededException e){
-            log.error(
-                "Timeout during host {} install",
-                _vds.getHostName(),
-                e
-            );
-            _messages.post(
-                InstallerMessages.Severity.ERROR,
-                "Processing stopped due to timeout"
-            );
-            throw e;
-        }
-        catch(Exception e) {
-            log.error(
-                "Error during host {} install",
-                _vds.getHostName(),
-                e
-            );
-            if (_failException == null) {
-                throw e;
-            }
-            else {
-                _messages.post(
-                    InstallerMessages.Severity.ERROR,
-                    e.getMessage()
-                );
-
-                log.error(
-                    "Error during host {} install, prefering first exception: 
{}",
-                    _vds.getHostName(),
-                    _failException.getMessage()
-                );
-                log.debug("Exception", _failException);
-                throw _failException;
-            }
-        }
-    }
-
-    /*
-     * SSHDialog.Sink
-     */
-
-    @Override
-    public void setControl(SSHDialog.Control control) {
-        _control = control;
-    }
-
-    @Override
-    public void setStreams(InputStream incoming, OutputStream outgoing) {
-        _parser.setStreams(incoming, outgoing);
-    }
-
-    @Override
-    public void start() {
-        _thread.start();
-    }
-
-    @Override
-    public void stop() {
-        if (_thread != null) {
-            /*
-             * We cannot just interrupt the thread as the
-             * implementation of jboss connection pooling
-             * drops the connection when interrupted.
-             * As we may have log events pending to be written
-             * to database, we wait for some time for thread
-             * complete before interrupting.
-             */
-            try {
-                _thread.join(THREAD_JOIN_TIMEOUT);
-            }
-            catch (InterruptedException e) {
-                log.error("interrupted", e);
-            }
-            if (_thread.isAlive()) {
-                _thread.interrupt();
-                while(true) {
-                    try {
-                        _thread.join();
-                        break;
-                    }
-                    catch (InterruptedException e) {}
-                }
-            }
-            _thread = null;
-        }
-    }
-
     public void setOpenStackAgentProperties(OpenstackNetworkProviderProperties 
properties) {
         _openStackAgentProperties = properties;
         if (_openStackAgentProperties != null) {
             _messagingConfiguration = 
_openStackAgentProperties.getAgentConfiguration().getMessagingConfiguration();
-            _customizationConditions.add(CustomizationCondition.NEUTRON_SETUP);
+            addCustomizationCondition(COND_NEUTRON_SETUP);
             if (_openStackAgentProperties.isLinuxBridge()) {
-                
_customizationConditions.add(CustomizationCondition.NEUTRON_LINUX_BRIDGE_SETUP);
+                addCustomizationCondition(COND_NEUTRON_LINUX_BRIDGE_SETUP);
             }
             else if (_openStackAgentProperties.isOpenVSwitch()) {
-                
_customizationConditions.add(CustomizationCondition.NEUTRON_OPEN_VSWITCH_SETUP);
+                addCustomizationCondition(COND_NEUTRON_OPEN_VSWITCH_SETUP);
             }
         }
     }
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdeploy/VdsDeployBase.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdeploy/VdsDeployBase.java
new file mode 100644
index 0000000..054355c
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdeploy/VdsDeployBase.java
@@ -0,0 +1,609 @@
+package org.ovirt.engine.core.bll.hostdeploy;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.security.KeyPair;
+import java.security.KeyStoreException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.concurrent.Callable;
+
+import javax.naming.TimeLimitExceededException;
+
+import org.ovirt.engine.core.bll.utils.EngineSSHDialog;
+import org.ovirt.engine.core.common.businessentities.VDS;
+import org.ovirt.engine.core.common.config.Config;
+import org.ovirt.engine.core.common.config.ConfigValues;
+import org.ovirt.engine.core.utils.EngineLocalConfig;
+import org.ovirt.engine.core.utils.archivers.tar.CachedTar;
+import org.ovirt.engine.core.uutils.ssh.SSHDialog;
+import org.ovirt.otopi.constants.BaseEnv;
+import org.ovirt.otopi.constants.CoreEnv;
+import org.ovirt.otopi.constants.Queries;
+import org.ovirt.otopi.dialog.Event;
+import org.ovirt.otopi.dialog.MachineDialogParser;
+import org.ovirt.otopi.dialog.SoftError;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class VdsDeployBase implements SSHDialog.Sink, Closeable {
+
+    private static final int THREAD_JOIN_TIMEOUT = 20 * 1000; // milliseconds
+    private static final String BOOTSTRAP_CUSTOM_ENVIRONMENT_PLACE_HOLDER = 
"@ENVIRONMENT@";
+    private static final String BOOTSTRAP_ENTRY_PLACE_HOLDER = "@ENTRY@";
+
+    private static final Logger log = 
LoggerFactory.getLogger(VdsDeployBase.class);
+    private static volatile CachedTar s_deployPackage;
+
+    /**
+     * Customization vector.
+     * This is tick based vector, every event execute the next
+     * tick.
+     */
+    // BUG: Arrays.asList() cannot handle single element correctly
+    protected final List<Callable<Boolean>> CUSTOMIZATION_DIALOG_EPILOG = new 
ArrayList() {{ add(
+        new Callable<Boolean>() { public Boolean call() throws Exception {
+            _parser.cliInstall();
+            return true;
+        }}
+    );}};
+
+    /**
+     * Termination vector.
+     * This is tick based vector, every event execute the next
+     * tick.
+     */
+    protected final List<Callable<Boolean>> TERMINATION_DIALOG_PROLOG = 
Arrays.asList(
+        new Callable<Boolean>() { public Boolean call() throws Exception {
+            _resultError = (Boolean)_parser.cliEnvironmentGet(
+                BaseEnv.ERROR
+            );
+            return true;
+        }},
+        new Callable<Boolean>() { public Boolean call() throws Exception {
+            _aborted = (Boolean)_parser.cliEnvironmentGet(
+                BaseEnv.ABORTED
+            );
+            return true;
+        }}
+    );
+    protected final List<Callable<Boolean>> TERMINATION_DIALOG_EPILOG = 
Arrays.asList(
+        new Callable<Boolean>() { public Boolean call() throws Exception {
+            File logFile = new File(
+                EngineLocalConfig.getInstance().getLogDir(),
+                String.format(
+                    "%1$s%2$s%3$s-%4$s-%5$s-%6$s.log",
+                    "host-deploy",
+                    File.separator,
+                    _logPrefix,
+                    new SimpleDateFormat("yyyyMMddHHmmss").format(
+                        Calendar.getInstance().getTime()
+                    ),
+                    _vds.getHostName(),
+                    _correlationId
+                )
+            );
+            _messages.post(
+                InstallerMessages.Severity.INFO,
+                String.format(
+                    "Retrieving installation logs to: '%1$s'",
+                    logFile
+                )
+            );
+            try (final OutputStream os = new FileOutputStream(logFile)) {
+                _parser.cliDownloadLog(os);
+            }
+            catch (IOException e) {
+                throw e;
+            }
+            catch (Exception e) {
+                log.error("Unexpected exception", e);
+                throw new RuntimeException(e);
+            }
+            return true;
+        }},
+        new Callable<Boolean>() { public Boolean call() throws Exception {
+            _parser.cliEnvironmentSet(
+                CoreEnv.LOG_REMOVE_AT_EXIT,
+                true
+            );
+            return true;
+        }},
+        new Callable<Boolean>() { public Boolean call() throws Exception {
+            _parser.cliQuit();
+            return true;
+        }}
+    );
+
+    private SSHDialog.Control _control;
+    private Thread _thread;
+    private EngineSSHDialog _dialog;
+
+    private final String _logPrefix;
+    private final String _entryPoint;
+
+    protected MachineDialogParser _parser;
+    protected final InstallerMessages _messages;
+    protected VDS _vds;
+    protected String _correlationId = null;
+    protected Exception _failException = null;
+    protected boolean _resultError = false;
+    protected boolean _aborted = false;
+
+    protected abstract boolean processEvent(Event.Base bevent) throws 
IOException;
+    protected void postExecute() {}
+
+    /*
+     * Customization dialog.
+     */
+
+    /**
+     * Special annotation to specify when the customization is necessary.
+     */
+    @Target(ElementType.METHOD)
+    @Retention(RetentionPolicy.RUNTIME)
+    protected @interface CallWhen {
+        /**
+         * @return A condition that determines if the customization should run.
+         */
+        String[] value();
+    }
+    /**
+     * A set of conditions under which the conditional customizations should 
run.
+     */
+    private Set<String> _customizationConditions = new HashSet<>();
+    /**
+     * Customization tick.
+     */
+    private int _customizationIndex = 0;
+    /**
+     * Customization aborting.
+     */
+    private boolean _customizationShouldAbort = false;
+    private List<Callable<Boolean>> _customizationDialog = new ArrayList<>();
+    /**
+     * Execute the next customization vector entry.
+     */
+    private void _nextCustomizationEntry() throws Exception {
+        try {
+            if (_customizationShouldAbort) {
+                _parser.cliAbort();
+            }
+            else {
+                boolean skip = false;
+                Callable<Boolean> customizationStep = 
_customizationDialog.get(_customizationIndex);
+                Method callMethod = 
customizationStep.getClass().getDeclaredMethod("call");
+                if (callMethod != null) {
+                    CallWhen ann = callMethod.getAnnotation(CallWhen.class);
+                    skip = ann != null && 
!_customizationConditions.containsAll(Arrays.asList(ann.value()));
+                }
+
+                if (skip) {
+                    _customizationIndex++;
+                    _parser.cliNoop();
+                }
+                else {
+                    if (customizationStep.call()) {
+                        _customizationIndex++;
+                    }
+                }
+            }
+        }
+        catch (ArrayIndexOutOfBoundsException e) {
+            throw new RuntimeException("Protocol violation", e);
+        }
+        catch (SoftError e) {
+            log.error(
+                "Soft error during host {} customization dialog: {}",
+                _vds.getHostName(),
+                e.getMessage()
+            );
+            log.debug("Exception", e);
+            _failException = e;
+            _customizationShouldAbort = true;
+        }
+    }
+    protected void addCustomizationDialog(List<Callable<Boolean>> dialog) {
+        _customizationDialog.addAll(dialog);
+    }
+    protected void addCustomizationCondition(String cond) {
+        _customizationConditions.add(cond);
+    }
+
+    /*
+     * Termination dialog.
+     */
+
+    /**
+     * Termination dialog tick.
+     */
+    private int _terminationIndex = 0;
+    private final List<Callable<Boolean>> _terminationDialog = new 
ArrayList<>();
+    /**
+     * Execute the next termination vector entry.
+     */
+    private void _nextTerminationEntry() throws Exception {
+        try {
+            if (_terminationDialog.get(_terminationIndex).call()) {
+                _terminationIndex++;
+            }
+        }
+        catch (ArrayIndexOutOfBoundsException e) {
+            throw new RuntimeException("Protocol violation", e);
+        }
+    }
+    protected void addTerminationDialog(List<Callable<Boolean>> dialog) {
+        _terminationDialog.addAll(dialog);
+    }
+
+    /**
+     * Dialog implementation.
+     * Handle events incoming from host.
+     */
+    private void _threadMain() {
+        try {
+            boolean terminate = false;
+
+            while(!terminate) {
+                Event.Base bevent = _parser.nextEvent();
+
+                log.debug(
+                    "Installation of {}: Event {}",
+                    _vds.getHostName(),
+                    bevent
+                );
+
+                boolean unknown = true;
+                if (bevent instanceof Event.Terminate) {
+                    terminate = true;
+                    unknown = false;
+                }
+                else if (bevent instanceof Event.Log) {
+                    Event.Log event = (Event.Log)bevent;
+                    InstallerMessages.Severity severity;
+                    switch (event.severity) {
+                    case INFO:
+                        severity = InstallerMessages.Severity.INFO;
+                        break;
+                    case WARNING:
+                        severity = InstallerMessages.Severity.WARNING;
+                        break;
+                    default:
+                        severity = InstallerMessages.Severity.ERROR;
+                        break;
+                    }
+                    _messages.post(severity, event.record);
+                    unknown = false;
+                }
+                else if (bevent instanceof Event.QueryString) {
+                    Event.QueryString event = (Event.QueryString)bevent;
+
+                    if (Queries.CUSTOMIZATION_COMMAND.equals(event.name)) {
+                        _nextCustomizationEntry();
+                        unknown = false;
+                    }
+                    else if (Queries.TERMINATION_COMMAND.equals(event.name)) {
+                        _nextTerminationEntry();
+                        unknown = false;
+                    }
+                }
+                else if (bevent instanceof Event.QueryValue) {
+                    Event.QueryValue event = (Event.QueryValue)bevent;
+
+                    if (Queries.TIME.equals(event.name)) {
+                        _messages.post(
+                            InstallerMessages.Severity.INFO,
+                            "Setting time"
+                        );
+                        SimpleDateFormat format = new 
SimpleDateFormat("yyyyMMddHHmmssZ");
+                        format.setTimeZone(TimeZone.getTimeZone("UTC"));
+                        event.value = 
format.format(Calendar.getInstance().getTime());
+                        unknown = false;
+                    }
+                }
+                if (unknown) {
+                    unknown = processEvent(bevent);
+                }
+
+                if (bevent instanceof Event.Confirm) {
+                    Event.Confirm event = (Event.Confirm)bevent;
+                    if (unknown) {
+                        log.warn(
+                            "Installation of {}: Not confirming {}: {}",
+                            _vds.getHostName(),
+                            event.what,
+                            event.description
+                        );
+                    }
+                    _parser.sendResponse(event);
+                }
+                else if (bevent instanceof Event.QueryValue) {
+                    Event.QueryValue event = (Event.QueryValue)bevent;
+                    if (unknown) {
+                        event.abort = true;
+                    }
+                    _parser.sendResponse(event);
+                }
+                else if (bevent instanceof Event.QueryMultiString) {
+                    Event.QueryMultiString event = 
(Event.QueryMultiString)bevent;
+                    if (unknown) {
+                        event.abort = true;
+                    }
+                    _parser.sendResponse(event);
+                }
+
+                if (unknown) {
+                    throw new SoftError(
+                        String.format(
+                            "Unexpected event '%1$s'",
+                            bevent
+                        )
+                    );
+                }
+            }
+        }
+        catch (Exception e) {
+            _failException = e;
+            log.error("Error during deploy dialog", e);
+            try {
+                _control.close();
+            }
+            catch (IOException ee) {
+                log.error("Error during close", e);
+            }
+        }
+    }
+
+    /*
+     * Constructor.
+     * @param vds vds to install.
+     */
+    public VdsDeployBase(String logPrefix, String entryPoint, VDS vds) {
+        _logPrefix = logPrefix;
+        _entryPoint = entryPoint;
+        _vds = vds;
+
+        _messages = new InstallerMessages(_vds);
+        _dialog = new EngineSSHDialog();
+        _parser = new MachineDialogParser();
+        _thread = new Thread(
+            new Runnable() {
+                @Override
+                public void run() {
+                    _threadMain();
+                }
+            },
+            "VdsDeploy"
+        );
+
+        if (s_deployPackage == null) {
+            s_deployPackage = new CachedTar(
+                new File(
+                    EngineLocalConfig.getInstance().getCacheDir(),
+                    Config.<String> getValue(ConfigValues.BootstrapPackageName)
+                ),
+                new File(Config.<String> 
getValue(ConfigValues.BootstrapPackageDirectory))
+            );
+        }
+    }
+
+    /**
+     * Destructor.
+     */
+    @Override
+    protected void finalize() {
+        try {
+            close();
+        }
+        catch (IOException e) {
+            log.error("Exception during finalize", e);
+        }
+    }
+
+    /**
+     * Release resources.
+     */
+    public void close() throws IOException {
+        stop();
+        if (_dialog != null) {
+            _dialog.close();
+            _dialog = null;
+        }
+    }
+
+    public void setCorrelationId(String correlationId) {
+        _correlationId = correlationId;
+        _messages.setCorrelationId(_correlationId);
+    }
+
+    /**
+     * Set user.
+     * @param user user.
+     */
+    public void setUser(String user) {
+        _dialog.setUser(user);
+    }
+
+    /**
+     * Set key pair.
+     * @param keyPair key pair.
+     */
+    public void setKeyPair(KeyPair keyPair) {
+        _dialog.setKeyPair(keyPair);
+    }
+
+    /**
+     * Use engine default key pairs.
+     */
+    public void useDefaultKeyPair() throws KeyStoreException {
+        _dialog.useDefaultKeyPair();
+    }
+
+    /**
+     * Set password.
+     * @param password password.
+     */
+    public void setPassword(String password) {
+        _dialog.setPassword(password);
+    }
+
+    /**
+     * Main method.
+     * Execute the command and initiate the dialog.
+     */
+    public void execute() throws Exception {
+        try {
+            _dialog.setVds(_vds);
+            _dialog.connect();
+            _messages.post(
+                InstallerMessages.Severity.INFO,
+                String.format(
+                    "Connected to host %1$s with SSH key fingerprint: %2$s",
+                    _vds.getHostName(),
+                    _dialog.getHostFingerprint()
+                )
+            );
+            _dialog.authenticate();
+
+            String command = Config.<String> 
getValue(ConfigValues.BootstrapCommand).replace(
+                BOOTSTRAP_ENTRY_PLACE_HOLDER,
+                _entryPoint
+            ).replace(
+                // in future we should set here LANG, LC_ALL
+                BOOTSTRAP_CUSTOM_ENVIRONMENT_PLACE_HOLDER,
+                ""
+            );
+
+            log.info(
+                "Installation of {}. Executing command via SSH {} < {}",
+                _vds.getHostName(),
+                command,
+                s_deployPackage.getFileNoUse()
+            );
+
+            try (final InputStream in = new 
FileInputStream(s_deployPackage.getFile())) {
+                _dialog.executeCommand(
+                    this,
+                    command,
+                    new InputStream[] {in}
+                );
+            }
+
+            if (_failException != null) {
+                throw _failException;
+            }
+
+            if (_resultError) {
+                // This is unlikeley as the ssh command will exit with failure.
+                throw new RuntimeException(
+                    "Installation failed, please refer to installation logs"
+                );
+            }
+            else {
+                postExecute();
+            }
+        }
+        catch (TimeLimitExceededException e){
+            log.error(
+                "Timeout during host {} install",
+                _vds.getHostName(),
+                e
+            );
+            _messages.post(
+                InstallerMessages.Severity.ERROR,
+                "Processing stopped due to timeout"
+            );
+            throw e;
+        }
+        catch(Exception e) {
+            log.error(
+                "Error during host {} install",
+                _vds.getHostName(),
+                e
+            );
+            if (_failException == null) {
+                throw e;
+            }
+            else {
+                _messages.post(
+                    InstallerMessages.Severity.ERROR,
+                    e.getMessage()
+                );
+
+                log.error(
+                    "Error during host {} install, prefering first exception: 
{}",
+                    _vds.getHostName(),
+                    _failException.getMessage()
+                );
+                log.debug("Exception", _failException);
+                throw _failException;
+            }
+        }
+    }
+
+    /*
+     * SSHDialog.Sink
+     */
+
+    @Override
+    public void setControl(SSHDialog.Control control) {
+        _control = control;
+    }
+
+    @Override
+    public void setStreams(InputStream incoming, OutputStream outgoing) {
+        _parser.setStreams(incoming, outgoing);
+    }
+
+    @Override
+    public void start() {
+        _thread.start();
+    }
+
+    @Override
+    public void stop() {
+        if (_thread != null) {
+            /*
+             * We cannot just interrupt the thread as the
+             * implementation of jboss connection pooling
+             * drops the connection when interrupted.
+             * As we may have log events pending to be written
+             * to database, we wait for some time for thread
+             * complete before interrupting.
+             */
+            try {
+                _thread.join(THREAD_JOIN_TIMEOUT);
+            }
+            catch (InterruptedException e) {
+                log.error("interrupted", e);
+            }
+            if (_thread.isAlive()) {
+                _thread.interrupt();
+                while(true) {
+                    try {
+                        _thread.join();
+                        break;
+                    }
+                    catch (InterruptedException e) {}
+                }
+            }
+            _thread = null;
+        }
+    }
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
index fbea703..a09aa40 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
@@ -1179,7 +1179,7 @@
         "MYTMP=\"$(TMPDIR=\"${OVIRT_TMPDIR}\" mktemp -d -t 
ovirt-XXXXXXXXXX)\"; " +
         "trap \"chmod -R u+rwX \\\"${MYTMP}\\\" > /dev/null 2>&1; rm -fr 
\\\"${MYTMP}\\\" > /dev/null 2>&1\" 0; " +
         "tar --warning=no-timestamp -C \"${MYTMP}\" -x && " +
-        "@ENVIRONMENT@ \"${MYTMP}\"/setup DIALOG/dialect=str:machine 
DIALOG/customization=bool:True"
+        "@ENVIRONMENT@ \"${MYTMP}\"/@ENTRY@ DIALOG/dialect=str:machine 
DIALOG/customization=bool:True"
     )
     BootstrapCommand,
 


-- 
To view, visit https://gerrit.ovirt.org/39964
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: If6055fc395765f054634afe2b06fd56158217154
Gerrit-PatchSet: 6
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Alon Bar-Lev <alo...@redhat.com>
Gerrit-Reviewer: Jenkins CI
Gerrit-Reviewer: Moti Asayag <masa...@redhat.com>
Gerrit-Reviewer: automat...@ovirt.org
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to