Package lcmc.drbd.ui.resource

Source Code of lcmc.drbd.ui.resource.BlockDevInfo

/*
* This file is part of DRBD Management Console by LINBIT HA-Solutions GmbH
* written by Rasto Levrinc.
*
* Copyright (C) 2009-2010, LINBIT HA-Solutions GmbH.
* Copyright (C) 2009-2010, Rasto Levrinc
*
* DRBD Management Console is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* DRBD Management Console is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with drbd; see the file COPYING.  If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package lcmc.drbd.ui.resource;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Named;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import lcmc.Exceptions;
import lcmc.common.domain.AccessMode;
import lcmc.common.ui.Browser;
import lcmc.cluster.ui.ClusterBrowser;
import lcmc.common.ui.treemenu.TreeMenuController;
import lcmc.drbd.ui.DrbdGraph;
import lcmc.common.ui.GUIData;
import lcmc.host.ui.HostBrowser;
import lcmc.common.domain.Application;
import lcmc.common.domain.ColorText;
import lcmc.host.domain.Host;
import lcmc.common.domain.StringValue;
import lcmc.common.domain.Value;
import lcmc.drbd.domain.DRBDtestData;
import lcmc.drbd.domain.DrbdXml;
import lcmc.drbd.domain.BlockDevice;
import lcmc.common.ui.EditableInfo;
import lcmc.common.ui.Info;
import lcmc.cluster.ui.widget.Check;
import lcmc.cluster.ui.widget.Widget;
import lcmc.common.ui.utils.ButtonCallback;
import lcmc.common.ui.utils.ComponentWithTest;
import lcmc.drbd.service.DRBD;
import lcmc.lvm.service.LVM;
import lcmc.logger.Logger;
import lcmc.logger.LoggerFactory;
import lcmc.common.domain.util.Tools;
import lcmc.common.ui.utils.UpdatableItem;

/**
* This class holds info data for a block device.
*/
@Named
public class BlockDevInfo extends EditableInfo {
    private static final Logger LOG = LoggerFactory.getLogger(BlockDevInfo.class);
    private static final Value DRBD_MD_TYPE_FLEXIBLE = new StringValue("Flexible");
    private static final String DRBD_MD_PARAM = "DrbdMetaDisk";
    private static final String DRBD_MD_INDEX_PARAM = "DrbdMetaDiskIndex";
    public static final ImageIcon HARDDISK_ICON_LARGE = Tools.createImageIcon(
                           Tools.getDefault("BlockDevInfo.HarddiskIconLarge"));
    public static final ImageIcon HARDDISK_DRBD_ICON_LARGE =
                    Tools.createImageIcon(Tools.getDefault("BlockDevInfo.HarddiskDRBDIconLarge"));
    public static final ImageIcon NO_HARDDISK_ICON_LARGE =
                    Tools.createImageIcon(Tools.getDefault("BlockDevInfo.NoHarddiskIconLarge"));
    public static final ImageIcon HARDDISK_ICON = Tools.createImageIcon(Tools.getDefault("BlockDevInfo.HarddiskIcon"));
    private static final ColorText METADISK_COLOR_TEXT = new ColorText("meta-disk", Color.BLUE, Color.BLACK);
    private static final ColorText SWAP_COLOR_TEXT = new ColorText("swap", Color.BLUE, Color.BLACK);
    private static final ColorText MOUNTED_COLOR_TEXT = new ColorText("mounted", Color.BLUE, Color.BLACK);
    private static final ColorText PHYSICAL_VOLUME_COLOR_TEXT = new ColorText("PV", Color.BLUE, Color.GREEN);
    private static final int MAX_RIGHT_CORNER_STRING_LENGTH = 28;
    /** String that is displayed as a tool tip for disabled menu item. */
    static final String NO_DRBD_RESOURCE_STRING = "it is not a drbd resource";
    public static final String ALLOW_TWO_PRIMARIES = "allow-two-primaries";
    public static final String PROXY_UP = "Proxy Up";
    private static final String PROXY_DOWN = "Proxy Down";

    private static final String BY_UUID_PATH = "/dev/disk/by-uuid/";
    @Inject
    private GUIData guiData;
    @Inject
    private BlockDevMenu blockDevMenu;
    @Inject
    private Application application;
    @Inject
    private TreeMenuController treeMenuController;

    public void init(final String name, final BlockDevice blockDevice, final Browser browser) {
        super.init(name, browser);
        setResource(blockDevice);
    }

    /**
     * Return whether the block device is unimportant (for the GUI), e.g.
     * cdrom or swap.
     */
    private static boolean isUnimportant(final String name, final String type, final String mountedOn) {
        return "swap".equals(type)
               || "/".equals(mountedOn)
               || "/boot".equals(mountedOn)
               || name.startsWith("/dev/cdrom")
               || name.startsWith("/dev/fd")
               || name.startsWith("/dev/sr")
               || name.endsWith("/root")
               || name.endsWith("/lv_root")
               || name.endsWith("/lv_swap")
               || name.contains("/swap");
    }
    /** DRBD resource in which this block device is member. */
    private VolumeInfo volumeInfo;
    /** Map from parameters to the fact if the last entered value was
     * correct. */
    private final Map<String, Boolean> paramCorrectValueMap = new HashMap<String, Boolean>();
    /** Cache for the info panel. */
    private JComponent infoPanel = null;

    /**
     * Returns object of the other block device that is connected via drbd
     * to this block device.
     */
    public BlockDevInfo getOtherBlockDevInfo() {
        final VolumeInfo dvi = volumeInfo;
        if (dvi == null) {
            return null;
        }
        return dvi.getOtherBlockDevInfo(this);
    }

    @Override
    public HostBrowser getBrowser() {
        return (HostBrowser) super.getBrowser();
    }

    void setInfoPanel(final JComponent infoPanel) {
        this.infoPanel = infoPanel;
    }

