edu.ucsb.eucalyptus.admin.client.ClusterInfoTable.java Source code

Java tutorial

Introduction

Here is the source code for edu.ucsb.eucalyptus.admin.client.ClusterInfoTable.java

Source

/*******************************************************************************
 *Copyright (c) 2009  Eucalyptus Systems, Inc.
 * 
 *  This program 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, only version 3 of the License.
 * 
 * 
 *  This file 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *  Please contact Eucalyptus Systems, Inc., 130 Castilian
 *  Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
 *  if you need additional information or have any questions.
 * 
 *  This file may incorporate work covered under the following copyright and
 *  permission notice:
 * 
 *    Software License Agreement (BSD License)
 * 
 *    Copyright (c) 2008, Regents of the University of California
 *    All rights reserved.
 * 
 *    Redistribution and use of this software in source and binary forms, with
 *    or without modification, are permitted provided that the following
 *    conditions are met:
 * 
 *      Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 * 
 *      Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * 
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 *    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
 *    THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
 *    LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
 *    SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
 *    IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
 *    BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
 *    THE REGENTS DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
 *    OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
 *    WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
 *    ANY SUCH LICENSES OR RIGHTS.
 *******************************************************************************/
package edu.ucsb.eucalyptus.admin.client;

import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;

import java.util.ArrayList;
import java.util.List;

// dmitrii TODO: remove commented out lines once the CSS-based design is confirmed

public class ClusterInfoTable extends VerticalPanel implements ClickListener {

    private static String warningMessage = "Note: adding a cluster requires synchronization of keys among all nodes, which cannot be done through this interface.  See documentation for details.";
    private static int maxClusters = 4096; //arbitrary
    private Label noClusterLabel = new Label();
    private Label statusLabel = new Label();
    private Grid grid = new Grid();
    private Button add_button = new Button("Register cluster", this);
    private HTML hint = new HTML();
    private List<ClusterInfoWeb> clusterList = new ArrayList<ClusterInfoWeb>();
    private List<StorageInfoWeb> storageList = new ArrayList<StorageInfoWeb>();
    private SystemConfigWeb systemConfig = new SystemConfigWeb();
    private String sessionId;
    private int numStorageParams;

    public ClusterInfoTable(String sessionId) {
        this.sessionId = sessionId;
        this.setStyleName("euca-config-component");
        this.setSpacing(2);
        this.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
        //      this.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
        Label clustersHeader = new Label("Clusters:");
        clustersHeader.setStyleName("euca-section-header");
        this.add(clustersHeader);
        this.noClusterLabel.setText("No clusters registered");
        this.noClusterLabel.setStyleName("euca-greeting-disabled");
        HorizontalPanel grid_and_hint = new HorizontalPanel();
        grid_and_hint.add(this.grid);
        grid_and_hint.add(this.hint);
        this.hint.setWidth("100");
        this.add(grid_and_hint);
        HorizontalPanel hpanel = new HorizontalPanel();
        hpanel.setSpacing(2);
        hpanel.add(add_button);
        hpanel.add(new Button("Save cluster configuration", new SaveCallback(this)));
        hpanel.add(this.statusLabel);
        //      this.statusLabel.setWidth ("250");
        this.statusLabel.setText("");
        this.statusLabel.setStyleName("euca-greeting-pending");
        this.add(hpanel);
        rebuildTable();
        EucalyptusWebBackend.App.getInstance().getClusterList(this.sessionId, new GetClusterListCallback(this));
        EucalyptusWebBackend.App.getInstance().getSystemConfig(this.sessionId, new GetSystemConfigCallback(this));
        EucalyptusWebBackend.App.getInstance().getStorageList(this.sessionId, new GetStorageListCallback(this));
    }

    public void onClick(final Widget widget) // Add cluster button
    {
        this.clusterList.add(new ClusterInfoWeb("cluster-name", "cc-host", 8774, 10, 4096));
        //these values are just defaults
        this.storageList.add(new StorageInfoWeb("sc-name", "sc-host", 8773, new ArrayList<String>()));
        this.rebuildTable();
        this.statusLabel.setText("Unsaved changes");
        this.statusLabel.setStyleName("euca-greeting-warning");
    }

