org.ow2.sirocco.cloudmanager.MachineCreationWizard.java Source code

Java tutorial

Introduction

Here is the source code for org.ow2.sirocco.cloudmanager.MachineCreationWizard.java

Source

/**
 *
 * SIROCCO
 * Copyright (C) 2013 France Telecom
 * Contact: sirocco@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 */
package org.ow2.sirocco.cloudmanager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;

import org.ow2.sirocco.cloudmanager.MachineView.MachineBean;
import org.ow2.sirocco.cloudmanager.core.api.ICloudProviderManager;
import org.ow2.sirocco.cloudmanager.core.api.ICredentialsManager;
import org.ow2.sirocco.cloudmanager.core.api.IMachineImageManager;
import org.ow2.sirocco.cloudmanager.core.api.IMachineManager;
import org.ow2.sirocco.cloudmanager.core.api.INetworkManager;
import org.ow2.sirocco.cloudmanager.core.api.exception.CloudProviderException;
import org.ow2.sirocco.cloudmanager.model.cimi.Credentials;
import org.ow2.sirocco.cloudmanager.model.cimi.Job;
import org.ow2.sirocco.cloudmanager.model.cimi.Machine;
import org.ow2.sirocco.cloudmanager.model.cimi.MachineConfiguration;
import org.ow2.sirocco.cloudmanager.model.cimi.MachineCreate;
import org.ow2.sirocco.cloudmanager.model.cimi.MachineImage;
import org.ow2.sirocco.cloudmanager.model.cimi.MachineTemplate;
import org.ow2.sirocco.cloudmanager.model.cimi.MachineTemplateNetworkInterface;
import org.ow2.sirocco.cloudmanager.model.cimi.Network;
import org.ow2.sirocco.cloudmanager.model.cimi.extension.CloudProviderAccount;
import org.ow2.sirocco.cloudmanager.model.cimi.extension.PlacementHint;
import org.ow2.sirocco.cloudmanager.model.cimi.extension.ProviderMapping;
import org.vaadin.teemu.wizards.Wizard;
import org.vaadin.teemu.wizards.WizardStep;
import org.vaadin.teemu.wizards.event.WizardCancelledEvent;
import org.vaadin.teemu.wizards.event.WizardCompletedEvent;
import org.vaadin.teemu.wizards.event.WizardProgressListener;
import org.vaadin.teemu.wizards.event.WizardStepActivationEvent;
import org.vaadin.teemu.wizards.event.WizardStepSetChangedEvent;

import com.vaadin.cdi.UIScoped;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.BeanContainer;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptAll;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.shared.ui.dd.VerticalDropLocation;
import com.vaadin.ui.AbstractSelect.AbstractSelectTargetDetails;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.Table.TableDragMode;
import com.vaadin.ui.Table.TableTransferable;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TwinColSelect;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

import de.steinwedel.messagebox.ButtonId;
import de.steinwedel.messagebox.Icon;
import de.steinwedel.messagebox.MessageBox;

@UIScoped
@SuppressWarnings("serial")
public class MachineCreationWizard extends Window implements WizardProgressListener {
    private MachineView machineView;

    private Wizard wizard;

    private Util.PlacementStep placementStep;

    private Util.MetadataStep metadataStep;

    private ImageStep imageStep;

    private ConfigStep configStep;

    private NetworkStep networkStep;

    private KeyPairStep keyPairStep;

    private UserDataStep userDataStep;

    private HostPlacementStep hostPlacementStep;

    @Inject
    private ICloudProviderManager providerManager;

    @Inject
    private IMachineManager machineManager;

    @Inject
    private IMachineImageManager machineImageManager;

    @Inject
    private ICredentialsManager credentialsManager;

    @Inject
    private INetworkManager networkManager;

