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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.hostedengine.HostedEngineHelper;
import org.ovirt.engine.core.bll.utils.PermissionSubject;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.action.AttachStorageDomainToPoolParameters;
import org.ovirt.engine.core.common.action.LockProperties;
import org.ovirt.engine.core.common.action.RemoveDiskParameters;
import org.ovirt.engine.core.common.action.StorageDomainManagementParameter;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdcReturnValueBase;
import org.ovirt.engine.core.common.businessentities.StorageDomain;
import org.ovirt.engine.core.common.businessentities.StorageDomainType;
import org.ovirt.engine.core.common.businessentities.StoragePoolStatus;
import org.ovirt.engine.core.common.businessentities.StorageServerConnections;
import org.ovirt.engine.core.common.businessentities.storage.BaseDisk;
import org.ovirt.engine.core.common.businessentities.storage.LUNs;
import org.ovirt.engine.core.common.businessentities.storage.StorageType;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.constants.StorageConstants;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.locks.LockingGroup;
import org.ovirt.engine.core.common.queries.GetExistingStorageDomainListParameters;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.common.utils.Pair;
import org.ovirt.engine.core.common.vdscommands.GetDeviceListVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.StoragePoolDao;
import org.ovirt.engine.core.dao.StorageServerConnectionDao;
import org.ovirt.engine.core.utils.transaction.TransactionMethod;
import org.ovirt.engine.core.utils.transaction.TransactionSupport;

/**
 * <pre>
 * Try to import the hosted engine storage domain which is already connected to the host by the hosted engine broker.
 * We use 1) the Storage Domain name from the config values
 * <code>{@linkplain org.ovirt.engine.core.common.config.ConfigValues#HostedEngineStorageDomainName}</code>
 * 2) The connection details are fetched from the deviceList
 * {@link org.ovirt.engine.core.common.vdscommands.VDSCommandType#GetDeviceList} connected in vdsm
 * (as the domain already connected) and crossed the storage domain info.
 * With that in hand we are able to get the connection user/pass (in case of block device)
 * </pre>
 */
public class ImportHostedEngineStorageDomainCommand<T extends StorageDomainManagementParameter> extends CommandBase<T> {

    @Inject
    private StoragePoolDao storagePoolDao;
    @Inject
    private StorageServerConnectionDao storageServerConnectionDao;
    @Inject
    private HostedEngineHelper hostedEngineHelper;
    private StorageDomain heStorageDomain;
    static final StorageType[] SUPPORTED_DOMAIN_TYPES =
            { StorageType.NFS, StorageType.FCP, StorageType.GLUSTERFS, StorageType.ISCSI };

    public ImportHostedEngineStorageDomainCommand(T parameters) {
        super(parameters);
    }

    public ImportHostedEngineStorageDomainCommand(T parameters, CommandContext cmdContext) {
        super(parameters, cmdContext);
    }

    @Override
    protected void init() {
        setVdsId(getParameters().getVdsId());
        fetchStorageDomainInfo();
    }

