<commit_before>package org.ovirt.engine.core.bll;

import java.util.ArrayList;
import java.util.List;

import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.action.AddVdsActionParameters;
import org.ovirt.engine.core.common.action.ApproveVdsParameters;
import org.ovirt.engine.core.common.action.UpdateVdsActionParameters;
import org.ovirt.engine.core.common.action.VdcActionParametersBase;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdcReturnValueBase;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.VDSStatus;
import org.ovirt.engine.core.common.businessentities.VDSType;
import org.ovirt.engine.core.common.businessentities.VdsStatic;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.queries.RegisterVdsParameters;
import org.ovirt.engine.core.compat.DateTime;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.compat.RefObject;
import org.ovirt.engine.core.compat.Regex;
import org.ovirt.engine.core.compat.StringHelper;
import org.ovirt.engine.core.compat.TransactionScopeOption;
import org.ovirt.engine.core.dal.VdcBllMessages;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase;
import org.ovirt.engine.core.dao.VdsDAO;
import org.ovirt.engine.core.utils.log.Log;
import org.ovirt.engine.core.utils.log.LogFactory;
import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil;
import org.ovirt.engine.core.utils.transaction.TransactionMethod;
import org.ovirt.engine.core.utils.transaction.TransactionSupport;

public class RegisterVdsQuery<P extends RegisterVdsParameters> extends QueriesCommandBase<P> {
    private final AuditLogableBase _logable;

    public RegisterVdsQuery(P parameters) {
        super(parameters);
        _logable = new AuditLogableBase(parameters.getVdsId());
    }

    private AuditLogType _error = AuditLogType.forValue(0);
    private static Object _doubleRegistrationLock = new Object();

    private static final String validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.:_";
    private String _strippedVdsUniqueId;

    private String getStrippedVdsUniqueId() {
        if (_strippedVdsUniqueId == null) {
            // since we use the management IP field, makes sense to remove the
            // illegal characters in advance
            StringBuilder builder = new StringBuilder();
            for (char ch : getParameters().getVdsUniqueId().toCharArray()) {
                if (validChars.indexOf(ch) != -1) {
                    builder.append(ch);
                }
            }
            _strippedVdsUniqueId = builder.toString();
        }
        return _strippedVdsUniqueId;
    }

    private List<VDS> _vdssByUniqueId;

    private List<VDS> getVdssByUniqueId() {
        if (_vdssByUniqueId == null) {
            VdsInstaller.UpdateUniqueId(getStrippedVdsUniqueId());
            _vdssByUniqueId = DbFacade.getInstance().getVdsDAO().getAllWithUniqueId(getStrippedVdsUniqueId());
        }
        return _vdssByUniqueId;
    }

    protected boolean CanDoAction(RefObject<String> errorMessage) {
        boolean returnValue = true;
        errorMessage.argvalue = "";
        Long otp = getParameters().getOtp();
        try {
            String hostName = getParameters().getVdsHostName();
            if (StringHelper.isNullOrEmpty(hostName)) {
                errorMessage.argvalue = "Cannot register Host - no Hostname address specified.";
                returnValue = false;
            } else {
                List<VDS> vdssByUniqueId = getVdssByUniqueId();
                if (vdssByUniqueId.size() > 1) {
                    errorMessage.argvalue = "Cannot register Host - unique id is ambigious.";
                    returnValue = false;
                } else if (vdssByUniqueId.size() == 1) {
                    VDS vds = vdssByUniqueId.get(0);
                    if (!VdsHandler.isPendingOvirt(vds)) {
                        errorMessage.argvalue =
                                String.format("Illegal Host status %s and/or type %s for host %s, expected %s type with %s status.",
                                        vds.getstatus().name(),
                                        vds.getvds_type().name(),
                                        vds.getvds_name(),
                                        VDSType.oVirtNode.name(),
                                        VDSStatus.PendingApproval.name());
                        errorMessage.argvalue = VdcBllMessages.VDS_STATUS_NOT_VALID_FOR_UPDATE.name();
                        returnValue = false;
                    } else if (otp != null && !isValidOtp(vds, otp)) {
                        errorMessage.argvalue = "Invalid OTP for host " + hostName;
                        returnValue = false;
                    }
                }
            }
        } catch (RuntimeException ex) {
            log.error("RegisterVdsQuery::CanDoAction: An exception has been thrown.", ex);
            errorMessage.argvalue = String.format("Cannot register Host - An exception has been thrown: %1$s",
                    ex.getMessage());
            returnValue = false;
        }

        return returnValue;
    }