    public MachineCreationWizard() {
        super("Machine Creation");
        this.center();
        this.setClosable(false);
        this.setModal(true);
        this.setResizable(false);

        VerticalLayout content = new VerticalLayout();
        content.setMargin(true);
        this.wizard = new Wizard();
        this.wizard.addListener(this);
        this.wizard.addStep(this.placementStep = new Util.PlacementStep(this.wizard), "placement");
        this.placementStep.setListener(new Property.ValueChangeListener() {

            @Override
            public void valueChange(final ValueChangeEvent event) {
                MachineCreationWizard.this.updateProviderSpecificResources();
            }
        });
        this.wizard.addStep(this.metadataStep = new Util.MetadataStep(this.wizard), "metadata");
        this.wizard.addStep(this.imageStep = new ImageStep(), "Image");
        this.wizard.addStep(this.configStep = new ConfigStep(), "Hardware");
        this.wizard.addStep(this.networkStep = new NetworkStep(), "Network");
        this.wizard.addStep(this.keyPairStep = new KeyPairStep(), "Key pair");
        this.wizard.addStep(this.userDataStep = new UserDataStep(), "User data");
        this.wizard.addStep(this.hostPlacementStep = new HostPlacementStep(), "Placement Constraints");
        this.wizard.setHeight("300px");
        this.wizard.setWidth("700px");

        content.addComponent(this.wizard);
        content.setComponentAlignment(this.wizard, Alignment.TOP_CENTER);
        this.setContent(content);
    }

    public boolean init(final MachineView machineView) {
        this.machineView = machineView;
        this.wizard.setUriFragmentEnabled(false);
        this.wizard.activateStep(this.placementStep);
        String tenantId = ((MyUI) UI.getCurrent()).getTenantId();

        this.placementStep.providerBox.removeAllItems();
        try {
            this.placementStep.setProviderManager(this.providerManager);
            for (CloudProviderAccount providerAccount : this.providerManager
                    .getCloudProviderAccountsByTenant(tenantId)) {
                this.placementStep.providerBox.addItem(providerAccount.getUuid());
                this.placementStep.providerBox.setItemCaption(providerAccount.getUuid(),
                        providerAccount.getCloudProvider().getDescription());
            }
            if (this.placementStep.providerBox.getItemIds().isEmpty()) {
                MessageBox.showPlain(Icon.ERROR, "No providers", "First add cloud providers", ButtonId.OK);
                return false;
            }
        } catch (CloudProviderException e) {
            Util.diplayErrorMessageBox("Internal error", e);
        }

        this.metadataStep.nameField.setValue("");
        this.metadataStep.descriptionField.setValue("");

        this.keyPairStep.keyPairBox.removeAllItems();
        try {
            for (Credentials cred : this.credentialsManager.getCredentials()) {
                this.keyPairStep.keyPairBox.addItem(cred.getUuid());
                this.keyPairStep.keyPairBox.setItemCaption(cred.getUuid(), cred.getName());
            }
        } catch (CloudProviderException e) {
            Util.diplayErrorMessageBox("Internal error", e);
        }
        this.updateProviderSpecificResources();
        return true;
    }

