Package lcmc.vm.ui.resource

Source Code of lcmc.vm.ui.resource.HardwareInfo

/*
* 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.vm.ui.resource;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.filechooser.FileSystemView;

import lcmc.common.ui.GUIData;
import lcmc.cluster.ui.widget.WidgetFactory;
import lcmc.common.domain.AccessMode;
import lcmc.common.domain.Application;
import lcmc.common.ui.treemenu.TreeMenuController;
import lcmc.host.domain.Host;
import lcmc.vm.domain.LinuxFile;
import lcmc.common.domain.StringValue;
import lcmc.vm.domain.VmsXml;
import lcmc.common.domain.Value;
import lcmc.common.domain.Resource;
import lcmc.common.ui.Browser;
import lcmc.cluster.ui.ClusterBrowser;
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.ComponentWithTest;
import lcmc.common.domain.EnablePredicate;
import lcmc.logger.Logger;
import lcmc.logger.LoggerFactory;
import lcmc.common.ui.utils.MenuAction;
import lcmc.common.ui.utils.MenuFactory;
import lcmc.common.ui.utils.MyButton;
import lcmc.common.domain.Predicate;
import lcmc.common.domain.util.Tools;
import lcmc.common.domain.Unit;
import lcmc.common.ui.utils.UpdatableItem;
import lcmc.cluster.service.ssh.ExecCommandConfig;
import lcmc.cluster.service.ssh.SshOutput;

import org.w3c.dom.Node;

/**
* This class holds info about Virtual Hardware.
*/
@Named
public abstract class HardwareInfo extends EditableInfo {
    private static final Logger LOG = LoggerFactory.getLogger(HardwareInfo.class);
    /**
     * Back to overview icon.
     */
    private static final ImageIcon BACK_ICON = Tools.createImageIcon(Tools.getDefault("BackIcon"));
    /**
     * Pattern that parses stat output.
     */
    private static final Pattern STAT_PATTERN = Pattern.compile("(.).{9}\\s+(\\d+)\\s+(\\d+)\\s+(\\d+) (.*)$");
    /**
     * Whether file chooser needs file or dir.
     */
    protected static final boolean FILECHOOSER_DIR_ONLY = true;
    protected static final boolean FILECHOOSER_FILE_ONLY = !FILECHOOSER_DIR_ONLY;
    private JComponent infoPanel = null;
    private DomainInfo vmsVirtualDomainInfo;
    private final Map<String, LinuxFile> linuxFileCache = new HashMap<String, LinuxFile>();
    @Inject
    private Application application;
    @Inject
    private MenuFactory menuFactory;
    @Inject
    private WidgetFactory widgetFactory;
    @Inject
    private GUIData guiData;
    @Inject
    private TreeMenuController treeMenuController;

    void init(final String name, final Browser browser, final DomainInfo vmsVirtualDomainInfo) {
        super.init(name, browser);
        setResource(new Resource(name));
        this.vmsVirtualDomainInfo = vmsVirtualDomainInfo;
    }

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

    @Override
    public final JComponent getInfoPanel() {
        application.isSwingThread();
        if (infoPanel != null) {
            return infoPanel;
        }
        final boolean abExisted = getApplyButton() != null;
        /* main, button and options panels */
        final JPanel mainPanel = new JPanel();
        mainPanel.setBackground(ClusterBrowser.PANEL_BACKGROUND);
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
        final JTable headerTable = getTable(DomainInfo.HEADER_TABLE);
        if (headerTable != null) {
            mainPanel.add(headerTable.getTableHeader());
            mainPanel.add(headerTable);
        }
        addHardwareTable(mainPanel);

        final JPanel buttonPanel = new JPanel(new BorderLayout());
        buttonPanel.setBackground(ClusterBrowser.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(ClusterBrowser.PANEL_BACKGROUND);
        optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.PAGE_AXIS));
        optionsPanel.setAlignmentX(java.awt.Component.LEFT_ALIGNMENT);