    private void rebuildTable() {
        if (this.clusterList.isEmpty()) {
            this.grid.setVisible(false);
            this.noClusterLabel.setVisible(true);
            this.add_button.setEnabled(true);

        } else {
            this.noClusterLabel.setVisible(false);
            this.grid.clear();
            this.grid.resize(this.clusterList.size(), 1);
            this.grid.setVisible(true);
            this.grid.setStyleName("euca-table");
            this.grid.setCellPadding(2);

            int row = 0;
            for (ClusterInfoWeb cluster : this.clusterList) {
                /*// big yellow block looks kinda weird
                if ( ( row % 2 ) == 1 ) {
                   this.grid.getRowFormatter().setStyleName( row, "euca-table-even-row" );
                } else {
                   this.grid.getRowFormatter().setStyleName( row, "euca-table-odd-row" );
                }*/
                StorageInfoWeb storageInfo = this.storageList.get(row);
                this.grid.setWidget(row, 0, addClusterEntry(row++, cluster, storageInfo));
            }

            if (row >= maxClusters) {
                this.add_button.setEnabled(false);
            } else {
                this.add_button.setEnabled(true);
            }
        }
    }

    private Grid addClusterEntry(int row, ClusterInfoWeb clusterInfo, final StorageInfoWeb storageInfo) {
        final ArrayList<String> storageParams = storageInfo.getStorageParams();
        numStorageParams = storageParams.size() / 4;
        Grid g = new Grid(8 + numStorageParams, 2);
        g.setStyleName("euca-table");
        if (row > 0) {
            g.setStyleName("euca-nonfirst-cluster-entry");
        }
        g.setCellPadding(4);

        int i = 0; // row 1
        g.setWidget(i, 0, new HTML("<b>Name:</b>"));
        g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
        final HorizontalPanel namePanel = new HorizontalPanel();
        namePanel.setSpacing(0);

        if (clusterInfo.isCommitted()) {
            namePanel.add(new Label(clusterInfo.getName()));
        } else {
            final TextBox nb = new TextBox();
            nb.addChangeListener(new ChangeCallback(this, row));
            nb.setVisibleLength(12);
            nb.setText(clusterInfo.getName());
            nb.addFocusListener(new FocusHandler(this.hint, this.warningMessage));
            namePanel.add(nb);
        }
        namePanel.add(new Button("Deregister Cluster", new DeleteCallback(this, row)));
        g.setWidget(i, 1, namePanel);

        i++; // next row
        g.setWidget(i, 1, new Label("Cluster Controller"));

        i++; // next row
        g.setWidget(i, 0, new Label("Host:"));
        g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
        final TextBox hb = new TextBox();
        hb.addChangeListener(new ChangeCallback(this, row));
        hb.setVisibleLength(20);
        hb.setText(clusterInfo.getHost());
        hb.addFocusListener(new FocusHandler(this.hint, this.warningMessage));
        g.setWidget(i, 1, hb);

        i++; // next row
        /*      g.setWidget( i, 0, new Label( "Port:" ) );
              g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
              final TextBox pb = new TextBox();
              pb.addChangeListener (new ChangeCallback (this, row));
              pb.setVisibleLength( 5 );
              pb.setText( "" + clusterInfo.getPort() );
              pb.addFocusListener (new FocusHandler (this.hint, this.warningMessage));
              g.setWidget( i, 1, pb );*/

        final TextBox reservedAddressesBox = new TextBox(); // declare here, set up after the checkbox later

        final CheckBox dynamicAddressesCheckbox = new CheckBox();
        g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
        g.setWidget(i, 0, dynamicAddressesCheckbox);
        if (systemConfig.isDoDynamicPublicAddresses()) {
            dynamicAddressesCheckbox.setChecked(true);
            reservedAddressesBox.setEnabled(false);
        } else {
            dynamicAddressesCheckbox.setChecked(false);
            reservedAddressesBox.setEnabled(true);
        }
        dynamicAddressesCheckbox.addClickListener(new ClickListener() {
            public void onClick(Widget sender) {
                if (((CheckBox) sender).isChecked()) {
                    reservedAddressesBox.setEnabled(false);
                    systemConfig.setDoDynamicPublicAddresses(true);
                } else {
                    reservedAddressesBox.setEnabled(true);
                    systemConfig.setDoDynamicPublicAddresses(false);
                }
            }
        });
        g.setWidget(i, 1, new Label("Dynamic public IP address assignment"));

        i++; // next row
        g.setWidget(i, 0, new Label("Reserve for assignment"));
        g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
        reservedAddressesBox.addChangeListener(new ChangeCallback(this, row));
        reservedAddressesBox.setVisibleLength(5);
        reservedAddressesBox.setText("" + systemConfig.getSystemReservedPublicAddresses());
        final HorizontalPanel reservedAddressesPanel = new HorizontalPanel();
        reservedAddressesPanel.setSpacing(4);
        reservedAddressesPanel.add(reservedAddressesBox);
        reservedAddressesPanel.add(new HTML("public IP addresses"));
        reservedAddressesBox.setText("" + systemConfig.getSystemReservedPublicAddresses());
        g.setWidget(i, 1, reservedAddressesPanel);

        i++; // next row
        g.setWidget(i, 0, new Label("Maximum of"));
        g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
        final TextBox publicAddressesBox = new TextBox();
        publicAddressesBox.addChangeListener(new ChangeCallback(this, row));
        publicAddressesBox.setVisibleLength(5);
        publicAddressesBox.setText("" + systemConfig.getMaxUserPublicAddresses());
        final HorizontalPanel publicAddressesPanel = new HorizontalPanel();
        publicAddressesPanel.setSpacing(4);
        publicAddressesPanel.add(publicAddressesBox);
        publicAddressesPanel.add(new HTML("public IP addresses per user"));
        g.setWidget(i, 1, publicAddressesPanel);

        i++;
        g.setWidget(i, 0, new Label("Use VLAN tags"));
        g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
        final TextBox minVlanBox = new TextBox();
        minVlanBox.addChangeListener(new ChangeCallback(this, row));
        minVlanBox.setVisibleLength(4);
        minVlanBox.setText(String.valueOf(clusterInfo.getMinVlans()));
        final TextBox maxVlanBox = new TextBox();
        maxVlanBox.addChangeListener(new ChangeCallback(this, row));
        maxVlanBox.setVisibleLength(4);
        maxVlanBox.setText(String.valueOf(clusterInfo.getMaxVlans()));
        final HorizontalPanel vlanPanel = new HorizontalPanel();
        vlanPanel.setSpacing(4);
        vlanPanel.add(minVlanBox);
        vlanPanel.add(new HTML("through"));
        vlanPanel.add(maxVlanBox);
        g.setWidget(i, 1, vlanPanel);

        i++; // next row
        g.setWidget(i, 1, new Label("Storage Controller"));

        for (int paramidx = 0; paramidx < numStorageParams; ++paramidx) {
            i++; // next row
            if ("KEYVALUE".equals(storageParams.get(4 * paramidx))) {
                g.setWidget(i, 0, new Label(storageParams.get(4 * paramidx + 1) + ": "));
                g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
                final TextBox propTextBox = new TextBox();
                propTextBox.addChangeListener(new ChangeCallback(this, row));
                propTextBox.setVisibleLength(30);
                propTextBox.setText(storageParams.get(4 * paramidx + 2));
                propTextBox.addFocusListener(new FocusHandler(this.hint, this.warningMessage));
                g.setWidget(i, 1, propTextBox);
            } else if ("PASSWORD".equals(storageParams.get(4 * paramidx))) {
                g.setWidget(i, 0, new Label(storageParams.get(4 * paramidx + 1) + ": "));
                g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
                final TextBox propTextBox = new PasswordTextBox();
                propTextBox.addChangeListener(new ChangeCallback(this, row));
                propTextBox.setVisibleLength(30);
                propTextBox.setText(storageParams.get(4 * paramidx + 2));
                propTextBox.addFocusListener(new FocusHandler(this.hint, this.warningMessage));
                g.setWidget(i, 1, propTextBox);
            } else if ("BOOLEAN".equals(storageParams.get(4 * paramidx))) {

                final int index = paramidx;
                final CheckBox propCheckbox = new CheckBox();
                g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT);
                g.setWidget(i, 0, propCheckbox);
                if (Boolean.parseBoolean(storageParams.get(4 * index + 2))) {
                    propCheckbox.setChecked(true);
                } else {
                    propCheckbox.setChecked(false);
                }
                propCheckbox.addClickListener(new ClickListener() {
                    public void onClick(Widget sender) {
                        if (((CheckBox) sender).isChecked()) {
                            storageParams.set(4 * index + 2, String.valueOf(true));
                        } else {
                            storageParams.set(4 * index + 2, String.valueOf(false));
                        }
                    }
                });
                g.setWidget(i, 1, new Label(storageParams.get(paramidx * 4 + 1)));
            }
        }