    private void updateProviderSpecificResources() {
        this.imageStep.imageBox.removeAllItems();
        try {
            for (MachineImage image : this.machineImageManager.getMachineImages()) {
                ProviderMapping mapping = ProviderMapping.find(image, this.getSelectedProviderAccountId(),
                        this.getLocationConstraint());
                if (mapping == null) {
                    continue;
                }
                this.imageStep.imageBox.addItem(image.getUuid());
                this.imageStep.imageBox.setItemCaption(image.getUuid(), image.getName());
            }
        } catch (CloudProviderException e) {
            Util.diplayErrorMessageBox("Internal error", e);
        }
        this.configStep.configBox.removeAllItems();
        List<MachineConfiguration> configs = new ArrayList<>();
        try {
            for (MachineConfiguration config : this.machineManager.getMachineConfigurations().getItems()) {
                ProviderMapping mapping = ProviderMapping.find(config, this.getSelectedProviderAccountId(),
                        this.getLocationConstraint());
                if (mapping == null) {
                    continue;
                }
                configs.add(config);
            }
        } catch (CloudProviderException e) {
            Util.diplayErrorMessageBox("Internal error", e);
        }
        Collections.sort(configs);
        for (MachineConfiguration config : configs) {
            this.configStep.configBox.addItem(config.getUuid());
            this.configStep.configBox.setItemCaption(config.getUuid(), config.getName());
        }

        this.networkStep.nics.removeAllItems();
        this.networkStep.nets.removeAllItems();
        try {
            for (Network net : this.networkManager.getNetworks().getItems()) {
                if (net.getCloudProviderAccount().getUuid().equals(this.getSelectedProviderAccountId())
                        && net.getLocation().matchLocationConstraint(this.getLocationConstraint())) {
                    this.networkStep.nets.addBean(new NetBean(net));
                }
            }
        } catch (CloudProviderException e) {
            Util.diplayErrorMessageBox("Internal error", e);
        }

        this.hostPlacementStep.machineSelect.removeAllItems();
        try {
            for (Machine machine : this.machineManager.getMachines().getItems()) {
                if (machine.getCloudProviderAccount().getUuid().equals(this.getSelectedProviderAccountId())
                        && machine.getLocation().matchLocationConstraint(this.getLocationConstraint())) {
                    this.hostPlacementStep.machineSelect.addItem(machine.getUuid());
                    this.hostPlacementStep.machineSelect.setItemCaption(machine.getUuid(), machine.getName());
                }
            }
        } catch (CloudProviderException e) {
            Util.diplayErrorMessageBox("Internal error", e);
        }
    }

    @Override
    public void activeStepChanged(final WizardStepActivationEvent event) {
        if (event.getActivatedStep() == this.metadataStep) {
            this.metadataStep.nameField.focus();
        }
    }

    @Override
    public void stepSetChanged(final WizardStepSetChangedEvent event) {
    }

    private String getSelectedProviderAccountId() {
        return (String) MachineCreationWizard.this.placementStep.providerBox.getValue();
    }

    private String getLocationConstraint() {
        return (String) MachineCreationWizard.this.placementStep.locationBox.getValue();
    }