        final String[] params = getParametersFromXML();
        initApplyButton(null);
        /* add item listeners to the apply button. */
        if (!abExisted) {
            getApplyButton().addAction(new Runnable() {
                @Override
                public void run() {
                    final Thread thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            getBrowser().clStatusLock();
                            apply(Application.RunMode.LIVE);
                            getBrowser().clStatusUnlock();
                        }
                    });
                    thread.start();
                }
            });
            getRevertButton().addActionListener(
                    new ActionListener() {
                        @Override
                        public void actionPerformed(final ActionEvent e) {
                            final Thread thread = new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    getBrowser().clStatusLock();
                                    revert();
                                    getBrowser().clStatusUnlock();
                                }
                            });
                            thread.start();
                        }
                    }
            );
        }
        final JPanel extraButtonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 3, 0));
        extraButtonPanel.setBackground(Browser.BUTTON_PANEL_BACKGROUND);
        buttonPanel.add(extraButtonPanel);
        addApplyButton(buttonPanel);
        addRevertButton(extraButtonPanel);
        final MyButton overviewButton = widgetFactory.createButton("VM Host Overview", BACK_ICON);
        application.makeMiniButton(overviewButton);
        overviewButton.setPreferredSize(new Dimension(130, 50));
        overviewButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
                vmsVirtualDomainInfo.selectMyself();
            }
        });
        extraButtonPanel.add(overviewButton);
        addParams(optionsPanel,
                  params,
                  application.getServiceLabelWidth(),
                  application.getServiceFieldWidth() * 2,
                  null);
        /* Actions */
        buttonPanel.add(getActionsButton(), BorderLayout.LINE_END);

        mainPanel.add(optionsPanel);
        final JPanel newPanel = new JPanel();
        newPanel.setBackground(ClusterBrowser.PANEL_BACKGROUND);
        newPanel.setLayout(new BoxLayout(newPanel, BoxLayout.PAGE_AXIS));
        newPanel.add(buttonPanel);
        newPanel.add(getMoreOptionsPanel(application.getServiceLabelWidth()
                                         + application.getServiceFieldWidth() * 2 + 4));
        newPanel.add(new JScrollPane(mainPanel));
        application.invokeLater(new Runnable() {
            @Override
            public void run() {
                getApplyButton().setVisible(!getVMSVirtualDomainInfo().getResource().isNew());
                setApplyButtons(null, params);
            }
        });
        infoPanel = newPanel;
        infoPanelDone();
        return infoPanel;
    }

    @Override
    protected final Unit[] getUnits(final String param) {
        return VmsXml.getUnits();
    }

    /**
     * Returns the default unit for the parameter.
     */
    protected final String getDefaultUnit(final String param) {
        return null;
    }

    /**
     * Returns columns for the table.
     */
    @Override
    protected final String[] getColumnNames(final String tableName) {
        return vmsVirtualDomainInfo.getColumnNames(tableName);
    }

    /**
     * Execute when row in the table was clicked.
     */
    @Override
    protected final void rowClicked(final String tableName, final String key, final int column) {
        final Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                if (isControlButton(tableName, column)) {
                    vmsVirtualDomainInfo.rowClicked(tableName, key, column);
                } else {
                    vmsVirtualDomainInfo.selectMyself();
                }
            }
        });
        thread.start();
    }

    /**
     * Retrurns color for some rows.
     */
    @Override
    protected final Color getTableRowColor(final String tableName, final String key) {
        if (DomainInfo.HEADER_TABLE.equals(tableName)) {
            return vmsVirtualDomainInfo.getTableRowColor(tableName, key);
        }
        return Browser.PANEL_BACKGROUND;
    }

    @Override
    protected final int getTableColumnAlignment(final String tableName, final int column) {
        if (DomainInfo.HEADER_TABLE.equals(tableName)) {
            return vmsVirtualDomainInfo.getTableColumnAlignment(tableName, column);
        }
        return SwingConstants.LEFT;
    }

    /**
     * Returns info object for this row.
     */
    @Override
    protected final Info getTableInfo(final String tableName, final String key) {
        if (DomainInfo.HEADER_TABLE.equals(tableName)) {
            return vmsVirtualDomainInfo;
        }
        return null;
    }

    protected final DomainInfo getVMSVirtualDomainInfo() {
        return vmsVirtualDomainInfo;
    }

    /**
     * Get first host that has this vm and is connected.
     */
    protected final Host getFirstConnectedHost() {
        for (final Host h : getBrowser().getClusterHosts()) {
            final VmsXml vmsXml = getBrowser().getVmsXml(h);
            if (vmsXml != null && h.isConnected()) {
                return h;
            }
        }
        return null;
    }

    /**
     * Returns whether this item is removeable (null), or string why it isn't.
     */
    protected abstract String isRemoveable();

    /**
     * Updates parameters.
     */
    abstract void updateParameters();

    /**
     * Returns list of menu items.
     */
    @Override
    public final List<UpdatableItem> createPopup() {
        final List<UpdatableItem> items = new ArrayList<UpdatableItem>();
        /* remove service */
        final ComponentWithTest removeMenuItem = menuFactory.createMenuItem(
                Tools.getString("HardwareInfo.Menu.Remove"),
                ClusterBrowser.REMOVE_ICON,
                ClusterBrowser.STARTING_PTEST_TOOLTIP,
                Tools.getString("HardwareInfo.Menu.Cancel"),
                ClusterBrowser.REMOVE_ICON,
                ClusterBrowser.STARTING_PTEST_TOOLTIP,
                new AccessMode(AccessMode.ADMIN, AccessMode.NORMAL),
                new AccessMode(AccessMode.OP, AccessMode.NORMAL))
                .predicate(new Predicate() {
                    @Override
                    public boolean check() {
                        return !getResource().isNew();
                    }
                })
                .enablePredicate(new EnablePredicate() {
                    @Override
                    public String check() {
                        if (getResource().isNew()) {
                            return null;
                        }
                        return isRemoveable();
                    }
                })
                .addAction(new MenuAction() {
                    @Override
                    public void run(final String text) {
                        hidePopup();
                        removeMyself(Application.RunMode.LIVE);
                    }
                });
        addMouseOverListener(removeMenuItem, null);
        items.add((UpdatableItem) removeMenuItem);
        return items;
    }

    /**
     * Removes this hardware from the libvirt with confirmation dialog.
     */
    @Override
    public final void removeMyself(final Application.RunMode runMode) {
        if (getResource().isNew()) {
            super.removeMyself(runMode);
            getResource().setNew(false);
            treeMenuController.removeNode(getNode());
            return;
        }
        String desc = Tools.getString("HardwareInfo.confirmRemove.Description");

        desc = desc.replaceAll("@HW@", Matcher.quoteReplacement(toString()));
        if (application.confirmDialog(
                Tools.getString("HardwareInfo.confirmRemove.Title"),
                desc,
                Tools.getString("HardwareInfo.confirmRemove.Yes"),
                Tools.getString("HardwareInfo.confirmRemove.No"))) {
            removeMyselfNoConfirm(runMode);
            getResource().setNew(false);
        }
    }

    /**
     * Removes this disk without confirmation dialog.
     */
    protected abstract void removeMyselfNoConfirm(final Application.RunMode runMode);

    /**
     * Applies the changes.
     */
    abstract void apply(final Application.RunMode runMode);

    /**
     * Adds disk table with only this disk to the main panel.
     */
    protected abstract void addHardwareTable(final JPanel mainPanel);

    /**
     * Modify device xml.
     */
    protected abstract void modifyXML(final VmsXml vmsXml,
                                      final Node node,
                                      final String domainName,
                                      final Map<String, String> params);

    /**
     * Returns whether the column is a button, 0 column is always a button.
     */
    @Override
    protected final Map<Integer, Integer> getDefaultWidths(final String tableName) {
        return vmsVirtualDomainInfo.getDefaultWidths(tableName);
    }

    protected Map<String, String> getHWParameters(final boolean allParams) {
        application.invokeAndWait(new Runnable() {
            @Override
            public void run() {
                getInfoPanel();
            }
        });
        final Map<String, String> parameters = new HashMap<String, String>();
        for (final String param : getParametersFromXML()) {
            final Value value = getComboBoxValue(param);
            if (allParams || !getParamSaved(param).equals(value)) {
                if (Tools.areEqual(getParamDefault(param), value)) {
                    parameters.put(param, null);
                } else {
                    parameters.put(param, value.getValueForConfig());
                }
            }
        }
        return parameters;
    }

    /**
     * Returns default widths for columns. Null for computed width.
     */
    @Override
    protected final boolean isControlButton(final String tableName, final int column) {
        return vmsVirtualDomainInfo.isControlButton(tableName, column);
    }

    /**
     * Returns tool tip text in the table.
     */
    @Override
    protected final String getTableToolTip(final String tableName,
                                           final String key,
                                           final Object object,
                                           final int raw,
                                           final int column) {
        return vmsVirtualDomainInfo.getTableToolTip(tableName, key, object, raw, column);
    }

    /**
     * Returns cached file object.
     */
    public final LinuxFile getLinuxDir(final String dir, final Host host) {
        LinuxFile ret = linuxFileCache.get(dir);
        if (ret == null) {
            ret = new LinuxFile(this, host, dir, "d", 0, 0);
            linuxFileCache.put(dir, ret);
        }
        return ret;
    }

    /**
     * Returns file system view that allows remote browsing.
     */
    private FileSystemView getFileSystemView(final Host host, final String directory) {
        final HardwareInfo thisClass = this;
        return new FileSystemView() {
            @Override
            public File[] getRoots() {
                return new LinuxFile[]{getLinuxDir("/", host)};
            }

            @Override
            public boolean isRoot(final File f) {
                final String path = Tools.getUnixPath(f.toString());
                return "/".equals(path);
            }

            @Override
            public File createNewFolder(final File containingDir) {
                return null;
            }

            @Override
            public File getHomeDirectory() {
                return getLinuxDir(directory, host);
            }

            @Override
            public Boolean isTraversable(final File f) {
                final LinuxFile lf = linuxFileCache.get(f.toString());
                return lf == null || lf.isDirectory();
            }

            @Override
            public File getParentDirectory(final File dir) {
                return getLinuxDir(dir.getParent(), host);
            }

            @Override
            public File[] getFiles(final File dir, final boolean useFileHiding) {
                final StringBuilder dirSB = new StringBuilder(dir.toString());
                if ("/".equals(dir.toString())) {
                    dirSB.append('*');
                } else {
                    dirSB.append("/*");
                }
                final SshOutput out = host.captureCommandProgressIndicator(
                        "executing...",
                        new ExecCommandConfig().command("stat -c \"%A %a %Y %s %n\" " + dirSB + " 2>/dev/null")
                                .silentOutput());
                final List<LinuxFile> files = new ArrayList<LinuxFile>();
                if (out.getExitCode() == 0) {
                    for (final String line : out.getOutput().split("\r\n")) {
                        if (line.trim().isEmpty()) {
                            continue;
                        }
                        final Matcher m = STAT_PATTERN.matcher(line);
                        if (m.matches()) {
                            final String type = m.group(1);
                            final long lastModified = Long.parseLong(m.group(3)) * 1000;
                            final long size = Long.parseLong(m.group(4));
                            final String filename = m.group(5);
                            LinuxFile lf = linuxFileCache.get(filename);
                            if (lf == null) {
                                lf = new LinuxFile(thisClass, host, filename, type, lastModified, size);
                                linuxFileCache.put(filename, lf);
                            } else {
                                lf.update(type, lastModified, size);
                            }
                            files.add(lf);
                        } else {
                            LOG.appWarning("getFileSystemView: could not match: " + line);
                        }
                    }
                }
                return files.toArray(new LinuxFile[files.size()]);
            }
        };
    }

    /**
     * @param directory whether it needs dir or file
     */
    protected final void startFileChooser(final Widget paramWi,
                                          final String directory,
                                          final boolean dirOnly) {
        final Host host = getFirstConnectedHost();
        if (host == null) {
            LOG.error("startFileChooser: connection to host lost.");
            return;
        }
        final HardwareInfo thisClass = this;
        final JFileChooser fc = new JFileChooser(getLinuxDir(directory, host), getFileSystemView(host, directory)) {
            @Override
            public void setCurrentDirectory(final File dir) {
                super.setCurrentDirectory(new LinuxFile(thisClass, host, dir.toString(), "d", 0, 0));
            }
        };
        fc.setBackground(ClusterBrowser.STATUS_BACKGROUND);
        fc.setDialogType(JFileChooser.CUSTOM_DIALOG);
        if (dirOnly) {
            fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        }
        fc.setDialogTitle(Tools.getString("DiskInfo.FileChooserTitle") + host.getName());
        fc.setApproveButtonToolTipText(Tools.getString("DiskInfo.Approve.ToolTip"));
        fc.putClientProperty("FileChooser.useShellFolder", Boolean.FALSE);
        final int ret = fc.showDialog(guiData.getMainFrame(), Tools.getString("DiskInfo.Approve"));
        linuxFileCache.clear();
        if (ret == JFileChooser.APPROVE_OPTION && fc.getSelectedFile() != null) {
            final String name = fc.getSelectedFile().getAbsolutePath();
            paramWi.setValue(new StringValue(name));
        }
    }

    /**
     * Returns whether the specified parameter or any of the parameters
     * have changed. Don't check the invisible for the type parameters.
     */
    @Override
    public final Check checkResourceFields(final String param, final String[] params) {
        return checkResourceFields(param, params, false);
    }

    /**
     * Returns whether the specified parameter or any of the parameters
     * have changed. Don't check the invisible for the type parameters.
     */
    final Check checkResourceFields(final String param, final String[] params, final boolean fromDomain) {
        final DomainInfo vdi = vmsVirtualDomainInfo;
        if (!fromDomain && vdi != null && params.length != 1) {
            vdi.setApplyButtons(null, vdi.getParametersFromXML());
        }
        final String[] parameters;
        if (params == null || params.length == 1) {
            /* just one param */
            parameters = params;
        } else {
            parameters = getRealParametersFromXML();
        }
        return super.checkResourceFields(param, parameters);
    }

    protected final void checkOneParam(final String param) {
        checkResourceFields(param, new String[]{param}, true);
    }

    String[] getRealParametersFromXML() {
        return getParametersFromXML();
    }

    public final void savePreferredValues() {
        for (final String param : getParametersFromXML()) {
            final Value pv = getParamPreferred(param);
            if (pv != null) {
                getResource().setValue(param, pv);
            }
        }
    }

    @Override
    public boolean equals(final Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final HardwareInfo other = (HardwareInfo) obj;
        if (this.getName() != other.getName() && (this.getName() == null || !this.getName().equals(other.getName()))) {
            return false;
        }
        return this.vmsVirtualDomainInfo == other.vmsVirtualDomainInfo
                || (this.vmsVirtualDomainInfo != null
                && this.vmsVirtualDomainInfo.equals(
                other.vmsVirtualDomainInfo));
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 97 * hash + (this.getName() != null ? this.getName().hashCode() : 0);
        hash = 97 * hash + (this.vmsVirtualDomainInfo != null ? this.vmsVirtualDomainInfo.hashCode() : 0);
        return hash;
    }
}
TOP

Related Classes of lcmc.vm.ui.resource.HardwareInfo

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.