Package lcmc.lvm.ui

Source Code of lcmc.lvm.ui.LVResize

/*
* This file is part of DRBD Management Console by LINBIT HA-Solutions GmbH
* written by Rasto Levrinc.
*
* Copyright (C) 2009, LINBIT HA-Solutions GmbH.
* Copyright (C) 2011-2012, Rastislav 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.lvm.ui;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SpringLayout;

import lcmc.cluster.ui.widget.WidgetFactory;
import lcmc.common.domain.AccessMode;
import lcmc.common.domain.Application;
import lcmc.cluster.domain.Cluster;
import lcmc.host.domain.Host;
import lcmc.common.domain.StringValue;
import lcmc.vm.domain.VmsXml;
import lcmc.common.domain.Value;
import lcmc.drbd.domain.BlockDevice;
import lcmc.common.ui.Browser;
import lcmc.common.ui.SpringUtilities;
import lcmc.drbd.ui.resource.BlockDevInfo;
import lcmc.drbd.ui.resource.VolumeInfo;
import lcmc.cluster.ui.widget.Widget;
import lcmc.lvm.service.LVM;
import lcmc.logger.Logger;
import lcmc.logger.LoggerFactory;
import lcmc.common.ui.utils.MyButton;
import lcmc.common.domain.util.Tools;
import lcmc.common.ui.utils.WidgetListener;

/**
* This class implements LVM resize dialog.
*/
@Named
public final class LVResize extends LV {
    private static final Logger LOG = LoggerFactory.getLogger(LVResize.class);
    private static final String DESCRIPTION =
                   "Resize the LVM volume. You can make it bigger, but not"
                   + " smaller for now. If this volume is replicated by"
                   + " DRBD, volumes on both nodes will be resized and"
                   + " drbdadm resize will be called. If you have something"
                   + " like filesystem on the DRBD, you have to resize the"
                   + " filesystem yourself.";
    private static final int RESIZE_LV_TIMEOUT = 5000;
    private BlockDevInfo blockDevInfo;
    private Widget sizeWidget;
    private Widget oldSizeWidget;
    private Widget maxSizeWidget;
    private Map<Host, JCheckBox> hostCheckBoxes = null;
    @Inject
    private Application application;
    @Inject
    private WidgetFactory widgetFactory;
    private MyButton resizeButton;

    public void init(final BlockDevInfo blockDevInfo) {
        super.init(null);
        this.blockDevInfo = blockDevInfo;
    }

    @Override
    protected String getDialogTitle() {
        return "LVM Resize";
    }

    @Override
    protected String getDescription() {
        return DESCRIPTION;
    }

    @Override
    public String cancelButton() {
        return "Close";
    }

    @Override
    protected void initDialogBeforeVisible() {
        super.initDialogBeforeVisible();
        enableComponentsLater(new JComponent[]{});
    }

    @Override
    protected void initDialogAfterVisible() {
        enableComponents();
        if (checkDRBD()) {
            makeDefaultAndRequestFocusLater(sizeWidget.getComponent());
        }
    }

    /** Check if it is DRBD device and if it could be resized. */
    private boolean checkDRBD() {
        if (blockDevInfo.getBlockDevice().isDrbd()) {
            final VolumeInfo dvi = blockDevInfo.getDrbdVolumeInfo();
            final BlockDevInfo oBDI = blockDevInfo.getOtherBlockDevInfo();
            if (!dvi.isConnected(Application.RunMode.LIVE)) {
                printErrorAndRetry("Not resizing. DRBD resource is not connected.");
                sizeWidget.setEnabled(false);
                resizeButton.setEnabled(false);
                return false;
            } else if (dvi.isSyncing()) {
                printErrorAndRetry("Not resizing. DRBD resource is syncing.");
                sizeWidget.setEnabled(false);
                resizeButton.setEnabled(false);
                return false;
            } else if (!oBDI.getBlockDevice().isAttached()) {
                printErrorAndRetry("Not resizing. DRBD resource is not attached on " + oBDI.getHost() + '.');
                sizeWidget.setEnabled(false);
                resizeButton.setEnabled(false);
                return false;
            } else if (!blockDevInfo.getBlockDevice().isAttached()) {
                printErrorAndRetry("Not resizing. DRBD resource is not attached on " + blockDevInfo.getHost() + '.');
                sizeWidget.setEnabled(false);
                resizeButton.setEnabled(false);
                return false;
            } else if (!oBDI.getBlockDevice().isPrimary() && !blockDevInfo.getBlockDevice().isPrimary()) {
                printErrorAndRetry("Not resizing. Must be primary at least on one node.");
                sizeWidget.setEnabled(false);
                resizeButton.setEnabled(false);
                return false;
            }
        }
        return true;
    }