    @Override
    public void wizardCompleted(final WizardCompletedEvent event) {
        this.close();

        MachineCreate machineCreate = new MachineCreate();
        machineCreate.setProperties(new HashMap<String, String>());

        try {
            String accountId = this.getSelectedProviderAccountId();
            machineCreate.setProviderAccountId(accountId);
            machineCreate.setLocation(this.getLocationConstraint());
            machineCreate.setName(MachineCreationWizard.this.metadataStep.nameField.getValue());
            machineCreate.setDescription(MachineCreationWizard.this.metadataStep.descriptionField.getValue());
            if (machineCreate.getDescription().isEmpty()) {
                machineCreate.setDescription(null);
            }
            MachineTemplate machineTemplate = new MachineTemplate();
            MachineConfiguration machineConfig = MachineCreationWizard.this.machineManager
                    .getMachineConfigurationByUuid(
                            (MachineCreationWizard.this.configStep.configBox.getValue()).toString());
            machineTemplate.setMachineConfig(machineConfig);
            MachineImage machineImage = MachineCreationWizard.this.machineImageManager
                    .getMachineImageByUuid((MachineCreationWizard.this.imageStep.imageBox.getValue()).toString());
            machineTemplate.setMachineImage(machineImage);

            // network interfaces
            List<MachineTemplateNetworkInterface> nics = new ArrayList<>();
            machineTemplate.setNetworkInterfaces(nics);
            for (Object itemId : MachineCreationWizard.this.networkStep.nicTable.getItemIds()) {
                NicBean nicBean = MachineCreationWizard.this.networkStep.nics.getItem(itemId).getBean();
                MachineTemplateNetworkInterface nic = new MachineTemplateNetworkInterface();
                nic.setNetwork(nicBean.net);
                nics.add(nic);
            }

            if (MachineCreationWizard.this.keyPairStep.keyPairBox.getValue() != null) {
                Credentials cred = MachineCreationWizard.this.credentialsManager.getCredentialsByUuid(
                        (MachineCreationWizard.this.keyPairStep.keyPairBox.getValue()).toString());
                machineTemplate.setCredential(cred);
            }

            machineTemplate.setUserData(MachineCreationWizard.this.userDataStep.userDataField.getValue());
            if (machineTemplate.getUserData().isEmpty()) {
                machineTemplate.setUserData(null);
            }

            String placementConstraint = (String) this.hostPlacementStep.constraintBox.getValue();
            if (!placementConstraint.equals("NONE")) {
                PlacementHint placementHint = new PlacementHint();
                switch (placementConstraint) {
                case "AFFINITY":
                    placementHint.setPlacementConstraint(PlacementHint.AFFINITY_CONSTRAINT);
                    break;
                case "ANTI AFFINITY":
                    placementHint.setPlacementConstraint(PlacementHint.ANTI_AFFINITY_CONSTRAINT);
                    break;
                }
                @SuppressWarnings("unchecked")
                Set<String> selectedMachineIds = (Set<String>) this.hostPlacementStep.machineSelect.getValue();
                placementHint.setMachineIds(new ArrayList<String>(selectedMachineIds));
                machineTemplate.setPlacementHint(placementHint);
            }

            machineCreate.setMachineTemplate(machineTemplate);

            Job job = MachineCreationWizard.this.machineManager.createMachine(machineCreate);
            Machine newMachine = (Machine) job.getAffectedResources().get(0);

            MachineCreationWizard.this.machineView.machines.addBeanAt(0, new MachineBean(newMachine));

            UI.getCurrent().push();
        } catch (CloudProviderException e) {
            Util.diplayErrorMessageBox("Instance creation failure", e);
        }

    }

    @Override
    public void wizardCancelled(final WizardCancelledEvent event) {
        this.close();
    }

    private class ImageStep implements WizardStep {
        FormLayout content;

        ComboBox imageBox;

        ImageStep() {
            this.content = new FormLayout();
            this.content.setSizeFull();
            this.content.setMargin(true);

            this.imageBox = new ComboBox("Image");
            this.imageBox.setTextInputAllowed(false);
            this.imageBox.setNullSelectionAllowed(false);
            this.imageBox.setInputPrompt("select image");
            this.imageBox.setImmediate(true);
            this.content.addComponent(this.imageBox);
            this.imageBox.addValueChangeListener(new Property.ValueChangeListener() {

                @Override
                public void valueChange(final ValueChangeEvent event) {
                    MachineCreationWizard.this.wizard.updateButtons();
                }
            });
        }

        @Override
        public String getCaption() {
            return "Image";
        }

        @Override
        public Component getContent() {
            return this.content;
        }

        @Override
        public boolean onAdvance() {
            return this.imageBox.getValue() != null;
        }

        @Override
        public boolean onBack() {
            return true;
        }

    }

    private class ConfigStep implements WizardStep {
        FormLayout content;

        ComboBox configBox;

        ConfigStep() {
            this.content = new FormLayout();
            this.content.setSizeFull();
            this.content.setMargin(true);

            this.configBox = new ComboBox("Hardware config");
            this.configBox.setTextInputAllowed(false);
            this.configBox.setNullSelectionAllowed(false);
            this.configBox.setInputPrompt("select config");
            this.configBox.setImmediate(true);
            this.content.addComponent(this.configBox);
            this.configBox.addValueChangeListener(new Property.ValueChangeListener() {

                @Override
                public void valueChange(final ValueChangeEvent event) {
                    MachineCreationWizard.this.wizard.updateButtons();
                }
            });
        }

