Package lcmc.cluster.ui.wizard

Source Code of lcmc.cluster.ui.wizard.CoroConfig

/*
* 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.cluster.ui.wizard;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
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.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SpringLayout;

import lcmc.Exceptions.IllegalVersionException;
import lcmc.common.ui.GUIData;
import lcmc.common.domain.AccessMode;
import lcmc.crm.domain.AisCastAddress;
import lcmc.common.domain.Application;
import lcmc.cluster.domain.Cluster;
import lcmc.host.domain.Host;
import lcmc.common.domain.StringValue;
import lcmc.common.domain.Value;
import lcmc.drbd.domain.NetInterface;
import lcmc.common.ui.SpringUtilities;
import lcmc.common.ui.WizardDialog;
import lcmc.cluster.ui.widget.Check;
import lcmc.cluster.ui.widget.Widget;
import lcmc.cluster.ui.widget.WidgetFactory;
import lcmc.crm.service.Corosync;
import lcmc.common.domain.ExecCallback;
import lcmc.host.domain.HostNetworks;
import lcmc.host.service.NetInterfaceService;
import lcmc.logger.Logger;
import lcmc.logger.LoggerFactory;
import lcmc.common.ui.utils.MyButton;
import lcmc.crm.service.Openais;
import lcmc.cluster.service.ssh.ExecCommandConfig;
import lcmc.cluster.service.ssh.ExecCommandThread;
import lcmc.common.domain.util.Tools;
import lcmc.common.ui.utils.WidgetListener;

/**
* An implementation of a dialog where corosync/openais is initialized on all
* hosts.
*/
@Named
final class CoroConfig extends DialogCluster {
    private static final Logger LOG = LoggerFactory.getLogger(CoroConfig.class);
    private static final Value MCAST_TYPE = new StringValue("mcast");
    private static final int ADDR_COMBOBOX_WIDTH = 100;
    private static final int PORT_COMBOBOX_WIDTH = 60;
    private static final int TYPE_COMBOBOX_WIDTH = 80;
    private static final int INTERFACE_COMBOBOX_WIDTH = 80;
    private static final int REMOVE_BUTTON_WIDTH  = 100;
    private static final int REMOVE_BUTTON_HEIGHT = 14;
    private static final String CHECKBOX_EDIT_CONFIG_STRING = Tools.getString(
                                                                    "Dialog.Cluster.CoroConfig.Checkbox.EditConfig");
    private static final String CHECKBOX_SEE_EXISTING_STRING = Tools.getString(
                                                                    "Dialog.Cluster.CoroConfig.Checkbox.SeeExisting");
    private static final String OPENAIS_CONF_READ_ERROR_STRING = "error: read error";
    private static final String NEWLINE = "\\r?\\n";
    private static final String SPACE_TAB = "        ";
    private JPanel mcastPanel;
    /** Set of mcast etc. addresses. */
    private final Collection<AisCastAddress> aisCastAddresses = new LinkedHashSet<AisCastAddress>();
    private final JLabel configStatus = new JLabel("");
    /** Connection type pulldown menu: mcast ... */
    private Widget typeWidget;
    private Widget ifaceWidget;
    private Widget addrWidget;
    private Widget portWidget;
    private MyButton addAddressButton;
    private String[] configs;
    private JPanel statusPanel;
    /** Check box that allows to edit a new config are see the existing
     * configs. */
    private JCheckBox configCheckbox;
    private final JPanel configPanel = new JPanel();
    private boolean configChangedByUser = false;
    private volatile JScrollPane configScrollPane = null;
    private volatile boolean configAlreadyScrolled = false;

    @Inject
    private InitCluster initClusterDialog;
    @Inject
    private GUIData guiData;
    @Inject
    private Application application;
    @Inject
    private WidgetFactory widgetFactory;
    private MyButton makeConfigButton;
    @Inject
    private NetInterfaceService netInterfaceService;