    /**
     * Remove this block device.
     *
     * TODO: check this
     */
    @Override
    public void removeMyself(final Application.RunMode runMode) {
        getBlockDevice().setValue(DRBD_MD_PARAM, null);
        getBlockDevice().setValue(DRBD_MD_INDEX_PARAM, null);
        super.removeMyself(runMode);
        if (Application.isLive(runMode)) {
            treeMenuController.removeNode(getNode());
        }
        infoPanel = null;
    }

    public Host getHost() {
        return getBrowser().getHost();
    }

    @Override
    public ImageIcon getMenuIcon(final Application.RunMode runMode) {
        return BlockDevInfo.HARDDISK_ICON;
    }

    /** Returns info of this block device as string. */
    @Override
    public String getInfo() {
        final StringBuilder ret = new StringBuilder(120);
        ret.append("Host            : ")
           .append(getHost().getName())
           .append("\nDevice          : ")
           .append(getBlockDevice().getName())
           .append("\nMeta disk       : ")
           .append(getBlockDevice().isDrbdMetaDisk())
           .append("\nSize            : ")
           .append(getBlockDevice().getBlockSize())
           .append(" blocks");
        if (getBlockDevice().getMountedOn() == null) {
            ret.append("\nnot mounted");
        } else {
            ret.append("\nMounted on      : ")
               .append(getBlockDevice().getMountedOn())
               .append("\nType            : ")
               .append(getBlockDevice().getFsType());
            if (getUsed() >= 0) {
                ret.append("\nUsed:           : ")
                   .append(getUsed())
                   .append('%');
            }
        }
        if (getBlockDevice().isDrbd()) {
            ret.append("\nConnection state: ")
               .append(getBlockDevice().getConnectionState())
               .append("\nNode state      : ")
               .append(getBlockDevice().getNodeState())
               .append("\nDisk state      : ")
               .append(getBlockDevice().getDiskState())
               .append('\n');
        }
        return ret.toString();
    }