        @Override
        public String getCaption() {
            return "Hardware";
        }

        @Override
        public Component getContent() {
            return this.content;
        }

        @Override
        public boolean onAdvance() {
            return this.configBox.getValue() != null;
        }

        @Override
        public boolean onBack() {
            return true;
        }

    }

    private class NetworkStep implements WizardStep {
        HorizontalLayout content;

        Table nicTable;

        Table netTable;

        private BeanContainer<String, NicBean> nics = new BeanContainer<String, NicBean>(NicBean.class);

        private BeanContainer<String, NetBean> nets = new BeanContainer<String, NetBean>(NetBean.class);

        NetworkStep() {
            this.content = new HorizontalLayout();
            this.content.setSizeFull();
            this.content.setMargin(true);
            this.content.setSpacing(true);

            this.nicTable = new Table("Network Interfaces", this.nics);
            this.nics.setBeanIdProperty("id");
            this.nicTable.setPageLength(4);
            this.nicTable.setSelectable(true);
            this.nicTable.setImmediate(true);
            this.nicTable.setVisibleColumns("network");
            this.nicTable.setWidth("100%");
            this.nicTable.setDropHandler(new DropHandler() {

                @Override
                public AcceptCriterion getAcceptCriterion() {
                    return AcceptAll.get();
                }

                @Override
                public void drop(final DragAndDropEvent event) {
                    TableTransferable tableTransferable = (TableTransferable) event.getTransferable();
                    String netId = (String) tableTransferable.getItemId();
                    AbstractSelectTargetDetails dropData = ((AbstractSelectTargetDetails) event.getTargetDetails());
                    String targetItemId = (String) dropData.getItemIdOver();
                    VerticalDropLocation location = dropData.getDropLocation();

                    if (targetItemId == null) {
                        NetworkStep.this.nics
                                .addBean(new NicBean(NetworkStep.this.nets.getItem(netId).getBean().net));
                    } else {

                        if (location == VerticalDropLocation.MIDDLE || location == VerticalDropLocation.TOP) {
                            String prevItemId = NetworkStep.this.nics.prevItemId(targetItemId);
                            NetworkStep.this.nics.addBeanAfter(prevItemId,
                                    new NicBean(NetworkStep.this.nets.getItem(netId).getBean().net));
                        } else {
                            NetworkStep.this.nics.addBeanAfter(targetItemId,
                                    new NicBean(NetworkStep.this.nets.getItem(netId).getBean().net));
                        }
                    }

                }
            });
            this.content.addComponent(this.nicTable);

            this.netTable = new Table("Networks", this.nets);
            this.nets.setBeanIdProperty("id");
            this.netTable.setPageLength(4);
            this.netTable.setSelectable(true);
            this.netTable.setImmediate(true);
            this.netTable.setVisibleColumns("network");
            this.netTable.setWidth("100%");
            this.netTable.setDragMode(TableDragMode.ROW);
            this.content.addComponent(this.netTable);

            // HorizontalLayout buttonBar = new HorizontalLayout();
            // buttonBar.setMargin(true);
            // buttonBar.setSpacing(true);
            // Button button = new Button("Add NIC", new ClickListener() {
            //
            // @Override
            // public void buttonClick(ClickEvent event) {
            // }
            // });
            // buttonBar.addComponent(button);
            // button = new Button("Remove NIC", new ClickListener() {
            //
            // @Override
            // public void buttonClick(ClickEvent event) {
            // }
            // });
            // buttonBar.addComponent(button);
            // content.addComponent(buttonBar);

        }

        @Override
        public String getCaption() {
            return "Network";
        }

        @Override
        public Component getContent() {
            return this.content;
        }

        @Override
        public boolean onAdvance() {
            return true;
        }

        @Override
        public boolean onBack() {
            return true;
        }

    }

    private class KeyPairStep implements WizardStep {
        FormLayout content;