    private void enableResizeButton(boolean enable) {
        if (enable) {
            final long oldSize = VmsXml.convertToKilobytes(oldSizeWidget.getValue());
            final long size = VmsXml.convertToKilobytes(sizeWidget.getValue());
            final String maxBlockSize = getMaxBlockSize();
            final long maxSize = Long.parseLong(maxBlockSize);
            maxSizeWidget.setValue(VmsXml.convertKilobytes(maxBlockSize));

            if (oldSize >= size || size > maxSize) {
                enable = false;
                sizeWidget.wrongValue();
            } else {
                sizeWidget.setBackground(new StringValue(), new StringValue(), true);
            }
        }
        resizeButton.setEnabled(enable);
    }

    private void setComboBoxes() {
        final String oldBlockSize = blockDevInfo.getBlockDevice().getBlockSize();
        final String maxBlockSize = getMaxBlockSize();
        oldSizeWidget.setValue(VmsXml.convertKilobytes(oldBlockSize));
        sizeWidget.setValue(VmsXml.convertKilobytes(Long.toString(
                                         (Long.parseLong(oldBlockSize) + Long.parseLong(maxBlockSize)) / 2)));
        maxSizeWidget.setValue(VmsXml.convertKilobytes(maxBlockSize));
    }

    @Override
    protected JComponent getInputPane() {
        resizeButton = widgetFactory.createButton("Resize");
        resizeButton.setEnabled(false);
        final JPanel pane = new JPanel(new SpringLayout());
        final JPanel inputPane = new JPanel(new SpringLayout());
        inputPane.setBackground(Browser.BUTTON_PANEL_BACKGROUND);
        /* old size */
        final JLabel oldSizeLabel = new JLabel("Current Size");
        oldSizeLabel.setEnabled(false);

        final String oldBlockSize = blockDevInfo.getBlockDevice().getBlockSize();
        oldSizeWidget = widgetFactory.createInstance(
                                          Widget.Type.TEXTFIELDWITHUNIT,
                                          VmsXml.convertKilobytes(oldBlockSize),
                                          Widget.NO_ITEMS,
                                          getUnits(),
                                          Widget.NO_REGEXP,
                                          250,
                                          Widget.NO_ABBRV,
                                          new AccessMode(AccessMode.OP, AccessMode.NORMAL),
                                          Widget.NO_BUTTON);
        oldSizeWidget.setEnabled(false);
        inputPane.add(oldSizeLabel);
        inputPane.add(oldSizeWidget.getComponent());
        inputPane.add(new JLabel());

        final String maxBlockSize = getMaxBlockSize();
        /* size */
        final String newBlockSize = Long.toString((Long.parseLong(oldBlockSize) + Long.parseLong(maxBlockSize)) / 2);
        final JLabel sizeLabel = new JLabel("New Size");

        sizeWidget =  widgetFactory.createInstance(
                       Widget.Type.TEXTFIELDWITHUNIT,
                       VmsXml.convertKilobytes(newBlockSize),
                       Widget.NO_ITEMS,
                       getUnits(),
                       Widget.NO_REGEXP,
                       250,
                       Widget.NO_ABBRV,
                       new AccessMode(AccessMode.OP, AccessMode.NORMAL),
                       Widget.NO_BUTTON);
        inputPane.add(sizeLabel);
        inputPane.add(sizeWidget.getComponent());
        resizeButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
                final Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        if (checkDRBD()) {
                            application.invokeAndWait(new Runnable() {
                                @Override
                                public void run() {
                                    enableResizeButton(false);
                                }
                            });
                            disableComponents();
                            getProgressBar().start(RESIZE_LV_TIMEOUT * hostCheckBoxes.size());
                            final boolean ret = lvAndDrbdResize(sizeWidget.getStringValue());
                            final Host host = blockDevInfo.getHost();
                            host.getBrowser().getClusterBrowser().updateHWInfo(host, Host.UPDATE_LVM);
                            setComboBoxes();
                            if (ret) {
                                progressBarDone();
                            } else {
                                progressBarDoneError();
                            }
                            enableComponents();
                        }
                    }
                });
                thread.start();
            }
        });

        inputPane.add(resizeButton);
        /* max size */
        final JLabel maxSizeLabel = new JLabel("Max Size");
        maxSizeLabel.setEnabled(false);
        maxSizeWidget = widgetFactory.createInstance(
                                         Widget.Type.TEXTFIELDWITHUNIT,
                                         VmsXml.convertKilobytes(maxBlockSize),
                                         Widget.NO_ITEMS,
                                         getUnits(),
                                         Widget.NO_REGEXP,
                                         250,
                                         Widget.NO_ABBRV,
                                         new AccessMode(AccessMode.OP, AccessMode.NORMAL),
                                         Widget.NO_BUTTON);
        maxSizeWidget.setEnabled(false);
        inputPane.add(maxSizeLabel);
        inputPane.add(maxSizeWidget.getComponent());
        inputPane.add(new JLabel());
        sizeWidget.addListeners(new WidgetListener() {
            @Override
            public void check(final Value value) {
                enableResizeButton(true);
            }
        });

        SpringUtilities.makeCompactGrid(inputPane, 3, 3/* rows, cols */
                                                   1, 1/* initX, initY */
                                                   1, 1); /* xPad, yPad */

        pane.add(inputPane);
        final JPanel hostsPane = new JPanel(new FlowLayout(FlowLayout.LEADING));
        final Cluster cluster = blockDevInfo.getHost().getCluster();
        hostCheckBoxes = Tools.getHostCheckBoxes(cluster);
        hostsPane.add(new JLabel("Select Hosts: "));
        final Host host = blockDevInfo.getHost();
        final String lv = blockDevInfo.getBlockDevice().getLogicalVolume();
        for (final Map.Entry<Host, JCheckBox> hostEntry : hostCheckBoxes.entrySet()) {
            final Set<String> allLVS = hostEntry.getKey().getAllLogicalVolumes();
            hostEntry.getValue().addItemListener(
                    new ItemListener() {
                        @Override
                        public void itemStateChanged(final ItemEvent e) {
                            enableResizeButton(true);
                        }
                    });
            if (host == hostEntry.getKey()
                || blockDevInfo.getBlockDevice().isDrbd()
                && blockDevInfo.getOtherBlockDevInfo().getHost() == hostEntry.getKey()) {
                hostEntry.getValue().setEnabled(false);
                hostEntry.getValue().setSelected(true);
            } else if (!blockDevInfo.getBlockDevice().isDrbd() && !allLVS.contains(lv)) {
                hostEntry.getValue().setEnabled(false);
                hostEntry.getValue().setSelected(false);
            } else {
                hostEntry.getValue().setEnabled(true);
                hostEntry.getValue().setSelected(false);
            }
            hostsPane.add(hostEntry.getValue());
        }
        final JScrollPane sp = new JScrollPane(hostsPane);
        sp.setPreferredSize(new Dimension(0, 45));
        pane.add(sp);
        pane.add(getProgressBarPane(null));
        pane.add(getAnswerPane(""));
        SpringUtilities.makeCompactGrid(pane, 4, 1/* rows, cols */
                                              0, 0/* initX, initY */
                                              0, 0); /* xPad, yPad */
        enableResizeButton(true);
        return pane;
    }

    private boolean lvAndDrbdResize(final String size) {
        final boolean ret = LVM.resize(blockDevInfo.getHost(),
                                       blockDevInfo.getBlockDevice().getName(),
                                       size,
                                       Application.RunMode.LIVE);
        if (ret) {
            answerPaneSetText("Logical volume was successfully resized on " + blockDevInfo.getHost() + '.');
            /* resize lvm volume on the other node. */
            final String lvm = blockDevInfo.getBlockDevice().getName();
            final BlockDevInfo oBDI = blockDevInfo.getOtherBlockDevInfo();
            boolean resizingFailed = false;
            for (final Map.Entry<Host, JCheckBox> hostEntry : hostCheckBoxes.entrySet()) {
                if (hostEntry.getKey() == blockDevInfo.getHost() || !hostEntry.getValue().isSelected()) {
                    continue;
                }
                for (final BlockDevice b : hostEntry.getKey().getBlockDevices()) {
                    if (lvm.equals(b.getName()) || (oBDI != null && oBDI.getBlockDevice() == b)) {
                        /* drbd or selected other host */
                        final boolean oRet = LVM.resize(hostEntry.getKey(),
                                                        b.getName(),
                                                        size,
                                                        Application.RunMode.LIVE);
                        if (oRet) {
                            answerPaneAddText("Logical volume was successfully"
                                              + " resized on "
                                              + hostEntry.getKey().getName() + '.');
                        } else {
                            answerPaneAddTextError("Resizing of "
                                                   + b.getName()
                                                   + " on host "
                                                   + hostEntry.getKey().getName()
                                                   + " failed.");
                            resizingFailed = true;
                        }
                        break;
                    }
                    if (resizingFailed) {
                        break;
                    }
                }
            }
            if (oBDI != null && !resizingFailed) {
                final boolean dRet = blockDevInfo.resizeDrbd(Application.RunMode.LIVE);
                if (dRet) {
                    answerPaneAddText("DRBD resource "
                                      + blockDevInfo.getDrbdVolumeInfo().getName()
                                      + " was successfully resized.");
                } else {
                    answerPaneAddTextError("DRBD resource "
                                           + blockDevInfo.getDrbdVolumeInfo().getName()
                                           + " resizing failed.");
                }
            }
        } else {
            answerPaneAddTextError("Resizing of "
                                   + blockDevInfo.getName()
                                   + " on host "
                                   + blockDevInfo.getHost()
                                   + " failed.");
        }
        return ret;
    }

    /** Returns maximum block size available in the group. */
    private String getMaxBlockSize() {
        final long free = blockDevInfo.getFreeInVolumeGroup() / 1024;

        String maxBlockSize = "0";
        try {
            final long taken = Long.parseLong(blockDevInfo.getBlockDevice().getBlockSize());
            final BlockDevInfo oBDI = blockDevInfo.getOtherBlockDevInfo();
            long max = free + taken;
            final String lvm = blockDevInfo.getBlockDevice().getName();
            if (hostCheckBoxes != null) {
                for (final Map.Entry<Host, JCheckBox> hostEntry : hostCheckBoxes.entrySet()) {
                    if (blockDevInfo.getHost() == hostEntry.getKey()) {
                        continue;
                    }
                    if (hostEntry.getValue().isSelected()) {
                        for (final BlockDevice b : hostEntry.getKey().getBlockDevices()) {
                            if (lvm.equals(b.getName()) || (oBDI != null && oBDI.getBlockDevice() == b)) {
                                final long oFree = hostEntry.getKey().getFreeInVolumeGroup(b.getVolumeGroup())
                                 / 1024;
                                final long oTaken = Long.parseLong(b.getBlockSize());
                                if (oFree + oTaken < max) {
                                    /* take the smaller maximum. */
                                    max = oFree + oTaken;
                                }
                            }
                        }
                    }
                }
            }
            maxBlockSize = Long.toString(max);
        } catch (final NumberFormatException e) {
            LOG.appWarning("getMaxBlockSize: could not get max size");
            /* ignore */
        }
        return maxBlockSize;
    }
}
TOP

Related Classes of lcmc.lvm.ui.LVResize

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.