/* * 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.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.inject.Named; import javax.swing.JComponent; import javax.swing.JPanel; import lcmc.common.domain.AccessMode; import lcmc.common.domain.Application; import lcmc.common.ui.treemenu.TreeMenuController; import lcmc.common.ui.utils.SwingUtils; import lcmc.host.domain.Host; import lcmc.common.domain.StringValue; import lcmc.vm.domain.VmsXml; import lcmc.vm.domain.data.ParallelSerialData; import lcmc.common.domain.Value; import lcmc.common.ui.Browser; import lcmc.cluster.ui.widget.Widget; import lcmc.cluster.ui.widget.WidgetFactory; import lcmc.common.ui.utils.MyButton; import lcmc.common.domain.util.Tools; import org.w3c.dom.Node; /** * This class holds info about virtual parallel or serial device. */ @Named public abstract class ParallelSerialInfo extends HardwareInfo { /** Parameters. */ private static final String[] PARAMETERS = { ParallelSerialData.TYPE, ParallelSerialData.SOURCE_PATH, ParallelSerialData.SOURCE_MODE, ParallelSerialData.TARGET_PORT, ParallelSerialData.BIND_SOURCE_HOST, ParallelSerialData.BIND_SOURCE_SERVICE, ParallelSerialData.CONNECT_SOURCE_HOST, ParallelSerialData.CONNECT_SOURCE_SERVICE, ParallelSerialData.PROTOCOL_TYPE}; /** Parameters map. */ private static final Map<String, List<String>> PARAMETERS_MAP = new HashMap<String, List<String>>(); /** Field type. */ private static final Map<String, Widget.Type> FIELD_TYPES = new HashMap<String, Widget.Type>(); /** Short name. */ private static final Map<String, String> SHORTNAME_MAP = new HashMap<String, String>(); /** Whether the parameter is required. */ private static final Collection<String> IS_REQUIRED = new HashSet<String>( Arrays.asList(new String[]{ParallelSerialData.TYPE})); /** Default name. */ private static final Map<String, Value> DEFAULTS_MAP = new HashMap<String, Value>(); /** Preferred values map. */ private static final Map<String, Value> PREFERRED_MAP = new HashMap<String, Value>(); /** Possible values. */ private static final Map<String, Value[]> POSSIBLE_VALUES = new HashMap<String, Value[]>(); static { PARAMETERS_MAP.put("dev", Arrays.asList( ParallelSerialData.TYPE, ParallelSerialData.SOURCE_PATH, ParallelSerialData.TARGET_PORT)); PARAMETERS_MAP.put("file", Arrays.asList(ParallelSerialData.TYPE, ParallelSerialData.SOURCE_PATH, ParallelSerialData.TARGET_PORT)); PARAMETERS_MAP.put("null", Arrays.asList( ParallelSerialData.TYPE, ParallelSerialData.TARGET_PORT)); PARAMETERS_MAP.put("pipe", Arrays.asList( ParallelSerialData.TYPE, ParallelSerialData.SOURCE_PATH, ParallelSerialData.TARGET_PORT)); PARAMETERS_MAP.put("pty", Arrays.asList( ParallelSerialData.TYPE, ParallelSerialData.TARGET_PORT)); PARAMETERS_MAP.put("stdio", Arrays.asList( ParallelSerialData.TYPE, ParallelSerialData.TARGET_PORT)); PARAMETERS_MAP.put("tcp", Arrays.asList( ParallelSerialData.TYPE, ParallelSerialData.SOURCE_MODE, /* one or another */ ParallelSerialData.BIND_SOURCE_HOST, ParallelSerialData.BIND_SOURCE_SERVICE, ParallelSerialData.CONNECT_SOURCE_HOST, ParallelSerialData.CONNECT_SOURCE_SERVICE, ParallelSerialData.PROTOCOL_TYPE, ParallelSerialData.TARGET_PORT)); PARAMETERS_MAP.put("udp", Arrays.asList( ParallelSerialData.TYPE, ParallelSerialData.BIND_SOURCE_HOST, ParallelSerialData.BIND_SOURCE_SERVICE, ParallelSerialData.CONNECT_SOURCE_HOST, ParallelSerialData.CONNECT_SOURCE_SERVICE, ParallelSerialData.TARGET_PORT)); PARAMETERS_MAP.put("unix", Arrays.asList( ParallelSerialData.TYPE, ParallelSerialData.SOURCE_MODE, ParallelSerialData.SOURCE_PATH, ParallelSerialData.TARGET_PORT)); PARAMETERS_MAP.put("vc", Arrays.asList(ParallelSerialData.TYPE, ParallelSerialData.TARGET_PORT)); } static { SHORTNAME_MAP.put(ParallelSerialData.TYPE, "Type"); SHORTNAME_MAP.put(ParallelSerialData.SOURCE_PATH, "Source Path"); SHORTNAME_MAP.put(ParallelSerialData.SOURCE_MODE, "Mode"); SHORTNAME_MAP.put(ParallelSerialData.BIND_SOURCE_HOST, "Server"); SHORTNAME_MAP.put(ParallelSerialData.BIND_SOURCE_SERVICE, "Server Port"); SHORTNAME_MAP.put(ParallelSerialData.CONNECT_SOURCE_HOST, "Client"); SHORTNAME_MAP.put(ParallelSerialData.CONNECT_SOURCE_SERVICE, "Client Port"); SHORTNAME_MAP.put(ParallelSerialData.PROTOCOL_TYPE, "Protocol"); SHORTNAME_MAP.put(ParallelSerialData.TARGET_PORT, "Target Port"); FIELD_TYPES.put(ParallelSerialData.PROTOCOL_TYPE, Widget.Type.RADIOGROUP); } static { POSSIBLE_VALUES.put( ParallelSerialData.TYPE, new Value[]{new StringValue("dev", "Physical Host Char Device (dev)"), new StringValue("file", "Plain File"), new StringValue( "null", "Null Device"), new StringValue("pipe", "Named Pipe"), new StringValue("pty", "PTTY"), new StringValue("stdio","Standard Input/Output"), new StringValue("tcp", "TCP Console"), new StringValue("udp", "UDP Console"), new StringValue("unix", "Unix Socket"), new StringValue("vc", "Virtual Console")}); POSSIBLE_VALUES.put( ParallelSerialData.SOURCE_MODE, new Value[]{new StringValue("bind", "Server (bind)"), new StringValue("connect", "Client (connect)")}); POSSIBLE_VALUES.put( ParallelSerialData.PROTOCOL_TYPE, new Value[]{new StringValue("telnet"), new StringValue("raw")}); DEFAULTS_MAP.put(ParallelSerialData.TARGET_PORT, new StringValue("generate")); PREFERRED_MAP.put(ParallelSerialData.BIND_SOURCE_HOST, new StringValue("127.0.0.1")); PREFERRED_MAP.put(ParallelSerialData.BIND_SOURCE_SERVICE, new StringValue("4555")); PREFERRED_MAP.put(ParallelSerialData.CONNECT_SOURCE_HOST, new StringValue("127.0.0.1")); PREFERRED_MAP.put(ParallelSerialData.CONNECT_SOURCE_SERVICE, new StringValue("4556")); PREFERRED_MAP.put(ParallelSerialData.PROTOCOL_TYPE, new StringValue("telnet")); } /** Table panel. */ private JComponent tablePanel = null; @Inject private SwingUtils swingUtils; @Inject private WidgetFactory widgetFactory; @Inject private TreeMenuController treeMenuController; void init(final String name, final Browser browser, final DomainInfo vmsVirtualDomainInfo) { super.init(name, browser, vmsVirtualDomainInfo); } /** Adds disk table with only this disk to the main panel. */ @Override protected final void addHardwareTable(final JPanel mainPanel) { tablePanel = getTablePanel(getTableScreenName(), getTableName(), getNewBtn0(getVMSVirtualDomainInfo())); if (getResource().isNew()) { swingUtils.invokeLater(new Runnable() { @Override public void run() { tablePanel.setVisible(false); } }); } mainPanel.add(tablePanel); } /** Returns long description of the specified parameter. */ @Override protected final String getParamLongDesc(final String param) { return getParamShortDesc(param); } /** Returns short description of the specified parameter. */ @Override protected final String getParamShortDesc(final String param) { final String name = SHORTNAME_MAP.get(param); if (name == null) { return param; } return name; } /** Returns preferred value for specified parameter. */ @Override protected Value getParamPreferred(final String param) { return PREFERRED_MAP.get(param); } /** Returns default value for specified parameter. */ @Override protected Value getParamDefault(final String param) { return DEFAULTS_MAP.get(param); } /** Returns parameters. */ @Override public final String[] getParametersFromXML() { return PARAMETERS.clone(); } /** Returns possible choices for drop down lists. */ @Override protected final Value[] getParamPossibleChoices(final String param) { return POSSIBLE_VALUES.get(param); } /** Returns section to which the specified parameter belongs. */ @Override protected final String getSection(final String param) { return "Display Options"; } /** Returns true if the specified parameter is required. */ @Override protected final boolean isRequired(final String param) { return IS_REQUIRED.contains(param); } /** Returns true if the specified parameter is integer. */ @Override protected final boolean isInteger(final String param) { return false; } /** Returns true if the specified parameter is label. */ @Override protected final boolean isLabel(final String param) { return false; } /** Returns true if the specified parameter is of time type. */ @Override protected final boolean isTimeType(final String param) { return false; } /** Returns whether parameter is checkbox. */ @Override protected final boolean isCheckBox(final String param) { return false; } /** Returns the type of the parameter. */ @Override protected final String getParamType(final String param) { return "undef"; // TODO: } /** Returns the regexp of the parameter. */ @Override protected final String getParamRegexp(final String param) { return null; } /** Returns type of the field. */ @Override protected final Widget.Type getFieldType(final String param) { return FIELD_TYPES.get(param); } /** Applies the changes. */ @Override final void apply(final Application.RunMode runMode) { if (Application.isTest(runMode)) { return; } swingUtils.invokeAndWait(new Runnable() { @Override public void run() { getApplyButton().setEnabled(false); getRevertButton().setEnabled(false); getInfoPanel(); } }); waitForInfoPanel(); final Map<String, String> parameters = getHWParameters(getResource().isNew()); for (final Host h : getVMSVirtualDomainInfo().getDefinedOnHosts()) { final VmsXml vmsXml = getBrowser().getVmsXml(h); if (vmsXml != null) { final Value type = getParamSaved(ParallelSerialData.TYPE); if (type == null) { parameters.put(ParallelSerialData.SAVED_TYPE, null); } else { parameters.put(ParallelSerialData.SAVED_TYPE, type.getValueForConfig()); } final String domainName = getVMSVirtualDomainInfo().getDomainName(); final Node domainNode = vmsXml.getDomainNode(domainName); modifyXML(vmsXml, domainNode, domainName, parameters); final String virshOptions = getVMSVirtualDomainInfo().getVirshOptions(); vmsXml.saveAndDefine(domainNode, domainName, virshOptions); } getResource().setNew(false); } treeMenuController.reloadNode(getNode(), false); getBrowser().periodicalVmsUpdate( getVMSVirtualDomainInfo().getDefinedOnHosts()); swingUtils.invokeLater(new Runnable() { @Override public void run() { tablePanel.setVisible(true); } }); final String[] params = getParametersFromXML(); if (Application.isLive(runMode)) { storeComboBoxValues(params); } checkResourceFields(null, params); } /** Returns device parameters. */ @Override protected Map<String, String> getHWParameters(final boolean allParams) { swingUtils.invokeAndWait(new Runnable() { @Override public void run() { getInfoPanel(); } }); final List<String> params = PARAMETERS_MAP.get( getComboBoxValue(ParallelSerialData.TYPE).getValueForConfig()); final Map<String, String> parameters = new HashMap<String, String>(); if (params == null) { return parameters; } for (final String param : params) { final Value value = getComboBoxValue(param); if (allParams || !Tools.areEqual(getParamSaved(param), value)) { if (Tools.areEqual(getParamDefault(param), value)) { parameters.put(param, null); } else { parameters.put(param, value.getValueForConfig()); } } } return parameters; } /** Returns whether this parameter is advanced. */ @Override protected final boolean isAdvanced(final String param) { return false; } /** Whether the parameter should be enabled. */ @Override protected final String isEnabled(final String param) { if (ParallelSerialData.TARGET_PORT.equals(param)) { return ""; } else if (!getResource().isNew() && ParallelSerialData.TYPE.equals(param)) { return ""; } return null; } /** Whether the parameter should be enabled only in advanced mode. */ @Override protected final AccessMode.Mode isEnabledOnlyInAdvancedMode(final String param) { return AccessMode.NORMAL; } /** Returns access type of this parameter. */ @Override protected final AccessMode.Type getAccessType(final String param) { return AccessMode.ADMIN; } /** Returns true if the value of the parameter is ok. */ @Override protected final boolean checkParam(final String param, final Value newValue) { if (ParallelSerialData.TYPE.equals(param)) { swingUtils.invokeLater(new Runnable() { @Override public void run() { for (final String thisParam : PARAMETERS) { getWidget(thisParam, null).setVisible( PARAMETERS_MAP.get(newValue.getValueForConfig()).contains(thisParam)); } } }); } return !isRequired(param) || (newValue != null && !newValue.isNothingSelected()); } /** * Returns whether this item is removeable (null), or string why it isn't. */ @Override protected final String isRemoveable() { return null; } /** Returns combo box for parameter. */ @Override protected final Widget createWidget(final String param, final String prefix, final int width) { if (ParallelSerialData.SOURCE_PATH.equals(param)) { final Value sourceFile = getParamSaved(ParallelSerialData.SOURCE_PATH); final String regexp = ".*[^/]$"; final MyButton fileChooserBtn = widgetFactory.createButton("Browse..."); final Widget paramWi = widgetFactory.createInstance( Widget.Type.TEXTFIELD, sourceFile, Widget.NO_ITEMS, regexp, width, Widget.NO_ABBRV, new AccessMode(getAccessType(param), AccessMode.NORMAL), fileChooserBtn); if (Tools.isWindows()) { /* does not work on windows and I tries, ultimatly because FilePane.usesShellFolder(fc) in BasicFileChooserUI returns true and it is not possible to descent into a directory. TODO: It may work in the future. */ paramWi.setTFButtonEnabled(false); } fileChooserBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { final Thread t = new Thread(new Runnable() { @Override public void run() { final String oldDir = paramWi.getStringValue(); final String directory; if (oldDir == null || oldDir.isEmpty()) { final String type = getComboBoxValue( ParallelSerialData.TYPE).getValueForConfig(); if ("dev".equals(type)) { directory = "/dev"; } else { directory = "/"; } } else { directory = oldDir; } startFileChooser(paramWi, directory, FILECHOOSER_FILE_ONLY); } }); t.start(); } }); widgetAdd(param, prefix, paramWi); return paramWi; } else { final Widget paramWi = super.createWidget(param, prefix, width); if (ParallelSerialData.TYPE.equals(param) || ParallelSerialData.SOURCE_MODE.equals(param)) { paramWi.setAlwaysEditable(false); } return paramWi; } } /** Returns "add new" button. */ protected abstract MyButton getNewBtn0(final DomainInfo vdi); /** Return table name that appears on the screen. */ protected abstract String getTableScreenName(); /** Return table name. */ protected abstract String getTableName(); /** Return saved value of target port. */ final String getTargetPort() { return getParamSaved(ParallelSerialData.TARGET_PORT).getValueForConfig(); } /** Returns real parameters. */ @Override String[] getRealParametersFromXML() { final Value type = getComboBoxValue(ParallelSerialData.TYPE); final String typeS; if (type == null) { typeS = null; } else { typeS = type.getValueForConfig(); } final List<String> params = PARAMETERS_MAP.get(typeS); if (params == null) { return PARAMETERS.clone(); } return params.toArray(new String[params.size()]); } }