        ComboBox keyPairBox;

        KeyPairStep() {
            this.content = new FormLayout();
            this.content.setSizeFull();
            this.content.setMargin(true);

            this.keyPairBox = new ComboBox("Key pair");
            this.keyPairBox.setTextInputAllowed(false);
            this.keyPairBox.setNullSelectionAllowed(false);
            this.keyPairBox.setInputPrompt("select config");
            this.keyPairBox.setImmediate(true);
            this.content.addComponent(this.keyPairBox);
        }

        @Override
        public String getCaption() {
            return "Key pair";
        }

        @Override
        public Component getContent() {
            return this.content;
        }

        @Override
        public boolean onAdvance() {
            return true;
        }

        @Override
        public boolean onBack() {
            return true;
        }

    }

    private class UserDataStep implements WizardStep {
        FormLayout content;

        TextArea userDataField;

        UserDataStep() {
            this.content = new FormLayout();
            this.content.setSizeFull();
            this.content.setMargin(true);

            this.userDataField = new TextArea("User data");
            this.userDataField.setWidth("80%");
            this.content.addComponent(this.userDataField);
        }

        @Override
        public String getCaption() {
            return "User data";
        }

        @Override
        public Component getContent() {
            return this.content;
        }

        @Override
        public boolean onAdvance() {
            return true;
        }

        @Override
        public boolean onBack() {
            return true;
        }

    }

    private class HostPlacementStep implements WizardStep {
        VerticalLayout content;

        ComboBox constraintBox;

        TwinColSelect machineSelect;

        HostPlacementStep() {
            this.content = new VerticalLayout();
            // this.content.setSizeFull();
            this.content.setMargin(true);
            // this.content.setSpacing(true);

            this.constraintBox = new ComboBox("Placement rule");
            this.constraintBox.setTextInputAllowed(false);
            this.constraintBox.setNullSelectionAllowed(false);
            // this.constraintBox.setInputPrompt("select constraint");
            this.constraintBox.setImmediate(true);

            this.content.addComponent(this.constraintBox);
            this.constraintBox.addItem("NONE");
            this.constraintBox.addItem("AFFINITY");
            this.constraintBox.addItem("ANTI AFFINITY");
            this.constraintBox.setValue("NONE");

            this.machineSelect = new TwinColSelect("");
            this.machineSelect.setEnabled(false);
            this.machineSelect.setLeftColumnCaption("Available machines");
            this.machineSelect.setRightColumnCaption("Placement rule members");
            // this.machineSelect.setHeight("200px");
            this.machineSelect.setRows(5);
            this.machineSelect.setWidth("100%");
            this.content.addComponent(this.machineSelect);

            this.constraintBox.addValueChangeListener(new Property.ValueChangeListener() {
                @Override
                public void valueChange(final ValueChangeEvent event) {
                    HostPlacementStep.this.machineSelect
                            .setEnabled(HostPlacementStep.this.constraintBox.getValue() != null
                                    && !HostPlacementStep.this.constraintBox.getValue().equals("NONE"));
                }
            });

        }

        @Override
        public Component getContent() {
            return this.content;
        }

        @Override
        public String getCaption() {
            return "Placement";
        }

        @Override
        public boolean onAdvance() {
            return true;
        }

        @Override
        public boolean onBack() {
            return true;
        }
    }

    public static class NicBean {
        String id;

        String network;

        Network net;

        NicBean(final Network net) {
            this.net = net;
            this.id = net.getUuid();
            this.network = net.getName();
        }

        public String getId() {
            return this.id;
        }

        public String getNetwork() {
            return this.network;
        }

    }

    public static class NetBean {
        String id;

        String network;

        Network net;

        NetBean(final Network net) {
            this.net = net;
            this.id = net.getUuid();
            this.network = net.getName();
        }

        public String getId() {
            return this.id;
        }

        public String getNetwork() {
            return this.network;
        }

    }

}