        return g;
    }

    public List<ClusterInfoWeb> getClusterList() {
        return clusterList;
    }

    public void setClusterList(final List<ClusterInfoWeb> clusterList) {
        this.clusterList = clusterList;
    }

    public List<StorageInfoWeb> getStorageList() {
        return storageList;
    }

    public void setStorageList(final List<StorageInfoWeb> storageList) {
        this.storageList = storageList;
    }

    public void updateRow(int row) {
        ClusterInfoWeb cluster = this.clusterList.get(row);
        StorageInfoWeb storage = this.storageList.get(row);
        Grid g = (Grid) this.grid.getWidget(row, 0);
        HorizontalPanel p = (HorizontalPanel) g.getWidget(0, 1);
        if (p.getWidget(0) instanceof TextBox) {
            cluster.setName(((TextBox) p.getWidget(0)).getText());
            storage.setName(((TextBox) p.getWidget(0)).getText());
        } else {
            cluster.setName(((Label) p.getWidget(0)).getText());
            storage.setName(((Label) p.getWidget(0)).getText());
        }

        // CC section
        cluster.setHost(((TextBox) g.getWidget(2, 1)).getText());
        //cluster.setPort (Integer.parseInt(((TextBox)g.getWidget(3, 1)).getText()));
        p = (HorizontalPanel) g.getWidget(4, 1);
        systemConfig.setSystemReservedPublicAddresses(Integer.parseInt(((TextBox) p.getWidget(0)).getText()));
        p = (HorizontalPanel) g.getWidget(5, 1);
        systemConfig.setMaxUserPublicAddresses(Integer.parseInt(((TextBox) p.getWidget(0)).getText()));
        p = (HorizontalPanel) g.getWidget(6, 1);
        cluster.setMinVlans(Integer.parseInt(((TextBox) p.getWidget(0)).getText()));
        cluster.setMaxVlans(Integer.parseInt(((TextBox) p.getWidget(2)).getText()));
        //7 is SC label
        // SC section
        int widgetStartIndex = 8;
        ArrayList<String> storageParams = storage.getStorageParams();
        for (int i = 0; i < numStorageParams; ++i) {
            if (storageParams.get(4 * i).startsWith("KEYVALUE"))
                storageParams.set(4 * i + 2, ((TextBox) g.getWidget(widgetStartIndex + i, 1)).getText());
        }
    }

    public void MarkCommitted() {
        for (ClusterInfoWeb cluster : this.clusterList) {
            cluster.setCommitted();
        }
    }

    class ChangeCallback implements ChangeListener, ClickListener {
        private ClusterInfoTable parent;
        private int row;

        ChangeCallback(final ClusterInfoTable parent, final int row) {
            this.parent = parent;
            this.row = row;
        }

        public void onChange(Widget sender) {
            this.parent.updateRow(this.row);
            this.parent.statusLabel.setText("Unsaved changes");
            this.parent.statusLabel.setStyleName("euca-greeting-warning");
        }

        public void onClick(Widget sender) {
            this.parent.updateRow(this.row);
            this.parent.statusLabel.setText("Unsaved changes");
            this.parent.statusLabel.setStyleName("euca-greeting-warning");
        }
    }

    class DeleteCallback implements ClickListener {

        private ClusterInfoTable parent;
        private int row;

        DeleteCallback(final ClusterInfoTable parent, final int row) {
            this.parent = parent;
            this.row = row;
        }

        public void onClick(final Widget widget) {
            this.parent.clusterList.remove(this.row);
            this.parent.storageList.remove(this.row);
            this.parent.rebuildTable();
            this.parent.statusLabel.setText("Unsaved changes");
            this.parent.statusLabel.setStyleName("euca-greeting-warning");
        }
    }

    class GetClusterListCallback implements AsyncCallback {

        private ClusterInfoTable parent;

        GetClusterListCallback(final ClusterInfoTable parent) {
            this.parent = parent;
        }

        public void onFailure(final Throwable throwable) {
            this.parent.statusLabel.setText("Failed to contact server!");
            this.parent.statusLabel.setStyleName("euca-greeting-error");
        }

        public void onSuccess(final Object o) {
            List<ClusterInfoWeb> newClusterList = (List<ClusterInfoWeb>) o;
            this.parent.statusLabel.setText("Clusters up to date");
            this.parent.statusLabel.setStyleName("euca-greeting-disabled");
            this.parent.clusterList = newClusterList;
            this.parent.MarkCommitted();
            this.parent.rebuildTable();
        }
    }

    class GetStorageListCallback implements AsyncCallback {

        private ClusterInfoTable parent;

        GetStorageListCallback(final ClusterInfoTable parent) {
            this.parent = parent;
        }

        public void onFailure(final Throwable throwable) {
            this.parent.statusLabel.setText("Failed to contact server!");
            this.parent.statusLabel.setStyleName("euca-greeting-error");
        }

        public void onSuccess(final Object o) {
            List<StorageInfoWeb> newStorageList = (List<StorageInfoWeb>) o;
            this.parent.statusLabel.setText("Clusters up to date");
            this.parent.statusLabel.setStyleName("euca-greeting-disabled");
            this.parent.storageList = newStorageList;
            this.parent.MarkCommitted();
            this.parent.rebuildTable();
        }
    }

    class GetSystemConfigCallback implements AsyncCallback {

        private ClusterInfoTable parent;

        GetSystemConfigCallback(final ClusterInfoTable parent) {
            this.parent = parent;
        }

        public void onFailure(final Throwable throwable) {
            this.parent.statusLabel.setText("Failed to contact server!");
            this.parent.statusLabel.setStyleName("euca-greeting-error");
        }

        public void onSuccess(final Object o) {
            this.parent.systemConfig = (SystemConfigWeb) o;
            this.parent.rebuildTable();
        }
    }

    class SaveCallback implements AsyncCallback, ClickListener {

        private ClusterInfoTable parent;

        SaveCallback(final ClusterInfoTable parent) {
            this.parent = parent;
        }

        public void onClick(final Widget widget) {
            this.parent.statusLabel.setText("Saving...");
            this.parent.statusLabel.setStyleName("euca-greeting-pending");
            EucalyptusWebBackend.App.getInstance().setClusterList(this.parent.sessionId, this.parent.clusterList,
                    this);
            EucalyptusWebBackend.App.getInstance().setSystemConfig(this.parent.sessionId, this.parent.systemConfig,
                    this);
            EucalyptusWebBackend.App.getInstance().setStorageList(this.parent.sessionId, this.parent.storageList,
                    this);
        }

        public void onFailure(final Throwable throwable) {
            this.parent.statusLabel.setText("Failed to save!");
            this.parent.statusLabel.setStyleName("euca-greeting-error");
        }

        public void onSuccess(final Object o) {
            this.parent.statusLabel.setText("Saved clusters to server");
            this.parent.statusLabel.setStyleName("euca-greeting-disabled");
            this.parent.MarkCommitted();
            this.parent.rebuildTable(); // so the commmitted ones show up
        }
    }

    class FocusHandler implements FocusListener {
        private HTML parent;
        private String message;

        FocusHandler(final HTML parent, String message) {
            this.parent = parent;
            this.message = message;
        }

        public void onLostFocus(Widget sender) {
            this.parent.setHTML("");
            this.parent.setStyleName("euca-text");
        }

        public void onFocus(Widget sender) {
            this.parent.setHTML(message);
            this.parent.setStyleName("euca-error-hint");
        }
    }
}