    private boolean isValidOtp(VDS vds, Long otp) {
        if (otp != null && otp.longValue() == vds.getOtpValidity()) {
            Integer otpExpiration = Config.<Integer> GetValue(ConfigValues.OtpExpirationInSeconds);
            DateTime otpValidity = new DateTime(otp);
            otpValidity.AddSeconds(otpExpiration);
            if (otpValidity.before(DateTime.getUtcNow())) {
                return true;
            }
        }
        return false;
    }

    @Override
    protected void executeQueryCommand() {

        // CanDoAction:
        String errorMessage = null;
        RefObject<String> tempRefObject = new RefObject<String>(errorMessage);
        boolean tempVar = !CanDoAction(tempRefObject);
        errorMessage = tempRefObject.argvalue;
        if (tempVar) {
            log.errorFormat("RegisterVdsQuery::ExecuteQueryCommand: CanDoAction failed: {0}", errorMessage);
            throw new RuntimeException(errorMessage);
        }

        // ExecuteAction:
        TransactionSupport.executeInScope(TransactionScopeOption.Required, new TransactionMethod<Object>() {
            @Override
            public Object runInTransaction() {
                ExecuteWithoutTransaction();
                return null;
            }
        });
    }

    protected boolean ExecuteWithoutTransaction() {
        boolean succeeded = false;

        try {
            log.info("Running Command: RegisterVds");
            ExecuteRegisterVdsCommand();
            succeeded = getQueryReturnValue().getSucceeded();
        }

        catch (RuntimeException ex) {
            log.error("RegisterVdsQuery::ExecuteWithoutTransaction: An exception has been thrown.", ex);
        }

        finally {
            WriteToAuditLog();
        }

        return succeeded;
    }

    protected void ExecuteRegisterVdsCommand() {
        synchronized (_doubleRegistrationLock) {
            // force to reload vdss by unique ID used later on
            _vdssByUniqueId = null;
            VDS vdsByUniqueId = getVdssByUniqueId().size() != 0 ? getVdssByUniqueId().get(0) : null;

            // in case oVirt host was added for the second time - perform approval
            if (vdsByUniqueId != null && vdsByUniqueId.getstatus() == VDSStatus.PendingApproval
                    && getParameters().getVdsType() == VDSType.oVirtNode
                    && getParameters().getOtp() != null) {

                getQueryReturnValue().setSucceeded(dispatchOvirtApprovalCommand(vdsByUniqueId.getId()));
                return;
            }

            if (Config.<Boolean> GetValue(ConfigValues.LogVdsRegistration)) {
                log.info("RegisterVdsQuery::ExecuteCommand - Entering");
            }

            if (StringHelper.isNullOrEmpty(getParameters().getVdsName())) {
                getParameters().setVdsName(getParameters().getVdsUniqueId());
                if (Config.<Boolean> GetValue(ConfigValues.LogVdsRegistration)) {
                    log.info("RegisterVdsQuery::ExecuteCommand - VdsName empty, using VdsUnique ID as name");
                }
            }

            _logable.AddCustomValue("VdsName1", getParameters().getVdsName());

            Guid vdsGroupId;
            if (getParameters().getVdsGroupId().equals(Guid.Empty)) {
                vdsGroupId = new Guid(
                        Config.<String> GetValue(ConfigValues.PowerClientAutoRegistrationDefaultVdsGroupID));
                if (Config.<Boolean> GetValue(ConfigValues.LogVdsRegistration)) {
                    log.infoFormat(
                            "RegisterVdsQuery::ExecuteCommand - VdsGroupId recieved as -1, using PowerClientAutoRegistrationDefaultVdsGroupID: {0}",
                            vdsGroupId);
                }
            } else {
                vdsGroupId = getParameters().getVdsGroupId();
            }

            if (Config.<Boolean> GetValue(ConfigValues.LogVdsRegistration) && vdsByUniqueId != null) {
                log.infoFormat(
                        "RegisterVdsQuery::ExecuteCommand - found vds {0} with existing Unique Id {1}.  Will try to update existing vds",
                        vdsByUniqueId.getId(),
                        vdsByUniqueId.getUniqueId());
            }

            boolean isPending = false;
            // TODO: always add in pending state, and if auto approve call
            // approve command action after registration
            RefObject<Boolean> tempRefObject = new RefObject<Boolean>(isPending);
            getQueryReturnValue().setSucceeded(
                    HandleOldVdssWithSameHostName(vdsByUniqueId) && HandleOldVdssWithSameName(vdsByUniqueId)
                    && CheckAutoApprovalDefinitions(tempRefObject) && Register(vdsByUniqueId, vdsGroupId, tempRefObject.argvalue));
            isPending = tempRefObject.argvalue;
            if (Config.<Boolean> GetValue(ConfigValues.LogVdsRegistration)) {
                log.infoFormat("RegisterVdsQuery::ExecuteCommand - Leaving Succeded value is {0}",
                        getQueryReturnValue().getSucceeded());
            }
        }
    }