    public void init(final WizardDialog previousDialog, final Cluster cluster) {
        super.init(previousDialog, cluster);
        makeConfigButton = widgetFactory.createButton(Tools.getString("Dialog.Cluster.CoroConfig.CreateAisConfig"));
        final Host[] hosts = getCluster().getHostsArray();
        configs = new String[hosts.length];
        makeConfigButton.setBackgroundColor(Tools.getDefaultColor("ConfigDialog.Button"));
        makeConfigButton.addActionListener(
            new ActionListener() {
                @Override
                public void actionPerformed(final ActionEvent e) {
                    final Thread thread = new Thread(
                        new Runnable() {
                            @Override
                            public void run() {
                                application.invokeLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        makeConfigButton.setEnabled(false);
                                    }
                                });
                                disableComponents();
                                final StringBuilder config = aisConfigHead(false);
                                int ringnumber = 0;
                                for (final AisCastAddress ca : aisCastAddresses) {
                                    config.append('\n');
                                    config.append(ca.getConfigString(ringnumber, "\t"));
                                    config.append('\n');
                                    ringnumber++;
                                }
                                config.append("}\n");
                                final String serviceVersion =
                                            hosts[0].getDistString("Pacemaker.Service.Ver");
                                config.append(aisConfigPacemaker("\t", serviceVersion));
                                if (hosts[0].isCorosyncInstalled()) {
                                    Corosync.createCorosyncConfig(hosts, config);
                                } else {
                                    Openais.createAISConfig(hosts, config);
                                }
                                final boolean configOk = updateOldAisConfig();
                                if (hosts[0].isCorosyncInstalled() && !hosts[0].isOpenaisWrapper()) {
                                    Corosync.reloadCorosyncs(hosts);
                                } else {
                                    Openais.reloadOpenaises(hosts);
                                }
                                enableComponents();
                                final List<String> incorrect = new ArrayList<String>();
                                final List<String> changed = new ArrayList<String>();
                                if (configOk) {
                                    hideRetryButton();
                                } else {
                                    incorrect.add("config failed");
                                }
                                nextButtonSetEnabled(new Check(incorrect, changed));
                                if (configOk) {
                                    if (!application.getAutoClusters().isEmpty()) {
                                        Tools.sleep(1000);
                                        pressNextButton();
                                    }
                                }
                            }
                        }
                    );
                    thread.start();
                }
            });
    }

    @Override
    public WizardDialog nextDialog() {
        initClusterDialog.init(this, getCluster());
        return initClusterDialog;
    }

    @Override
    protected String getClusterDialogTitle() {
        return Tools.getString("Dialog.Cluster.CoroConfig.Title");
    }

    @Override
    protected String getDescription() {
        return Tools.getString("Dialog.Cluster.CoroConfig.Description");
    }

    @Override
    public String nextButton() {
        return Tools.getString("Dialog.Cluster.CoroConfig.NextButton");
    }

    @Override
    protected void initDialogBeforeVisible() {
        super.initDialogBeforeVisible();
        configPanel.setLayout(new BoxLayout(configPanel, BoxLayout.PAGE_AXIS));
        configPanel.setBackground(Tools.getDefaultColor("ConfigDialog.Background"));
        enableComponentsLater(new JComponent[]{buttonClass(nextButton())});
    }

    @Override
    protected void initDialogAfterVisible() {
        final Thread thread = new Thread(
            new Runnable() {
                @Override
                public void run() {
                    final boolean configOk = updateOldAisConfig();
                    application.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            makeConfigButton.setEnabled(false);
                        }
                    });
                    enableComponents();
                    final List<String> incorrect = new ArrayList<String>();
                    final List<String> changed = new ArrayList<String>();
                    if (!configOk) {
                        incorrect.add("config failed");
                    }
                    nextButtonSetEnabled(new Check(incorrect, changed));
                    if (configOk) {
                        if (!application.getAutoClusters().isEmpty()) {
                            Tools.sleep(1000);
                            pressNextButton();
                        }
                    }
                }
            });
        thread.start();
    }

    /**
     * Parses the old config and sets the new one with old and new information.
     */
    private void setNewConfig(final String oldConfig) {
        final String[] config = oldConfig.split(NEWLINE);
        /*
          interface {
                  ringnumber: 0
                  bindnetaddr: 192.168.2.0
                  mcastaddr: 226.94.1.1
                  mcastport: 5405
          }
        */
        final Pattern totemP = Pattern.compile("\\s*totem\\s*\\{\\s*");
        final Pattern interfaceP = Pattern.compile("\\s*interface\\s+\\{\\s*");
        final Pattern serviceP = Pattern.compile("\\s*service\\s*\\{\\s*");
        final Pattern endParenthesesP = Pattern.compile("^\\s*}\\s*");
        final Pattern pattern = Pattern.compile("\\s*(\\S+):\\s*(\\S+)\\s*");
        aisCastAddresses.clear();
        boolean inTotem = false;
        boolean inInterface = false;
        boolean inService = false;
        String mcastaddr = null;
        String mcastport = null;
        String bindnetaddr = null;
        for (final String line : config) {
            final Matcher totemM = totemP.matcher(line);
            final Matcher serviceM = serviceP.matcher(line);
            if (!inService && serviceM.matches()) {
                inService = true;
            } else if (!inTotem && totemM.matches()) {
                inTotem = true;
            } else if (inTotem && !inInterface) {
                final Matcher interfaceM = interfaceP.matcher(line);
                if (interfaceM.matches()) {
                    inInterface = true;
                } else {
                    final Matcher endParenthesesM = endParenthesesP.matcher(line);
                    if (endParenthesesM.matches()) {
                        inTotem = false;
                    }
                }
            } else if (inInterface) {
                final Matcher endParenthesesM = endParenthesesP.matcher(line);
                if (endParenthesesM.matches()) {
                    aisCastAddresses.add(new AisCastAddress(MCAST_TYPE.getValueForConfig(),
                                                            bindnetaddr,
                                                            mcastaddr,
                                                            mcastport));
                    inInterface = false;
                    mcastaddr = null;
                    mcastport = null;
                    bindnetaddr = null;
                } else {
                    final Matcher lineM = pattern.matcher(line);
                    if (lineM.matches()) {
                        final String name  = lineM.group(1);
                        final String value = lineM.group(2);
                        if ("mcastaddr".equals(name)) {
                            mcastaddr = value;
                        } else if ("mcastport".equals(name)) {
                            mcastport = value;
                        } else if ("bindnetaddr".equals(name)) {
                            bindnetaddr = value;
                        }
                    }
                }
            } else if (inService) {
                final Matcher endParenthesesM = endParenthesesP.matcher(line);
                if (endParenthesesM.matches()) {
                    inService = false;
                } else {
                    final Matcher lineM = pattern.matcher(line);
                    if (lineM.matches()) {
                        final String name  = lineM.group(1);
                        final String value = lineM.group(2);
                        //TODO: nothing is here, yet
                    }
                }
            }
        }
        checkInterface();
    }

    /**
     * Checks whether the old config is the same on all hosts, if it exists at
     * all and enable the components accordingly.
     * Returns whether the configs are ok and the same on all hosts.
     */
    private boolean updateOldAisConfig() { /* is run in a thread */
        final Host[] hosts = getCluster().getHostsArray();
        final ExecCommandThread[] ts = new ExecCommandThread[hosts.length];
        configStatus.setText(Tools.getString("Dialog.Cluster.CoroConfig.Loading"));

        String cf = "/etc/corosync/corosync.conf";
        String command = "Corosync.getAisConfig";
        if (!hosts[0].isCorosyncInstalled()) {
            cf = "/etc/ais/openais.conf";
            command = "OpenAIS.getAisConfig";
        }
        final String configFile = cf;
        int i = 0;
        for (final Host h : hosts) {
            final int index = i;
            ts[i] = h.execCommand(new ExecCommandConfig()
                                      .commandString(command)
                                      .execCallback(new ExecCallback() {
                                          @Override
                                          public void done(final String answer) {
                                              configs[index] = answer;
                                          }

                                          @Override
                                          public void doneError(final String answer, final int errorCode) {
                                              configs[index] = OPENAIS_CONF_READ_ERROR_STRING;
                                          }
                                      })
                                      .silentCommand()
                                      .silentOutput());
            i++;
        }
        for (final ExecCommandThread t : ts) {
            /* wait for all of them */
            try {
                t.join();
            } catch (final InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        boolean noConfigs = true;
        boolean configOk = false;
        if (configs[0].equals(OPENAIS_CONF_READ_ERROR_STRING)) {
            application.invokeLater(new Runnable() {
                @Override
                public void run() {
                    configStatus.setText(hosts[0] + Tools.getString("Dialog.Cluster.CoroConfig.NoConfigFound"));
                }
            });
            retry();
            if (!application.getAutoClusters().isEmpty()) {
                Tools.sleep(1000);
                addAddressButton.pressButton();
            }
        } else {
            noConfigs = false;
            int j;
            for (j = 1; j < configs.length; j++) {
                final Host host = hosts[j];
                if (configs[j].equals(OPENAIS_CONF_READ_ERROR_STRING)) {
                    application.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            configStatus.setText(host
                                                 + ": "
                                                 + configFile
                                                 + Tools.getString("Dialog.Cluster.CoroConfig.NoConfigFound"));
                        }
                    });
                    break;
                } else if (!configs[0].equals(configs[j])) {
                    application.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            configStatus.setText(Tools.getString("Dialog.Cluster.CoroConfig.ConfigsNotTheSame"));
                        }
                    });
                    break;
                }
            }
            if (j < configs.length) {
                retry();
            } else {
                boolean generated = false;
                final Pattern p = Pattern.compile("## generated by (drbd-gui|LCMC).*", Pattern.DOTALL);
                final Matcher m = p.matcher(configs[0]);
                if (m.matches()) {
                    generated = true;
                }
                final boolean editableConfig = generated;
                application.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        configStatus.setText(configFile + Tools.getString("Dialog.Cluster.CoroConfig.ais.conf.ok"));
                        configCheckbox.setSelected(false);
                        if (editableConfig) {
                            configCheckbox.setText(CHECKBOX_SEE_EXISTING_STRING);
                        } else {
                            configCheckbox.setText(CHECKBOX_EDIT_CONFIG_STRING);
                        }
                        statusPanel.setMaximumSize(statusPanel.getPreferredSize());
                    }
                });
                setNewConfig(configs[0]);
                if (editableConfig) {
                    updateConfigPanelEditable(false);
                } else {
                    updateConfigPanelExisting();
                }
                hideRetryButton();
                configOk = true;
            }
        }
        if (!configOk) {
            final boolean noConfigsF = noConfigs;
            application.invokeLater(new Runnable() {
                @Override
                public void run() {
                    if (noConfigsF) {
                        configCheckbox.setText(CHECKBOX_SEE_EXISTING_STRING);
                    } else {
                        configCheckbox.setText(CHECKBOX_EDIT_CONFIG_STRING);
                    }
                    configCheckbox.setSelected(false);
                    statusPanel.setMaximumSize(statusPanel.getPreferredSize());
                }
            });
            if (noConfigs) {
                updateConfigPanelEditable(false);
            } else {
                updateConfigPanelExisting();
            }
        }
        return configOk;
    }

    /** Shows all corosync or openais.conf config files. */
    private void updateConfigPanelExisting() {
        final Host[] hosts = getCluster().getHostsArray();
        application.invokeLater(new Runnable() {
            @Override
            public void run() {
                makeConfigButton.setEnabled(false);
                configPanel.removeAll();
                final JPanel insideConfigPanel = new JPanel(new SpringLayout());
                int cols = 0;
                for (int i = 0; i < hosts.length; i++) {
                    if (OPENAIS_CONF_READ_ERROR_STRING.equals(configs[i])) {
                        configs[i] = Tools.getString("Dialog.Cluster.CoroConfig.NoConfigFound");
                    }
                    final JLabel l = new JLabel(hosts[i].getName() + ':');
                    l.setBackground(Color.WHITE);
                    final JPanel labelP = new JPanel();
                    labelP.setBackground(Tools.getDefaultColor("ConfigDialog.Background"));
                    labelP.setLayout(new BoxLayout(labelP, BoxLayout.PAGE_AXIS));
                    labelP.setAlignmentX(java.awt.Component.TOP_ALIGNMENT);
                    labelP.add(l);
                    insideConfigPanel.add(labelP);
                    final JTextArea ta = new JTextArea(configs[i]);
                    ta.setEditable(false);
                    insideConfigPanel.add(ta);
                    cols += 2;
                }
                if (cols > 0) {
                    SpringUtilities.makeCompactGrid(insideConfigPanel,
                                                    1, cols,
                                                    1, 1,
                                                    1, 1);
                    configPanel.add(insideConfigPanel);
                }
                configPanel.revalidate();
                configPanel.repaint();
            }
        });
    }

    private void updateConfigPanelEditable(final boolean configChanged) {
        this.configChangedByUser = configChanged;
        final Host[] hosts = getCluster().getHostsArray();
        application.invokeLater(new Runnable() {
            @Override
            public void run() {
                if (!configChanged) {
                    makeConfigButton.setEnabled(false);
                }
                configPanel.removeAll();
                /* head */
                final String[] head = aisConfigHead(true).toString().split(NEWLINE);
                for (final String line : head) {
                    configPanel.add(new JLabel(line));
                }
                /* addresses */
                int ringnumber = 0;
                for (final AisCastAddress c : aisCastAddresses) {
                    configPanel.add(new JLabel(""));
                    final String[] interfaceLines = c.getConfigString(ringnumber, SPACE_TAB).split(NEWLINE);
                    ringnumber++;
                    boolean firstLine = true;
                    for (final String interfaceLine : interfaceLines) {
                        if (firstLine) {
                            configPanel.add(getComponentPanel(interfaceLine, getRemoveButton(c)));
                            firstLine = false;
                        } else {
                            configPanel.add(new JLabel(interfaceLine));
                        }
                    }
                }

                if (aisCastAddresses.size() < 2) {
                    final JLabel l;
                    if (aisCastAddresses.size() < 1) {
                        l = new JLabel(Tools.getString("Dialog.Cluster.CoroConfig.WarningAtLeastTwoInt"));
                    } else {
                        // TODO: we need to check if there is bond interface
                        // and one is enough
                        l = new JLabel(Tools.getString("Dialog.Cluster.CoroConfig.WarningAtLeastTwoInt.OneMore"));
                    }
                    l.setForeground(Color.RED);
                    configPanel.add(l);
                    configPanel.add(new JLabel(""));
                    l.addComponentListener(new ComponentListener() {
                        @Override
                        public void componentHidden(final ComponentEvent e) {
                            /* do nothing */
                        }

                        @Override
                        public void componentMoved(final ComponentEvent e) {
                            if (configAlreadyScrolled) {
                                return;
                            }
                            configAlreadyScrolled = true;
                            configScrollPane.getViewport().setViewPosition(l.getBounds().getLocation());
                        }

                        @Override
                        public void componentResized(final ComponentEvent e) {
                            /* do nothing */
                        }

                        @Override
                        public void componentShown(final ComponentEvent e) {
                            /* do nothing */
                        }
                    });
                }

                configPanel.add(new JLabel(""));
                /* mcast etc combo boxes */
                configPanel.add(mcastPanel);
                configPanel.add(new JLabel("}"));

                /* service pacemaker */
                final String serviceVersion = hosts[0].getDistString("Pacemaker.Service.Ver");
                final String[] pacemakerLines = aisConfigPacemaker(SPACE_TAB, serviceVersion).toString().split(NEWLINE);
                for (final String line : pacemakerLines) {
                    configPanel.add(new JLabel(line));
                }
                configPanel.revalidate();
                configPanel.repaint();
                if (configChanged) {
                    if (aisCastAddresses.isEmpty()) {
                        makeConfigButton.setEnabled(false);
                    } else {
                        guiData.setAccessible(makeConfigButton, AccessMode.ADMIN);
                    }
                    if (!application.getAutoClusters().isEmpty() && !aisCastAddresses.isEmpty()) {
                        Tools.sleep(1000);
                        makeConfigButton.pressButton();
                    }
                }
            }
        });
    }

    private MyButton getRemoveButton(final AisCastAddress c) {
        final MyButton removeButton = widgetFactory.createButton(Tools.getString("Dialog.Cluster.CoroConfig.RemoveIntButton"));
        removeButton.setBackgroundColor(Tools.getDefaultColor("ConfigDialog.Button"));
        removeButton.setMaximumSize(new Dimension(REMOVE_BUTTON_WIDTH, REMOVE_BUTTON_HEIGHT));
        removeButton.setPreferredSize(new Dimension(REMOVE_BUTTON_WIDTH, REMOVE_BUTTON_HEIGHT));
        removeButton.addActionListener(
            new ActionListener() {
                @Override
                public void actionPerformed(final ActionEvent e) {
                    final Thread t = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            aisCastAddresses.remove(c);
                            updateConfigPanelEditable(true);
                            checkInterface();
                        }
                    });
                    t.start();
                }
            });
        return removeButton;
    }

    /**
     * Checks interface if it already exists and enables/disables the 'add
     * button' accordingly.
     */
    private void checkInterface() {
        final Value type  = typeWidget.getValue();
        String address     = "";
        String bindnetaddr = "";
        String port        = "";

        if (MCAST_TYPE.equals(type)) {
            final NetInterface iface = (NetInterface) ifaceWidget.getValue();
            bindnetaddr = iface.getBindnetaddr();
            address = addrWidget.getStringValue();
            port = portWidget.getStringValue();
        }

        for (final AisCastAddress c : aisCastAddresses) {
            if (c.equals("\t", type.getValueForConfig(), bindnetaddr, address, port)) {
                application.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        addAddressButton.setEnabled(false);
                    }
                });
                return;
            }
        }
        application.invokeLater(new Runnable() {
            @Override
            public void run() {
                addAddressButton.setEnabled(true);
            }
        });
    }

    /** Plugins, not used from corosync 2.0. */
    private CharSequence plugins(final boolean fake) {
        final StringBuilder config = new StringBuilder(500);
        final String tab;
        if (fake) {
            tab = SPACE_TAB;
        } else {
            tab = "\t";
        }
        config.append("aisexec {\n");
        config.append(tab);
        config.append("user: root\n");
        config.append(tab);
        config.append("group: root\n}\n\ncorosync {\n");
        config.append(tab);
        config.append("user: root\n");
        config.append(tab);
        config.append("group: root\n}\n\namf {\n");
        config.append(tab);
        config.append("mode: disabled\n}\n\n");
        return config;
    }

    /** Returns the head of the corosync or openais config. */
    private StringBuilder aisConfigHead(final boolean fake) {
        final StringBuilder config = new StringBuilder(500);
        final String tab;
        if (fake) {
            config.append("## to be generated by LCMC ");
            tab = SPACE_TAB;
        } else {
            config.append("## generated by LCMC ");
            tab = "\t";
        }
        config.append(Tools.getRelease());
        config.append("\n\n");
        final Host[] hosts = getCluster().getHostsArray();
        boolean corosync2 = false;
        try {
           corosync2 = Tools.compareVersions(hosts[0].getCorosyncVersion(), "2") >= 0;
        } catch (final IllegalVersionException e) {
            LOG.appWarning("aisConfigHead: cannot compare corosync version: " + hosts[0].getCorosyncVersion());
        }
        if (!corosync2) {
            config.append(plugins(fake));
        }
        config.append("logging {\n");
        if (corosync2) {
            config.append(tab);
            config.append("fileline: off\n");
            config.append(tab);
            config.append("to_logfile: yes\n");
            config.append(tab);
            config.append("logfile: /var/log/cluster/corosync.log\n");

        }
        config.append(tab);
        config.append("to_stderr: no\n");
        config.append(tab);
        config.append("debug: off\n");
        config.append(tab);
        config.append("timestamp: on\n");
        config.append(tab);
        config.append("to_syslog: yes\n");
        if (corosync2) {
            config.append(tab);
            config.append("logger_subsys {\n");
            config.append(tab);
            config.append(tab);
            config.append("subsys: QUORUM\n");
            config.append(tab);
            config.append(tab);
            config.append("debug: off\n");
            config.append(tab);
            config.append("}\n");
        } else {
            config.append(tab);
            config.append("to_file: no\n");
            config.append(tab);
            config.append("syslog_facility: daemon\n");
        }
        config.append("}\n\ntotem {\n");
        config.append(tab);
        config.append("version: 2\n");
        config.append(tab);
        config.append("token: 3000\n");
        config.append(tab);
        config.append("secauth: on\n");
        if (!corosync2) {
            config.append(tab);
            config.append("token_retransmits_before_loss_const: 10\n");
            config.append(tab);
            config.append("join: 60\n");
            config.append(tab);
            config.append("consensus: 4000\n");
            config.append(tab);
            config.append("vsftype: none\n");
            config.append(tab);
            config.append("max_messages: 20\n");
            config.append(tab);
            config.append("clear_node_high_bit: yes\n");
            config.append(tab);
            config.append("threads: 0\n");
            config.append(tab);
            config.append("# nodeid: 1234\n");
        }
        config.append(tab);
        config.append("rrp_mode: active\n");
        return config;
    }


    /**
     * Returns the part of the config.
     */
    private CharSequence aisConfigPacemaker(final String tab, final String serviceVersion) {
        final StringBuilder config = new StringBuilder(120);
        final Host[] hosts = getCluster().getHostsArray();
        boolean corosync2 = false;
        try {
           corosync2 = Tools.compareVersions(hosts[0].getCorosyncVersion(), "2") >= 0;
        } catch (final IllegalVersionException e) {
            LOG.appWarning("aisConfigPacemaker: cannot compare corosync version: " + hosts[0].getCorosyncVersion());
        }
        if (corosync2) {
            config.append("\nquorum {\n");
            config.append(tab);
            config.append("provider: corosync_votequorum\n");
            config.append(tab);
            config.append("expected_votes: ");
            config.append(hosts.length);
            config.append("\n}\n");
        } else {
            config.append("\nservice {\n");
            config.append(tab);
            config.append("ver: ");
            config.append(serviceVersion);
            config.append('\n');
            config.append(tab);
            config.append("name: pacemaker\n");
            config.append(tab);
            config.append("use_mgmtd: no\n");
            config.append("}\n");
        }
        return config;
    }

    /** Adds interface to the config panel. It must be called from a thread. */
    private void addInterface(final Value type) {
        String bindnetaddr = "";
        String addr        = "";
        String port        = "";
        if (MCAST_TYPE.equals(type)) {
            final NetInterface iface  = (NetInterface) ifaceWidget.getValue();
            if (iface == null) {
                LOG.appWarning("addInterface: cannot add null interface");
                return;
            }
            bindnetaddr = iface.getBindnetaddr();
            addr = addrWidget.getStringValue();
            port = portWidget.getStringValue();
        }
        aisCastAddresses.add(new AisCastAddress(type.getValueForConfig(), bindnetaddr, addr, port));
        updateConfigPanelEditable(true);
        checkInterface();
    }

    @Override
    protected JComponent getInputPane() {
        final JPanel pane = new JPanel();
        pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS));
        final Host[] hosts = getCluster().getHostsArray();
        final Value[] types = {MCAST_TYPE};

        typeWidget = widgetFactory.createInstance(Widget.GUESS_TYPE,
                                                  MCAST_TYPE,
                                                  types,
                                                  Widget.NO_REGEXP,
                                                  TYPE_COMBOBOX_WIDTH,
                                                  Widget.NO_ABBRV,
                                                  new AccessMode(AccessMode.RO, AccessMode.NORMAL),
                                                  Widget.NO_BUTTON);
        typeWidget.setEnabled(false);

        final NetInterface[] ni = netInterfaceService.getNetInterfacesWithBridges(hosts[0]);
        NetInterface defaultNi = null;
        for (final NetInterface n : ni) {
            /* skip lo */
            if (!n.isLocalHost()) {
                defaultNi = n;
                break;
            }
        }
        if (defaultNi == null) {
            LOG.appError("getInputPane: " + hosts[0].getName() + ": missing network interfaces");
        }
        ifaceWidget = widgetFactory.createInstance(
                                          Widget.Type.COMBOBOX,
                                          defaultNi,
                                          ni,
                                          Widget.NO_REGEXP,
                                          INTERFACE_COMBOBOX_WIDTH,
                                          Widget.NO_ABBRV,
                                          new AccessMode(AccessMode.RO, AccessMode.NORMAL),
                                          Widget.NO_BUTTON);

        /* this matches something like this: 225.0.0.43 694 1 0
         * if you think that the regexp is too complicated for that, consider,
         * that it must match also during the thing is written.
         */
        final String regexp = "^[\\d.]+$";
        addrWidget = widgetFactory.createInstance(
                              Widget.GUESS_TYPE,
                              new StringValue(Tools.getDefault("Dialog.Cluster.CoroConfig.DefaultMCastAddress")),
                              Widget.NO_ITEMS,
                              regexp,
                              ADDR_COMBOBOX_WIDTH,
                              Widget.NO_ABBRV,
                              new AccessMode(AccessMode.RO, AccessMode.NORMAL),
                              Widget.NO_BUTTON);

        typeWidget.addListeners(new WidgetListener() {
            @Override
            public void check(final Value value) {
                checkInterface();
            }
        });

        ifaceWidget.addListeners(new WidgetListener() {
            @Override
            public void check(final Value value) {
                checkInterface();
            }
        });

        final String portRegexp = "^\\d+$";
        portWidget = widgetFactory.createInstance(
                Widget.GUESS_TYPE,
                new StringValue(Tools.getDefault("Dialog.Cluster.CoroConfig.DefaultMCastPort")),
                Widget.NO_ITEMS,
                portRegexp,
                PORT_COMBOBOX_WIDTH,
                Widget.NO_ABBRV,
                new AccessMode(AccessMode.RO, AccessMode.NORMAL),
                Widget.NO_BUTTON);
        portWidget.addListeners(new WidgetListener() {
            @Override
            public void check(final Value value) {
                checkInterface();
            }
        });

        addrWidget.addListeners(new WidgetListener() {
            @Override
            public void check(final Value value) {
                checkInterface();
            }
        });

        addAddressButton = widgetFactory.createButton(Tools.getString("Dialog.Cluster.CoroConfig.AddIntButton"));
        addAddressButton.setBackgroundColor(Tools.getDefaultColor("ConfigDialog.Button"));
        addAddressButton.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(final ActionEvent e) {
                        final Value type = typeWidget.getValue();
                        final Thread thread = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                addInterface(type);
                            }
                        });
                        thread.start();
                    }
                });

        configScrollPane = new JScrollPane(configPanel,
                                           JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                                           JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        configScrollPane.setPreferredSize(new Dimension(Short.MAX_VALUE, 150));
        statusPanel = new JPanel();
        statusPanel.add(configStatus);
        configCheckbox = new JCheckBox("-----", true);
        configCheckbox.setBackground(Tools.getDefaultColor("ConfigDialog.Background.Light"));

        guiData.setAccessible(configCheckbox, AccessMode.ADMIN);
        configCheckbox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(final ItemEvent e) {
                final String text = configCheckbox.getText();
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    final Thread thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            if (CHECKBOX_EDIT_CONFIG_STRING.equals(text)) {
                                updateConfigPanelEditable(configChangedByUser);
                                application.invokeLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        configCheckbox.setText(CHECKBOX_SEE_EXISTING_STRING);
                                        configCheckbox.setSelected(false);
                                        statusPanel.setMaximumSize(statusPanel.getPreferredSize());
                                    }
                                });
                            } else if (CHECKBOX_SEE_EXISTING_STRING.equals(text)) {
                                updateConfigPanelExisting();
                                application.invokeLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        configCheckbox.setText(CHECKBOX_EDIT_CONFIG_STRING);
                                        configCheckbox.setSelected(false);
                                        statusPanel.setMaximumSize(statusPanel.getPreferredSize());
                                    }
                                });
                            }
                        }
                    });
                    thread.start();
                }
            }
        });
        statusPanel.add(configCheckbox);
        statusPanel.setAlignmentX(java.awt.Component.LEFT_ALIGNMENT);
        pane.add(statusPanel);
        pane.add(configScrollPane);
        configScrollPane.setAlignmentX(java.awt.Component.LEFT_ALIGNMENT);
        mcastPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        mcastPanel.setBackground(Tools.getDefaultColor("ConfigDialog.Background"));
        mcastPanel.add(new JLabel("# "));
        mcastPanel.add(typeWidget.getComponent());
        mcastPanel.add(ifaceWidget.getComponent());
        mcastPanel.add(addrWidget.getComponent());
        mcastPanel.add(portWidget.getComponent());
        mcastPanel.add(addAddressButton);
        mcastPanel.setPreferredSize(mcastPanel.getMinimumSize());
        mcastPanel.setAlignmentX(java.awt.Component.LEFT_ALIGNMENT);
        pane.add(makeConfigButton);
        return pane;
    }

    @Override
    protected boolean skipButtonEnabled() {
        return true;
    }
}
TOP

Related Classes of lcmc.cluster.ui.wizard.CoroConfig

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.