    /** Append hierarchy  of block devices in the string buffer using HTML. */
    private void appendBlockDeviceHierarchy(final BlockDevice bd, final StringBuilder tt, final int shift) {
        String tab = "";
        for (int i = 0; i != shift; ++i) {
            tab += "    ";
        }
        /* physical volumes */
        String vg = null;
        String selectedPV = null;
        if (bd.isVolumeGroupOnPhysicalVolume()) {
            vg = bd.getVgOnPhysicalVolume();
            selectedPV = bd.getName();
        else if (isLVM()) {
            vg = bd.getVolumeGroup();
        }
        if (vg != null) {
            for (final BlockDevice pv : getHost().getPhysicalVolumes(vg)) {
                if (pv.getName().equals(selectedPV)) {
                    tt.append("<b>").append(tab).append(pv).append("</b>");
                } else {
                    tt.append(tab).append(pv);
                }
                tt.append('\n');
            }
        }
        /* volume groups */
        if (vg != null) {
            String selectedLV = null;
            if (bd.isVolumeGroupOnPhysicalVolume()) {
                tt.append("<b>")
                  .append("    ")
                  .append(tab)
                  .append(vg)
                  .append("</b>\n");
            } else if (isLVM()) {
                tt.append("    ").append(tab).append(vg).append('\n');
                selectedLV = bd.getName();
            }
            final Set<String> lvs = getHost().getLogicalVolumesFromVolumeGroup(vg);
            if (lvs != null) {
                for (final String lv : lvs) {
                    tt.append("        ").append(tab);
                    final String lvName = "/dev/" + vg + '/' + lv;
                    if (lvName.equals(selectedLV)) {
                        if (bd.isDrbd()) {
                            tt.append(lv).append('\n');
                            final BlockDevice drbdBD = bd.getDrbdBlockDevice();
                            if (drbdBD != null) {
                                appendBlockDeviceHierarchy(drbdBD, tt, shift + 3);
                            }
                        } else {
                            tt.append("<b>").append(lv).append("</b>\n");
                        }
                    } else {
                        tt.append(lv).append('\n');
                    }
                }
            }
        } else {
            final BlockDevice drbdBD = bd.getDrbdBlockDevice();
            if (drbdBD != null) {
                tt.append(tab).append(bd.getName()).append('\n');
                appendBlockDeviceHierarchy(drbdBD, tt, shift + 1);
            } else {
                tt.append("<b>")
                  .append(tab)
                  .append(bd.getName())
                  .append("</b>\n");
            }
        }
    }

    @Override
    public String getToolTipForGraph(final Application.RunMode runMode) {
        final StringBuilder tt = new StringBuilder(60);
        final BlockDevice bd = getBlockDevice();

        tt.append("<pre>");
        appendBlockDeviceHierarchy(bd, tt, 0);
        tt.append("</pre>");
        if (bd.isDrbdMetaDisk()) {
            tt.append(" (Meta Disk)\n");
            for (final BlockDevice mb : getBlockDevice().getMetaDiskOfBlockDevices()) {
                tt.append("&nbsp;&nbsp;of ").append(mb.getName()).append('\n');
            }
        }

        final String uuid = bd.getDiskUuid();
        tt.append("\n<table>");
        if (uuid != null && uuid.startsWith(BY_UUID_PATH)) {
            tt.append("<tr><td><b>UUID:</b></td><td>")
              .append(uuid.substring(18))
              .append("</td></tr>");
        }
        String label = "ID:";
        for (final String diskId : bd.getDiskIds()) {
            if (diskId.length() > 16) {
                tt.append("<tr><td><b>")
                  .append(label)
                  .append("</b></td><td>")
                  .append(diskId.substring(16))
                  .append("</td></tr>");
                label = "";
            }
        }
        tt.append("\n</table>");

        if (bd.isDrbd()) {
            if (getHost().isDrbdStatusOk()) {
                String cs = bd.getConnectionState();
                String st = bd.getNodeState();
                String ds = bd.getDiskState();
                if (cs == null) {
                    cs = "not available";
                }
                if (st == null) {
                    st = "not available";
                }
                if (ds == null) {
                    ds = "not available";
                }

                tt.append("\n<table><tr><td><b>cs:</b></td><td>")
                  .append(cs)
                  .append("</td></tr><tr><td><b>ro:</b></td><td>")
                  .append(st)
                  .append("</td></tr><tr><td><b>ds:</b></td><td>")
                  .append(ds)
                  .append("</td></tr></table>");
            } else {
                tt.append('\n')
                  .append(Tools.getString("HostBrowser.Hb.NoInfoAvailable"));
            }
        }
        return tt.toString();
    }

    String drbdBDConfig(final String resource,
                        final String drbdDevice,
                        final boolean volumesAvailable) throws Exceptions.DrbdConfigException {
        if (drbdDevice == null) {
            throw new Exceptions.DrbdConfigException(
                                       "Drbd device not defined for host "
                                       + getHost().getName()
                                       + " (" + resource + ')');
        }
        if (getBlockDevice().getName() == null) {
            throw new Exceptions.DrbdConfigException(
                                       "Block device not defined for host "
                                       + getHost().getName()
                                       + " (" + resource + ')');
        }

        final StringBuilder config = new StringBuilder(120);
        final String tabs;
        if (volumesAvailable) {
            tabs = "\t\t\t";
        } else {
            tabs = "\t\t";
        }
        config.append(tabs)
              .append("device\t\t")
              .append(drbdDevice)
              .append(";\n")
              .append(tabs)
              .append("disk\t\t");
        final String backingDisk = getBlockDevice().getDrbdBackingDisk();
        if (backingDisk == null) {
            config.append(getBlockDevice().getName());
        } else {
            config.append(backingDisk);
        }
        config.append(";\n")
              .append(tabs)
              .append(getBlockDevice().getMetaDiskString(
                   getComboBoxValue(DRBD_MD_PARAM).getValueForConfig(),
                   getComboBoxValue(DRBD_MD_INDEX_PARAM).getValueForConfig()))
              .append(';');
        return config.toString();
    }

    /** Sets whether this block device is drbd. */
    void setDrbd(final boolean drbd) {
        getBlockDevice().setDrbd(drbd);
    }

    @Override
    protected String getSection(final String param) {
        return getBlockDevice().getSection(param);
    }

    @Override
    protected Value[] getPossibleChoices(final String param) {
        return getBlockDevice().getPossibleChoices(param);
    }

    protected Object getDefaultValue(final String param) {
        return "<select>";
    }

    @Override
    protected Widget createWidget(final String param, final String prefix, final int width) {
        final Widget paramWi;
        if (DRBD_MD_INDEX_PARAM.equals(param)) {
            paramWi = super.createWidget(param, prefix, width);
        } else {
            final Widget gwi = super.createWidget(param, prefix, width);
            paramWi = gwi;
            application.invokeLater(new Runnable() {
                @Override
                public void run() {
                    gwi.setEditable(false);
                }
            });
        }
        return paramWi;
    }

    @Override
    protected boolean checkParam(final String param, final Value newValue) {
        boolean ret = true;
        if (newValue.isNothingSelected() && isRequired(param)) {
            ret = false;
        } else if (DRBD_MD_PARAM.equals(param)) {
            if (infoPanel != null) {
                if (!getHost().getWaitForServerStatusLatch()) {
                    final boolean internal = "internal".equals(newValue.getValueForConfig());
                    final Widget ind = getWidget(DRBD_MD_INDEX_PARAM, null);
                    final Widget indW = getWidget(DRBD_MD_INDEX_PARAM,
                    Widget.WIZARD_PREFIX);
                    if (internal) {
                        ind.setValue(DRBD_MD_TYPE_FLEXIBLE);
                        if (indW != null) {
                            indW.setValue(DRBD_MD_TYPE_FLEXIBLE);
                        }
                    }
                    application.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            ind.setEnabled(!internal);
                        }
                    });
                    if (indW != null) {
                        application.invokeLater(new Runnable() {
                            @Override
                            public void run() {
                                indW.setEnabled(!internal);
                            }
                        });
                    }
                }
            }
        } else if (DRBD_MD_INDEX_PARAM.equals(param)) {
            if (getBrowser().getUsedPorts().contains(newValue.getValueForConfig())
                && !newValue.equals(getBlockDevice().getValue(param))) {
                ret = false;
            }
            final Pattern p = Pattern.compile(".*\\D.*");
            final Matcher m = p.matcher(newValue.getValueForConfig());
            if (m.matches() && !DRBD_MD_TYPE_FLEXIBLE.equals(newValue)) {
                ret = false;
            }
        }
        paramCorrectValueMap.remove(param);
        paramCorrectValueMap.put(param, ret);
        return ret;
    }

    @Override
    protected boolean isRequired(final String param) {
        return true;
    }

    @Override
    protected boolean isAdvanced(final String param) {
        return false;
    }

    @Override
    protected AccessMode.Type getAccessType(final String param) {
        return AccessMode.ADMIN;
    }

    @Override
    protected String isEnabled(final String param) {
        return null;
    }

    @Override
    protected AccessMode.Mode isEnabledOnlyInAdvancedMode(final String param) {
        return AccessMode.NORMAL;
    }

    @Override
    protected boolean isInteger(final String param) {
        return false;
    }

    @Override
    protected boolean isLabel(final String param) {
        return false;
    }

    @Override
    protected boolean isTimeType(final String param) {
        /* not required */
        return false;
    }

    @Override
    protected boolean isCheckBox(final String param) {
        return false;
    }

    @Override
    protected String getParamType(final String param) {
        return null;
    }

    @Override
    protected String getParamRegexp(final String param) {
        return null;
    }

    @Override
    protected Value[] getParamPossibleChoices(final String param) {
        if (DRBD_MD_PARAM.equals(param)) {
            /* meta disk */
            final Value internalMetaDisk =
                                    new StringValue("internal", Tools.getString("HostBrowser.MetaDisk.Internal"));
            final Value defaultMetaDiskString = internalMetaDisk;
            getBrowser().lockBlockDevInfosRead();
            final Value[] blockDevices = getAvailableBlockDevicesForMetaDisk(
            internalMetaDisk,
            getName(),
            getBrowser().getSortedBlockDevInfos());
            getBrowser().unlockBlockDevInfosRead();

            getBlockDevice().setDefaultValue(DRBD_MD_PARAM,
            defaultMetaDiskString);
            return blockDevices;
        } else if (DRBD_MD_INDEX_PARAM.equals(param)) {
            final Value dmdiValue = getBlockDevice().getValue(DRBD_MD_INDEX_PARAM);
            String defaultMetaDiskIndex;
            if (dmdiValue == null) {
                defaultMetaDiskIndex = null;
            } else {
                defaultMetaDiskIndex = dmdiValue.getValueForConfig();
            }

            if ("internal".equals(defaultMetaDiskIndex)) {
                defaultMetaDiskIndex = Tools.getString("HostBrowser.MetaDisk.Internal");
            }

            int index = 0;
            if (defaultMetaDiskIndex == null) {
                defaultMetaDiskIndex = DRBD_MD_TYPE_FLEXIBLE.getValueForConfig();
            } else if (!DRBD_MD_TYPE_FLEXIBLE.getValueForConfig().equals(defaultMetaDiskIndex)) {
                index = Integer.valueOf(defaultMetaDiskIndex) - 5;
                if (index < 0) {
                    index = 0;
                }
            }

            final Value[] indeces = new Value[11];
            indeces[0] = DRBD_MD_TYPE_FLEXIBLE;
            for (int i = 1; i < 11; i++) {
                indeces[i] = new StringValue(Integer.toString(index));
                index++;
            }

            getBlockDevice().setDefaultValue(DRBD_MD_INDEX_PARAM,
            DRBD_MD_TYPE_FLEXIBLE);
            return indeces;
        }
        return null;
    }

    @Override
    protected Value getParamDefault(final String param) {
        return getBlockDevice().getDefaultValue(param);
    }

    @Override
    protected Value getParamPreferred(final String param) {
        return getBlockDevice().getPreferredValue(param);
    }

    @Override
    protected boolean checkParamCache(final String param) {
        final Boolean cv = paramCorrectValueMap.get(param);
        if (cv == null) {
            return false;
        }
        return cv.booleanValue();
    }

    protected Value[] getAvailableBlockDevicesForMetaDisk(final Value defaultValue,
                                                          final String serviceName,
                                                          final Iterable<BlockDevInfo> blockDevInfos) {
        final List<Value> list = new ArrayList<Value>();
        final Value savedMetaDisk = getBlockDevice().getValue(DRBD_MD_PARAM);

        if (defaultValue != null) {
            list.add(defaultValue);
        }

        for (final BlockDevInfo bdi : blockDevInfos) {
            final BlockDevice bd = bdi.getBlockDevice();
            if (bdi.equals(savedMetaDisk) || (!bd.isDrbd() && !bd.isUsedByCRM() && !bd.isMounted())) {
                list.add(bdi);
            }
        }
        return list.toArray(new Value[list.size()]);
    }

    public void attach(final Application.RunMode runMode) {
        DRBD.attach(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    void detach(final Application.RunMode runMode) {
        DRBD.detach(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    void connect(final Application.RunMode runMode) {
        DRBD.connect(getHost(), volumeInfo.getDrbdResourceInfo().getName(), null, runMode);
    }

    public void disconnect(final Application.RunMode runMode) {
        DRBD.disconnect(getHost(), volumeInfo.getDrbdResourceInfo().getName(), null, runMode);
    }

    void pauseSync(final Application.RunMode runMode) {
        DRBD.pauseSync(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    void resumeSync(final Application.RunMode runMode) {
        DRBD.resumeSync(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    void drbdUp(final Application.RunMode runMode) {
        DRBD.up(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    /** Sets this drbd block device to the primary state. */
    void setPrimary(final Application.RunMode runMode) {
        DRBD.setPrimary(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    /** Sets this drbd block device to the secondary state. */
    public void setSecondary(final Application.RunMode runMode) {
        DRBD.setSecondary(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    /** Initializes drbd block device. */
    void initDrbd(final Application.RunMode runMode) {
        DRBD.initDrbd(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    /** Make filesystem. */
    public void makeFilesystem(final String filesystem, final Application.RunMode runMode) {
        DRBD.makeFilesystem(getHost(), getDrbdVolumeInfo().getDevice(), filesystem, runMode);
    }

    public boolean pvCreate(final Application.RunMode runMode) {
        final String device;
        if (getBlockDevice().isDrbd()) {
            device = volumeInfo.getDevice();
        } else {
            device = getBlockDevice().getName();
        }
        final boolean ret = LVM.pvCreate(getHost(), device, runMode);
        if (ret) {
            getBlockDevice().setVolumeGroupOnPhysicalVolume("");
        }
        return ret;
    }

    public boolean pvRemove(final Application.RunMode runMode) {
        final String device;
        if (getBlockDevice().isDrbd()) {
            device = volumeInfo.getDevice();
        } else {
            device = getBlockDevice().getName();
        }
        final boolean ret = LVM.pvRemove(getHost(), device, runMode);
        if (ret) {
            if (getBlockDevice().isDrbd()) {
                getBlockDevice().getDrbdBlockDevice().setVolumeGroupOnPhysicalVolume(null);
            } else {
                getBlockDevice().setVolumeGroupOnPhysicalVolume(null);
            }
        }
        return ret;
    }

    public boolean lvRemove(final Application.RunMode runMode) {
        final String device = getBlockDevice().getName();
        return LVM.lvRemove(getHost(), device, runMode);
    }

    public boolean lvSnapshot(final String snapshotName, final String size, final Application.RunMode runMode) {
        final String device = getBlockDevice().getName();
        return LVM.createLVSnapshot(getHost(), snapshotName, device, size, runMode);
    }

    public void skipInitialFullSync(final Application.RunMode runMode) {
        DRBD.skipInitialFullSync(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    public void forcePrimary(final Application.RunMode runMode) {
        DRBD.forcePrimary(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    void invalidateBD(final Application.RunMode runMode) {
        DRBD.invalidate(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    void discardData(final Application.RunMode runMode) {
        DRBD.discardData(getHost(), volumeInfo.getDrbdResourceInfo().getName(), null, runMode);
    }

    public void verify(final Application.RunMode runMode) {
        DRBD.verify(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    public boolean resizeDrbd(final Application.RunMode runMode) {
        return DRBD.resize(getHost(), volumeInfo.getDrbdResourceInfo().getName(), volumeInfo.getName(), runMode);
    }

    @Override
    public JPanel getGraphicalView() {
        if (getBlockDevice().isDrbd()) {
            getBrowser().getClusterBrowser().getGlobalInfo().setSelectedNode(this);
        }
        return getBrowser().getClusterBrowser().getGlobalInfo().getGraphicalView();
    }

    @Override
    protected void setTerminalPanel() {
        if (getHost() != null) {
            guiData.setTerminalPanel(getHost().getTerminalPanel());
        }
    }

    @Override
    public JComponent getInfoPanel() {
        application.isSwingThread();
        return getInfoPanelBD();
    }

    @Override
    public String[] getParametersFromXML() {
        final String[] params = {
            DRBD_MD_PARAM,
            DRBD_MD_INDEX_PARAM,
        };
        return params;
    }

    /** Apply all fields. */
    public void apply(final Application.RunMode runMode) {
        if (Application.isLive(runMode)) {
            final String[] params = getParametersFromXML();
            application.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    getApplyButton().setEnabled(false);
                    getRevertButton().setEnabled(false);
                    getInfoPanel();
                }
            });
            waitForInfoPanel();
            if (getBlockDevice().getMetaDisk() != null) {
                getBlockDevice().getMetaDisk().removeMetadiskOfBlockDevice(
                getBlockDevice());
            }
            getBlockDevice().setNew(false);
            storeComboBoxValues(params);

            final Value v = getWidget(DRBD_MD_PARAM, null).getValue();
            if (v.isNothingSelected() || "internal".equals(v.getValueForConfig())) {
                getBlockDevice().setMetaDisk(null); /* internal */
            } else {
                final BlockDevice metaDisk = ((BlockDevInfo) v).getBlockDevice();
                getBlockDevice().setMetaDisk(metaDisk);
            }
            getBrowser().getClusterBrowser().getGlobalInfo().setAllApplyButtons();
        }
    }

    /** Returns block device panel. */
    JComponent getInfoPanelBD() {
        application.isSwingThread();
        if (infoPanel != null) {
            infoPanelDone();
            return infoPanel;
        }
        final BlockDevInfo thisClass = this;
        final ButtonCallback buttonCallback = new ButtonCallback() {
            private volatile boolean mouseStillOver = false;

            @Override
            public boolean isEnabled() {
                return true;
            }

            @Override
            public void mouseOut(final ComponentWithTest component) {
                if (!isEnabled()) {
                    return;
                }
                mouseStillOver = false;
                final DrbdGraph drbdGraph = getBrowser().getDrbdGraph();
                drbdGraph.stopTestAnimation((JComponent) component);
                component.setToolTipText("");
            }

            @Override
            public void mouseOver(final ComponentWithTest component) {
                if (!isEnabled()) {
                    return;
                }
                mouseStillOver = true;
                component.setToolTipText(Tools.getString("ClusterBrowser.StartingDRBDtest"));
                component.setToolTipBackground(Tools.getDefaultColor("ClusterBrowser.Test.Tooltip.Background"));
                Tools.sleep(250);
                if (!mouseStillOver) {
                    return;
                }
                mouseStillOver = false;
                final CountDownLatch startTestLatch = new CountDownLatch(1);
                final DrbdGraph drbdGraph = getBrowser().getDrbdGraph();
                drbdGraph.startTestAnimation((JComponent) component, startTestLatch);
                getBrowser().drbdtestLockAcquire();
                thisClass.setDRBDtestData(null);
                apply(Application.RunMode.TEST);
                final Map<Host, String> testOutput = new LinkedHashMap<Host, String>();
                try {
                    getBrowser().getClusterBrowser().getGlobalInfo().createConfigDryRun(testOutput);
                    final DRBDtestData dtd = new DRBDtestData(testOutput);
                    component.setToolTipText(dtd.getToolTip());
                    thisClass.setDRBDtestData(dtd);
                } finally {
                    getBrowser().drbdtestLockRelease();
                    startTestLatch.countDown();
                }
            }
        };
        initApplyButton(buttonCallback);

        final JPanel mainPanel = new JPanel();
        mainPanel.setBackground(HostBrowser.PANEL_BACKGROUND);
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));

        final JPanel buttonPanel = new JPanel(new BorderLayout());
        buttonPanel.setBackground(HostBrowser.BUTTON_PANEL_BACKGROUND);
        buttonPanel.setMinimumSize(new Dimension(0, 50));
        buttonPanel.setPreferredSize(new Dimension(0, 50));
        buttonPanel.setMaximumSize(new Dimension(Short.MAX_VALUE, 50));

        final JPanel optionsPanel = new JPanel();
        optionsPanel.setBackground(HostBrowser.PANEL_BACKGROUND);
        optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.PAGE_AXIS));
        optionsPanel.setAlignmentX(java.awt.Component.LEFT_ALIGNMENT);

        /* Actions */
        buttonPanel.add(getActionsButton(), BorderLayout.LINE_END);
        if (getBlockDevice().isDrbd()) {
            final String[] params = getParametersFromXML();

            addParams(optionsPanel,
                      params,
                      application.getDefaultSize("HostBrowser.DrbdDevLabelWidth"),
                      application.getDefaultSize("HostBrowser.DrbdDevFieldWidth"),
                      null);

            /* apply button */
            getApplyButton().addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(final ActionEvent e) {
                    final Thread thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            application.invokeAndWait(new Runnable() {
                                @Override
                                public void run() {
                                    getApplyButton().setEnabled(false);
                                    getRevertButton().setEnabled(false);
                                }
                            });
                            getBrowser().getClusterBrowser().drbdStatusLock();
                            try {
                                getBrowser().getClusterBrowser().getGlobalInfo().createDrbdConfigLive();
                                for (final Host h : getHost().getCluster().getHostsArray()) {
                                    DRBD.adjustApply(h, DRBD.ALL_DRBD_RESOURCES, null, Application.RunMode.LIVE);
                                }
                                apply(Application.RunMode.LIVE);
                            } catch (final Exceptions.DrbdConfigException e) {
                                LOG.appError("getInfoPanelBD: config failed", e);
                            } catch (final UnknownHostException e) {
                                LOG.appError("getInfoPanelBD: config failed", e);
                            } finally {
                                getBrowser().getClusterBrowser().drbdStatusUnlock();
                            }
                        }
                    });
                    thread.start();
                }
            });
            getRevertButton().addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(final ActionEvent e) {
                        final Thread thread = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                revert();
                            }
                        });
                        thread.start();
                    }
                }
            );
            addApplyButton(buttonPanel);
            addRevertButton(buttonPanel);
        }

        /* info */
        final JPanel riaPanel = new JPanel();
        riaPanel.setBackground(HostBrowser.PANEL_BACKGROUND);
        riaPanel.setAlignmentX(java.awt.Component.LEFT_ALIGNMENT);
        riaPanel.add(super.getInfoPanel());
        mainPanel.add(riaPanel);

        mainPanel.add(optionsPanel);
        final JPanel newPanel = new JPanel();
        newPanel.setBackground(HostBrowser.PANEL_BACKGROUND);
        newPanel.setLayout(new BoxLayout(newPanel, BoxLayout.PAGE_AXIS));
        newPanel.add(buttonPanel);
        newPanel.add(new JScrollPane(mainPanel));
        infoPanel = newPanel;
        infoPanelDone();
        setApplyButtons(null, getParametersFromXML());
        return infoPanel;
    }

    /** Sets drbd resource for this block device. */
    void setDrbdVolumeInfo(final VolumeInfo volumeInfo) {
        this.volumeInfo = volumeInfo;
    }

    /** Returns drbd resource info in which this block device is member. */
    public VolumeInfo getDrbdVolumeInfo() {
        return volumeInfo;
    }

    public BlockDevice getBlockDevice() {
        return (BlockDevice) getResource();
    }

    /** Removes this block device from drbd data structures. */
    public void removeFromDrbd() {
        setDrbd(false);
        getBlockDevice().setDrbdBlockDevice(null);
        setDrbdVolumeInfo(null);
    }

    @Override
    protected String getParamShortDesc(final String param) {
        return Tools.getString(param);
    }

    @Override
    protected String getParamLongDesc(final String param) {
        return Tools.getString(param + ".Long");
    }

    public String getVGName() {
        final BlockDevice bd;
        if (getBlockDevice().isDrbd()) {
            bd = getBlockDevice().getDrbdBlockDevice();
            if (bd == null) {
                return null;
            }
        } else {
            bd = getBlockDevice();
        }
        final String vg = bd.getVolumeGroup();
        if (vg == null) {
            /* vg on pv */
            return bd.getVgOnPhysicalVolume();
        } else {
            /* lv on vg */
            return vg;
        }
    }

    @Override
    public List<UpdatableItem> createPopup() {
        return blockDevMenu.getPulldownMenu(this);
    }

    /** Returns how much of the block device is used. */
    @Override
    public int getUsed() {
        final VolumeInfo dvi = volumeInfo;
        if (dvi != null) {
            return dvi.getUsed();
        }
        return getBlockDevice().getUsed();
    }

    public String getIconTextForGraph(final Application.RunMode runMode) {
        if (!getHost().isConnected()) {
            return Tools.getString("HostBrowser.Drbd.NoInfoAvailable");
        }
        if (getBlockDevice().isDrbd()) {
            return getBlockDevice().getNodeState();
        }
        return null;
    }

    @Override
    public String getMainTextForGraph() {
        if (!isLVM()) {
            final String vg = getBlockDevice().getVgOnPhysicalVolume();
            if (vg != null && !"".equals(vg)) {
                return "VG " + vg;
            }
        }
        return getName();
    }

    public ColorText getRightCornerTextForDrbdGraph(final Application.RunMode runMode) {
        final String vg;
        if (isLVM()) {
            vg = getBlockDevice().getVolumeGroup();
        } else {
            vg = getBlockDevice().getVgOnPhysicalVolume();
        }

        if (getBlockDevice().isDrbdMetaDisk()) {
            return METADISK_COLOR_TEXT;
        } else if (getBlockDevice().isSwap()) {
            return SWAP_COLOR_TEXT;
        } else if (getBlockDevice().getMountedOn() != null) {
            return MOUNTED_COLOR_TEXT;
        } else if (getBlockDevice().isDrbd()) {
            String s = getBlockDevice().getName();
            // TODO: cache that
            if (s.length() > MAX_RIGHT_CORNER_STRING_LENGTH) {
                s = "..." + s.substring(s.length() - MAX_RIGHT_CORNER_STRING_LENGTH + 3,
                s.length());
            }
            if (getBlockDevice().isDrbdPhysicalVolume()) {
                final String drbdVG = getBlockDevice().getDrbdBlockDevice().getVgOnPhysicalVolume();
                if (drbdVG != null && !"".equals(drbdVG)) {
                    s = s + " VG:" + drbdVG;
                } else {
                    s += " PV";
                }
            }
            return new ColorText(s, Color.BLUE, Color.BLACK);
        } else if (vg != null && !"".equals(vg)) {
            if (isLVM()) {
                return new ColorText("LV in " + vg, Color.BLUE, Color.GREEN);
            } else {
                return new ColorText(getName(), Color.BLUE, Color.GREEN);
            }
        } else if (getBlockDevice().isPhysicalVolume()) {
            return PHYSICAL_VOLUME_COLOR_TEXT;
        }
        return null;
    }

    /** Returns whether this device is connected via drbd. */
    public boolean isConnected(final Application.RunMode runMode) {
        final DRBDtestData dtd = getDRBDtestData();
        if (dtd != null && Application.isTest(runMode)) {
            return isConnectedTest(dtd) && !isWFConnection(runMode);
        } else {
            return getBlockDevice().isConnected();
        }
    }

    /** Returns whether this device is connected or wait-for-c via drbd. */
    public boolean isConnectedOrWF(final Application.RunMode runMode) {
        final DRBDtestData dtd = getDRBDtestData();
        if (dtd != null && Application.isTest(runMode)) {
            return isConnectedTest(dtd);
        } else {
            return getBlockDevice().isConnectedOrWF();
        }
    }

    /** Returns whether this device is in wait-for-connection state. */
    public boolean isWFConnection(final Application.RunMode runMode) {
        final DRBDtestData dtd = getDRBDtestData();
        if (dtd != null && Application.isTest(runMode)) {
            return isConnectedOrWF(runMode) && isConnectedTest(dtd) && !getOtherBlockDevInfo().isConnectedTest(dtd);
        } else {
            return getBlockDevice().isWFConnection();
        }
    }

    /** Returns whether this device will be disconnected. */
    boolean isConnectedTest(final DRBDtestData dtd) {
        return dtd.isConnected(getHost(), volumeInfo.getDrbdResourceInfo().getName())
               || (!dtd.isDisconnected(getHost(), volumeInfo.getDrbdResourceInfo().getName())
                   && getBlockDevice().isConnectedOrWF());
    }

    public boolean isDiskless(final Application.RunMode runMode) {
        final DRBDtestData dtd = getDRBDtestData();
        final VolumeInfo dvi = volumeInfo;
        if (dtd != null && dvi != null && Application.isTest(runMode)) {
            return dtd.isDiskless(getHost(), volumeInfo.getDevice())
                   || (!dtd.isAttached(getHost(), volumeInfo.getDevice()) && getBlockDevice().isDiskless());
        } else {
            return getBlockDevice().isDiskless();
        }
    }

    DRBDtestData getDRBDtestData() {
        final ClusterBrowser b = getBrowser().getClusterBrowser();
        if (b == null) {
            return null;
        }
        return b.getDRBDtestData();
    }

    void setDRBDtestData(final DRBDtestData drbdtestData) {
        final ClusterBrowser b = getBrowser().getClusterBrowser();
        if (b == null) {
            return;
        }
        b.setDRBDtestData(drbdtestData);
    }

    /** Compares ignoring case and using drbd device names if available. */
    @Override
    public int compareTo(final Info o) {
        if (o == null) {
            return -1;
        }
        if (o == this) {
            return 0;
        }
        final String name;
        int volume = 0;
        final VolumeInfo dvi = getDrbdVolumeInfo();
        if (getBlockDevice().isDrbd() && dvi != null) {
            name = dvi.getDrbdResourceInfo().getName();
            final String v = dvi.getName();
            if (Tools.isNumber(v)) {
                volume = Integer.parseInt(v);
            }
        } else {
            name = getName();
        }
        final BlockDevInfo obdi = (BlockDevInfo) o;
        final VolumeInfo odvi = obdi.getDrbdVolumeInfo();
        final String oName;
        int oVolume = 0;
        if (obdi.getBlockDevice().isDrbd() && odvi != null) {
            oName = odvi.getDrbdResourceInfo().getName();
            final String v = odvi.getName();
            if (Tools.isNumber(v)) {
                oVolume = Integer.parseInt(v);
            }
        } else {
            oName = o.getName();
        }
        /* drbds up */
        if (getBlockDevice().isDrbd() && !obdi.getBlockDevice().isDrbd()) {
            return -1;
        }
        if (!getBlockDevice().isDrbd() && obdi.getBlockDevice().isDrbd()) {
            return 1;
        }

        /* cdroms, swap etc down */
        final boolean unimportant = isUnimportant(name, getBlockDevice().getFsType(), getBlockDevice().getMountedOn());
        final boolean oUnimportant = isUnimportant(oName,
                                                   obdi.getBlockDevice().getFsType(),
                                                   obdi.getBlockDevice().getMountedOn());
        if (unimportant && !oUnimportant) {
            return 1;
        }
        if (!unimportant && oUnimportant) {
            return -1;
        }

        /* volume groups down */
        if (getBlockDevice().isVolumeGroupOnPhysicalVolume()
            && !obdi.getBlockDevice().isVolumeGroupOnPhysicalVolume()) {
            return 1;
        }
        if (!getBlockDevice().isVolumeGroupOnPhysicalVolume()
            && obdi.getBlockDevice().isVolumeGroupOnPhysicalVolume()) {
            return -1;
        }
        final int ret = name.compareToIgnoreCase(oName);
        if (ret == 0) {
            return volume - oVolume;
        }
        return ret;
    }

    public void setParameters(final String resName) {
        application.isSwingThread();
        getBlockDevice().setNew(false);

        final ClusterBrowser clusterBrowser = getBrowser().getClusterBrowser();
        if (clusterBrowser == null) {
            return;
        }
        final VolumeInfo dvi = volumeInfo;
        if (dvi == null) {
            return;
        }
        final DrbdXml dxml = clusterBrowser.getDrbdXml();
        final String hostName = getHost().getName();
        final DrbdGraph drbdGraph = getBrowser().getDrbdGraph();
        Value value = null;
        final String volumeNr = dvi.getName();
        for (final String param : getParametersFromXML()) {
            if (DRBD_MD_PARAM.equals(param)) {
                final String metaDisk = dxml.getMetaDisk(hostName, resName, volumeNr);
                if (value == null || !"internal".equals(value.getValueForConfig())) {
                    final BlockDevInfo mdI = drbdGraph.findBlockDevInfo(hostName, metaDisk);
                    if (mdI != null) {
                        getBlockDevice().setMetaDisk(mdI.getBlockDevice());
                    }
                }
                value = new StringValue(metaDisk);
            } else if (DRBD_MD_INDEX_PARAM.equals(param)) {
                value = new StringValue(dxml.getMetaDiskIndex(hostName, resName, volumeNr));
            }
            final Value defaultValue = getParamDefault(param);
            if (value == null) {
                value = defaultValue;
            }
            final Value oldValue = getParamSaved(param);
            final Widget wi = getWidget(param, null);
            if (!Tools.areEqual(value, oldValue)) {
                getResource().setValue(param, value);
                if (wi != null) {
                    wi.setValueAndWait(value);
                }
            }
        }
    }

    /**
     * Returns whether the specified parameter or any of the parameters
     * have changed. If param is null, only param will be checked,
     * otherwise all parameters will be checked.
     */
    @Override
    public Check checkResourceFields(final String param, final String[] params) {
        return checkResourceFields(param, params, false, false, false);
    }

    /**
     * Returns whether the specified parameter or any of the parameters
     * have changed. If param is null, only param will be checked,
     * otherwise all parameters will be checked.
     */
    Check checkResourceFields(final String param,
                              final String[] params,
                              final boolean fromDrbdInfo,
                              final boolean fromDrbdResourceInfo,
                              final boolean fromDrbdVolumeInfo) {
        final VolumeInfo dvi = getDrbdVolumeInfo();
        if (dvi != null && !fromDrbdVolumeInfo && !fromDrbdResourceInfo && !fromDrbdInfo) {
            dvi.setApplyButtons(null, dvi.getParametersFromXML());
        }
        final DrbdXml dxml = getBrowser().getClusterBrowser().getDrbdXml();
        final List<String> incorrect = new ArrayList<String>();
        if (dxml != null && dxml.isDrbdDisabled()) {
            incorrect.add("drbd is disabled");
        }
        final Check check = new Check(incorrect, new ArrayList<String>());
        check.addCheck(super.checkResourceFields(param, params));
        return check;
    }

    /** Returns whether this block device is a volume group in LVM. */
    public boolean isLVM() {
        return getBlockDevice().getVolumeGroup() != null;
    }

    /** Returns how much is free space in a volume group. */
    public Long getFreeInVolumeGroup() {
        return getHost().getFreeInVolumeGroup(getBlockDevice().getVolumeGroup());
    }

    /** Returns true if this is the first volume in the resource. Returns true
     * if this is not a DRBD resource. */
    public boolean isFirstDrbdVolume() {
        if (!getBlockDevice().isDrbd()) {
            return true;
        }
        final Set<VolumeInfo> drbdVolumes = getDrbdVolumeInfo().getDrbdResourceInfo().getDrbdVolumes();
        if (drbdVolumes == null || drbdVolumes.isEmpty()) {
            return true;
        }
        return drbdVolumes.iterator().next() == getDrbdVolumeInfo();
    }

    /** Return whether two primaries are allowed. */
    boolean allowTwoPrimaries() {
        final ResourceInfo dri = volumeInfo.getDrbdResourceInfo();
        return "yes".equals(dri.getParamSaved(ALLOW_TWO_PRIMARIES).getValueForConfig());
    }

    /**
     * Proxy status for graph, null if there's no proxy configured for the
     * resource.
     */
    public String getProxyStateForGraph(final Application.RunMode runMode) {
        final VolumeInfo dvi = volumeInfo;
        if (dvi == null) {
            return null;
        }
        final ResourceInfo dri = dvi.getDrbdResourceInfo();
        final Host pHost = dri.getProxyHost(getHost(), !WIZARD);
        if (dri.isProxy(getHost())) {
            if (pHost == null) {
                return "ERROR";
            }
            if (pHost.isConnected()) {
                if (pHost.isDrbdProxyUp(dri.getName())) {
                    return PROXY_UP;
                } else {
                    return PROXY_DOWN;
                }
            } else {
                if (dvi.isConnected(runMode)) {
                    return PROXY_UP;
                } else {
                    return pHost.getName();
                }
            }
        }
        return null;
    }

    /** Whether PV can be created on this BD. */
    public boolean canCreatePV() {
        return !isLVM() && !getBlockDevice().isPhysicalVolume() && !getBlockDevice().isDrbdPhysicalVolume();
    }

    /** Whether PV can be removed from this BD. */
    boolean canRemovePV() {
        final BlockDevice bd;
        if (getBlockDevice().isDrbd()) {
            if (!getBlockDevice().isPrimary()) {
                return false;
            }
            bd = getBlockDevice().getDrbdBlockDevice();
            if (bd == null) {
                return false;
            }
        } else {
            bd = getBlockDevice();
        }
        return bd.isPhysicalVolume() && !bd.isVolumeGroupOnPhysicalVolume();
    }

    /** Whether VG can be removed. */
    boolean canRemoveVG() {
        final BlockDevice bd;
        if (getBlockDevice().isDrbd()) {
            if (!getBlockDevice().isPrimary()) {
                return false;
            }
            bd = getBlockDevice().getDrbdBlockDevice();
            if (bd == null) {
                return false;
            }
        } else {
            bd = getBlockDevice();
        }
        if (!bd.isVolumeGroupOnPhysicalVolume()) {
            return false;
        }
        final String vg = bd.getVgOnPhysicalVolume();
        return getHost().getLogicalVolumesFromVolumeGroup(vg) == null;
    }
}
TOP

Related Classes of lcmc.drbd.ui.resource.BlockDevInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.