    private boolean dispatchOvirtApprovalCommand(Guid oVirtId) {
        boolean isApprovalDispatched = true;
        final ApproveVdsParameters params = new ApproveVdsParameters();
        params.setVdsId(oVirtId);
        params.setApprovedByRegister(true);

        try {
            ThreadPoolUtil.execute(new Runnable() {

                @Override
                public void run() {
                    try {
                        VdcReturnValueBase ret =
                            Backend.getInstance().runInternalAction(VdcActionType.ApproveVds, params);
                        if (ret == null || !ret.getSucceeded()) {
                            log.errorFormat("Approval of oVirt {0} failed. ", params.getVdsId());
                        } else if (ret.getSucceeded()) {
                            log.infoFormat("Approval of oVirt {0} ended successefully. ", params.getVdsId());
                        }
                    } catch (RuntimeException ex) {<commit_msg>core: minor cleanup on RegisterVdsQuery<commit_after>package org.ovirt.engine.core.bll;

import java.util.ArrayList;
import java.util.List;

import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.action.AddVdsActionParameters;
import org.ovirt.engine.core.common.action.ApproveVdsParameters;
import org.ovirt.engine.core.common.action.UpdateVdsActionParameters;
import org.ovirt.engine.core.common.action.VdcActionParametersBase;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdcReturnValueBase;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.VDSStatus;
import org.ovirt.engine.core.common.businessentities.VDSType;
import org.ovirt.engine.core.common.businessentities.VdsStatic;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.queries.RegisterVdsParameters;
import org.ovirt.engine.core.compat.DateTime;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.compat.RefObject;
import org.ovirt.engine.core.compat.Regex;
import org.ovirt.engine.core.compat.StringHelper;
import org.ovirt.engine.core.compat.TransactionScopeOption;
import org.ovirt.engine.core.dal.VdcBllMessages;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase;
import org.ovirt.engine.core.dao.VdsDAO;
import org.ovirt.engine.core.utils.log.Log;
import org.ovirt.engine.core.utils.log.LogFactory;
import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil;
import org.ovirt.engine.core.utils.transaction.TransactionMethod;
import org.ovirt.engine.core.utils.transaction.TransactionSupport;

public class RegisterVdsQuery<P extends RegisterVdsParameters> extends QueriesCommandBase<P> {
    private final AuditLogableBase _logable;

    public RegisterVdsQuery(P parameters) {
        super(parameters);
        _logable = new AuditLogableBase(parameters.getVdsId());
    }

    private AuditLogType _error = AuditLogType.forValue(0);
    private static Object _doubleRegistrationLock = new Object();

    private static final String validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.:_";
    private String _strippedVdsUniqueId;

    private String getStrippedVdsUniqueId() {
        if (_strippedVdsUniqueId == null) {
            // since we use the management IP field, makes sense to remove the
            // illegal characters in advance
            StringBuilder builder = new StringBuilder();
            for (char ch : getParameters().getVdsUniqueId().toCharArray()) {
                if (validChars.indexOf(ch) != -1) {
                    builder.append(ch);
                }
            }
            _strippedVdsUniqueId = builder.toString();
        }
        return _strippedVdsUniqueId;
    }

    private List<VDS> _vdssByUniqueId;

    private List<VDS> getVdssByUniqueId() {
        if (_vdssByUniqueId == null) {
            VdsInstaller.UpdateUniqueId(getStrippedVdsUniqueId());
            _vdssByUniqueId = DbFacade.getInstance().getVdsDAO().getAllWithUniqueId(getStrippedVdsUniqueId());
        }
        return _vdssByUniqueId;
    }

    protected boolean CanDoAction(RefObject<String> errorMessage) {
        boolean returnValue = true;
        errorMessage.argvalue = "";
        Long otp = getParameters().getOtp();
        try {
            String hostName = getParameters().getVdsHostName();
            if (StringHelper.isNullOrEmpty(hostName)) {
                errorMessage.argvalue = "Cannot register Host - no Hostname address specified.";
                returnValue = false;
            } else {
                List<VDS> vdssByUniqueId = getVdssByUniqueId();
                if (vdssByUniqueId.size() > 1) {
                    errorMessage.argvalue = "Cannot register Host - unique id is ambigious.";
                    returnValue = false;
                } else if (vdssByUniqueId.size() == 1) {
                    VDS vds = vdssByUniqueId.get(0);
                    if (!VdsHandler.isPendingOvirt(vds)) {
                        errorMessage.argvalue =
                                String.format("Illegal Host status %s and/or type %s for host %s, expected %s type with %s status.",
                                        vds.getstatus().name(),
                                        vds.getvds_type().name(),
                                        vds.getvds_name(),
                                        VDSType.oVirtNode.name(),
                                        VDSStatus.PendingApproval.name());
                        errorMessage.argvalue = VdcBllMessages.VDS_STATUS_NOT_VALID_FOR_UPDATE.name();
                        returnValue = false;
                    } else if (otp != null && !isValidOtp(vds, otp)) {
                        errorMessage.argvalue = "Invalid OTP for host " + hostName;
                        returnValue = false;
                    }
                }
            }
        } catch (RuntimeException ex) {
            log.error("RegisterVdsQuery::CanDoAction: An exception has been thrown.", ex);
            errorMessage.argvalue = String.format("Cannot register Host - An exception has been thrown: %1$s",
                    ex.getMessage());
            returnValue = false;
        }

        return returnValue;
    }

    private boolean isValidOtp(VDS vds, Long otp) {
        if (otp != null && otp.longValue() == vds.getOtpValidity()) {
            Integer otpExpiration = Config.<Integer> GetValue(ConfigValues.OtpExpirationInSeconds);
            DateTime otpValidity = new DateTime(otp);
            otpValidity.AddSeconds(otpExpiration);
            if (otpValidity.before(DateTime.getUtcNow())) {
                return true;
            }
        }
        return false;
    }

    @Override
    protected void executeQueryCommand() {

        // CanDoAction:
        String errorMessage = null;
        RefObject<String> tempRefObject = new RefObject<String>(errorMessage);
        boolean tempVar = !CanDoAction(tempRefObject);
        errorMessage = tempRefObject.argvalue;
        if (tempVar) {
            log.errorFormat("RegisterVdsQuery::ExecuteQueryCommand: CanDoAction failed: {0}", errorMessage);
            throw new RuntimeException(errorMessage);
        }

        // ExecuteAction:
        TransactionSupport.executeInScope(TransactionScopeOption.Required, new TransactionMethod<Object>() {
            @Override
            public Object runInTransaction() {
                ExecuteWithoutTransaction();
                return null;
            }
        });
    }

    protected boolean ExecuteWithoutTransaction() {
        boolean succeeded = false;

        try {
            log.info("Running Command: RegisterVds");
            ExecuteRegisterVdsCommand();
            succeeded = getQueryReturnValue().getSucceeded();
        }

        catch (RuntimeException ex) {
            log.error("RegisterVdsQuery::ExecuteWithoutTransaction: An exception has been thrown.", ex);
        }

        finally {
            WriteToAuditLog();
        }

        return succeeded;
    }

    protected void ExecuteRegisterVdsCommand() {
        synchronized (_doubleRegistrationLock) {
            // force to reload vdss by unique ID used later on
            _vdssByUniqueId = null;
            VDS vdsByUniqueId = getVdssByUniqueId().size() != 0 ? getVdssByUniqueId().get(0) : null;

            // in case oVirt host was added for the second time - perform approval
            if (vdsByUniqueId != null && vdsByUniqueId.getstatus() == VDSStatus.PendingApproval
                    && getParameters().getVdsType() == VDSType.oVirtNode
                    && getParameters().getOtp() != null) {

                getQueryReturnValue().setSucceeded(dispatchOvirtApprovalCommand(vdsByUniqueId.getId()));
                return;
            }

            if (Config.<Boolean> GetValue(ConfigValues.LogVdsRegistration)) {
                log.info("RegisterVdsQuery::ExecuteCommand - Entering");
            }

            if (StringHelper.isNullOrEmpty(getParameters().getVdsName())) {
                getParameters().setVdsName(getParameters().getVdsUniqueId());
                if (Config.<Boolean> GetValue(ConfigValues.LogVdsRegistration)) {
                    log.info("RegisterVdsQuery::ExecuteCommand - VdsName empty, using VdsUnique ID as name");
                }
            }

            _logable.AddCustomValue("VdsName1", getParameters().getVdsName());

            Guid vdsGroupId;
            if (getParameters().getVdsGroupId().equals(Guid.Empty)) {
                vdsGroupId = new Guid(
                        Config.<String> GetValue(ConfigValues.PowerClientAutoRegistrationDefaultVdsGroupID));
                if (Config.<Boolean> GetValue(ConfigValues.LogVdsRegistration)) {
                    log.infoFormat(
                            "RegisterVdsQuery::ExecuteCommand - VdsGroupId recieved as -1, using PowerClientAutoRegistrationDefaultVdsGroupID: {0}",
                            vdsGroupId);
                }
            } else {
                vdsGroupId = getParameters().getVdsGroupId();
            }

            if (Config.<Boolean> GetValue(ConfigValues.LogVdsRegistration) && vdsByUniqueId != null) {
                log.infoFormat(
                        "RegisterVdsQuery::ExecuteCommand - found vds {0} with existing Unique Id {1}.  Will try to update existing vds",
                        vdsByUniqueId.getId(),
                        vdsByUniqueId.getUniqueId());
            }

            // TODO: always add in pending state, and if auto approve call
            // approve command action after registration
            RefObject<Boolean> isPending = new RefObject<Boolean>(Boolean.FALSE);
            getQueryReturnValue().setSucceeded(
                    HandleOldVdssWithSameHostName(vdsByUniqueId) && HandleOldVdssWithSameName(vdsByUniqueId)
                            && CheckAutoApprovalDefinitions(isPending)
                            && Register(vdsByUniqueId, vdsGroupId, isPending.argvalue.booleanValue()));
            if (Config.<Boolean> GetValue(ConfigValues.LogVdsRegistration)) {
                log.infoFormat("RegisterVdsQuery::ExecuteCommand - Leaving Succeded value is {0}",
                        getQueryReturnValue().getSucceeded());
            }
        }
    }

    private boolean dispatchOvirtApprovalCommand(Guid oVirtId) {
        boolean isApprovalDispatched = true;
        final ApproveVdsParameters params = new ApproveVdsParameters();
        params.setVdsId(oVirtId);
        params.setApprovedByRegister(true);

        try {
            ThreadPoolUtil.execute(new Runnable() {

                @Override
                public void run() {
                    try {
                        VdcReturnValueBase ret =
                            Backend.getInstance().runInternalAction(VdcActionType.ApproveVds, params);
                        if (ret == null || !ret.getSucceeded()) {
                            log.errorFormat("Approval of oVirt {0} failed. ", params.getVdsId());
                        } else if (ret.getSucceeded()) {
                            log.infoFormat("Approval of oVirt {0} ended successefully. ", params.getVdsId());
                        }
                    } catch (RuntimeException ex) {
{'fraction_non_alphanumeric': 0.09544787077826726, 'fraction_numerical': 0.00233221041720653, 'mean_word_length': 2.168012039950746, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2658297', 'n_tokens_mistral': 6327, 'n_tokens_neox': 6125, 'n_words': 1143}