    @Override
    protected boolean canDoAction() {
        // no point in importing this domain without an active DC. The hosted
        // engine domain should never be the first, or master domain of a DC
        if (storagePoolDao.get(getVds().getStoragePoolId()).getStatus() != StoragePoolStatus.Up) {
            return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_MASTER_STORAGE_DOMAIN_NOT_ACTIVE);
        }
        // if sd imported already, fail
        if (hostedEngineHelper.getStorageDomain() != null) {
            return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_ALREADY_EXIST);
        }

        // fetch info on storage domain from VDSM, sets #heStorageDomain
        if (heStorageDomain == null) {
            return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_NOT_EXIST);
        }

        if (!Arrays.asList(SUPPORTED_DOMAIN_TYPES).contains(heStorageDomain.getStorageType())) {
            return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_TYPE_UNSUPPORTED);
        }
        return true;
    }

    @Override
    protected void executeCommand() {
        StorageDomainManagementParameter addSdParams =
                new StorageDomainManagementParameter(heStorageDomain.getStorageStaticData());
        addSdParams.setVdsId(getParameters().getVdsId());
        addSdParams.setStoragePoolId(getVds().getStoragePoolId());

        VdcActionType actionType = null;
        switch (heStorageDomain.getStorageType()) {
        case NFS:
        case GLUSTERFS:
            actionType = VdcActionType.AddExistingFileStorageDomain;
            addStorageServerConnection();
            break;
        case ISCSI:
            discoverBlockConnectionDetails();
        case FCP:
            actionType = VdcActionType.AddExistingBlockStorageDomain;
            removeHostedEngineLunDisk();
            break;
        }

        // note - every former action must set succeeded on success.
        if (getSucceeded()) {
            setSucceeded(getBackend().runInternalAction(
                    actionType,
                    addSdParams,
                    getContext()).getSucceeded());
        }

        if (getSucceeded()) {
            AttachStorageDomainToPoolParameters attachSdParams =
                    new AttachStorageDomainToPoolParameters(
                            addSdParams.getStorageDomainId(),
                            addSdParams.getStoragePoolId());
            setSucceeded(getBackend().runInternalAction(
                    VdcActionType.AttachStorageDomainToPool,
                    attachSdParams,
                    getContext()).getSucceeded());
        }

        setActionReturnValue(heStorageDomain);
    }

    private void discoverBlockConnectionDetails() {
        // get device list
        VDSReturnValue getDeviceList = runVdsCommand(
                VDSCommandType.GetDeviceList,
                new GetDeviceListVDSCommandParameters(
                        getParameters().getVdsId(),
                        heStorageDomain.getStorageType()));

        if (getDeviceList.getSucceeded() && getDeviceList.getReturnValue() != null
                && heStorageDomain.getStorageStaticData().getStorage() != null) {
            for (LUNs lun : (ArrayList<LUNs>) getDeviceList.getReturnValue()) {
                // match a lun vgid to the domain vgid.
                if (heStorageDomain.getStorage().equals(lun.getvolume_group_id())) {
                    // found a lun. Use its connection details
                    heStorageDomain.getStorageStaticData()
                            .setConnection(lun.getLunConnections().get(0));
                    setSucceeded(true);
                    break;
                }
            }
            if (!getSucceeded()) {
                log.error("There are no luns with VG that match the SD VG '{}'."
                        + " Connections details are missing.  completing this automatic import");
            }
        }
    }

    /**
     * For File based storage only, we need to save the connection in DB. It is implicitly called for SAN domains.
     */
    private void addStorageServerConnection() {
        TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() {
            @Override
            public Void runInTransaction() {
                StorageServerConnections connection = heStorageDomain.getStorageStaticData().getConnection();
                connection.setId(Guid.newGuid().toString());
                storageServerConnectionDao.save(connection);
                // make sure the storage domain object is full for the rest of the flow
                heStorageDomain.setStorage(connection.getId());
                setSucceeded(true);
                getCompensationContext().snapshotEntity(connection);
                getCompensationContext().stateChanged();
                return null;
            }
        });
    }

    private void removeHostedEngineLunDisk() {
        List<BaseDisk> disks =
                getDbFacade().getBaseDiskDao().getDisksByAlias(StorageConstants.HOSTED_ENGINE_LUN_DISK_ALIAS);
        if (disks != null && !disks.isEmpty()) {
            BaseDisk heDirectLun = disks.get(0);
            VdcReturnValueBase removeDisk = getBackend().runInternalAction(<commit_msg>engine: Set the vfsType glusterfs when importing HE domain<commit_after>package org.ovirt.engine.core.bll;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.hostedengine.HostedEngineHelper;
import org.ovirt.engine.core.bll.utils.PermissionSubject;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.action.AttachStorageDomainToPoolParameters;
import org.ovirt.engine.core.common.action.LockProperties;
import org.ovirt.engine.core.common.action.RemoveDiskParameters;
import org.ovirt.engine.core.common.action.StorageDomainManagementParameter;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdcReturnValueBase;
import org.ovirt.engine.core.common.businessentities.StorageDomain;
import org.ovirt.engine.core.common.businessentities.StorageDomainType;
import org.ovirt.engine.core.common.businessentities.StoragePoolStatus;
import org.ovirt.engine.core.common.businessentities.StorageServerConnections;
import org.ovirt.engine.core.common.businessentities.storage.BaseDisk;
import org.ovirt.engine.core.common.businessentities.storage.LUNs;
import org.ovirt.engine.core.common.businessentities.storage.StorageType;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.constants.StorageConstants;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.locks.LockingGroup;
import org.ovirt.engine.core.common.queries.GetExistingStorageDomainListParameters;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.common.utils.Pair;
import org.ovirt.engine.core.common.vdscommands.GetDeviceListVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.StoragePoolDao;
import org.ovirt.engine.core.dao.StorageServerConnectionDao;
import org.ovirt.engine.core.utils.transaction.TransactionMethod;
import org.ovirt.engine.core.utils.transaction.TransactionSupport;

/**
 * <pre>
 * Try to import the hosted engine storage domain which is already connected to the host by the hosted engine broker.
 * We use 1) the Storage Domain name from the config values
 * <code>{@linkplain org.ovirt.engine.core.common.config.ConfigValues#HostedEngineStorageDomainName}</code>
 * 2) The connection details are fetched from the deviceList
 * {@link org.ovirt.engine.core.common.vdscommands.VDSCommandType#GetDeviceList} connected in vdsm
 * (as the domain already connected) and crossed the storage domain info.
 * With that in hand we are able to get the connection user/pass (in case of block device)
 * </pre>
 */
public class ImportHostedEngineStorageDomainCommand<T extends StorageDomainManagementParameter> extends CommandBase<T> {

    @Inject
    private StoragePoolDao storagePoolDao;
    @Inject
    private StorageServerConnectionDao storageServerConnectionDao;
    @Inject
    private HostedEngineHelper hostedEngineHelper;
    private StorageDomain heStorageDomain;
    static final StorageType[] SUPPORTED_DOMAIN_TYPES =
            { StorageType.NFS, StorageType.FCP, StorageType.GLUSTERFS, StorageType.ISCSI };

    public ImportHostedEngineStorageDomainCommand(T parameters) {
        super(parameters);
    }

    public ImportHostedEngineStorageDomainCommand(T parameters, CommandContext cmdContext) {
        super(parameters, cmdContext);
    }

    @Override
    protected void init() {
        setVdsId(getParameters().getVdsId());
        fetchStorageDomainInfo();
    }

    @Override
    protected boolean canDoAction() {
        // no point in importing this domain without an active DC. The hosted
        // engine domain should never be the first, or master domain of a DC
        if (storagePoolDao.get(getVds().getStoragePoolId()).getStatus() != StoragePoolStatus.Up) {
            return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_MASTER_STORAGE_DOMAIN_NOT_ACTIVE);
        }
        // if sd imported already, fail
        if (hostedEngineHelper.getStorageDomain() != null) {
            return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_ALREADY_EXIST);
        }

        // fetch info on storage domain from VDSM, sets #heStorageDomain
        if (heStorageDomain == null) {
            return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_NOT_EXIST);
        }

        if (!Arrays.asList(SUPPORTED_DOMAIN_TYPES).contains(heStorageDomain.getStorageType())) {
            return failCanDoAction(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DOMAIN_TYPE_UNSUPPORTED);
        }
        return true;
    }

    @Override
    protected void executeCommand() {
        StorageDomainManagementParameter addSdParams =
                new StorageDomainManagementParameter(heStorageDomain.getStorageStaticData());
        addSdParams.setVdsId(getParameters().getVdsId());
        addSdParams.setStoragePoolId(getVds().getStoragePoolId());

        VdcActionType actionType = null;
        switch (heStorageDomain.getStorageType()) {
        case NFS:
        case GLUSTERFS:
            actionType = VdcActionType.AddExistingFileStorageDomain;
            addStorageServerConnection();
            break;
        case ISCSI:
            discoverBlockConnectionDetails();
        case FCP:
            actionType = VdcActionType.AddExistingBlockStorageDomain;
            removeHostedEngineLunDisk();
            break;
        }

        // note - every former action must set succeeded on success.
        if (getSucceeded()) {
            setSucceeded(getBackend().runInternalAction(
                    actionType,
                    addSdParams,
                    getContext()).getSucceeded());
        }

        if (getSucceeded()) {
            AttachStorageDomainToPoolParameters attachSdParams =
                    new AttachStorageDomainToPoolParameters(
                            addSdParams.getStorageDomainId(),
                            addSdParams.getStoragePoolId());
            setSucceeded(getBackend().runInternalAction(
                    VdcActionType.AttachStorageDomainToPool,
                    attachSdParams,
                    getContext()).getSucceeded());
        }

        setActionReturnValue(heStorageDomain);
    }

    private void discoverBlockConnectionDetails() {
        // get device list
        VDSReturnValue getDeviceList = runVdsCommand(
                VDSCommandType.GetDeviceList,
                new GetDeviceListVDSCommandParameters(
                        getParameters().getVdsId(),
                        heStorageDomain.getStorageType()));

        if (getDeviceList.getSucceeded() && getDeviceList.getReturnValue() != null
                && heStorageDomain.getStorageStaticData().getStorage() != null) {
            for (LUNs lun : (ArrayList<LUNs>) getDeviceList.getReturnValue()) {
                // match a lun vgid to the domain vgid.
                if (heStorageDomain.getStorage().equals(lun.getvolume_group_id())) {
                    // found a lun. Use its connection details
                    heStorageDomain.getStorageStaticData()
                            .setConnection(lun.getLunConnections().get(0));
                    setSucceeded(true);
                    break;
                }
            }
            if (!getSucceeded()) {
                log.error("There are no luns with VG that match the SD VG '{}'."
                        + " Connections details are missing.  completing this automatic import");
            }
        }
    }

    /**
     * For File based storage only, we need to save the connection in DB. It is implicitly called for SAN domains.
     */
    private void addStorageServerConnection() {
        TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() {
            @Override
            public Void runInTransaction() {
                StorageServerConnections connection = heStorageDomain.getStorageStaticData().getConnection();
                connection.setId(Guid.newGuid().toString());
                if (heStorageDomain.getStorageType() == StorageType.GLUSTERFS) {
                    // The use of the vfs type is mainly used for posix Storage Domains, usually,
                    // adding a posix SD will have a defined vfs type configured by the user,
                    // for this specific Gluster Storage Domain the user does not indicate the vfs type,
                    // and that is the reason why it is done only for Gluster
                    connection.setVfsType(StorageType.GLUSTERFS.name().toLowerCase());
                }
                storageServerConnectionDao.save(connection);
                // make sure the storage domain object is full for the rest of the flow
                heStorageDomain.setStorage(connection.getId());
                setSucceeded(true);
                getCompensationContext().snapshotEntity(connection);
                getCompensationContext().stateChanged();
                return null;
            }
        });
    }

    private void removeHostedEngineLunDisk() {
        List<BaseDisk> disks =
                getDbFacade().getBaseDiskDao().getDisksByAlias(StorageConstants.HOSTED_ENGINE_LUN_DISK_ALIAS);
        if (disks != null && !disks.isEmpty()) {
            BaseDisk heDirectLun = disks.get(0);
            VdcReturnValueBase removeDisk = getBackend().runInternalAction(
{'fraction_non_alphanumeric': 0.08631733697364276, 'fraction_numerical': 0.00042003570303475793, 'mean_word_length': 2.919135802469136, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7666268', 'n_tokens_mistral': 5133, 'n_tokens_neox': 5054, 'n_words': 999}