/* * Copyright 2014 by SCSK Corporation. * * This file is part of PrimeCloud Controller(TM). * * PrimeCloud Controller(TM) 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 of the License, or * (at your option) any later version. * * PrimeCloud Controller(TM) 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 PrimeCloud Controller(TM). If not, see <http://www.gnu.org/licenses/>. */ package jp.primecloud.auto.ui; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import jp.primecloud.auto.common.status.ComponentInstanceStatus; import jp.primecloud.auto.common.status.InstanceStatus; import jp.primecloud.auto.entity.crud.AwsVolume; import jp.primecloud.auto.entity.crud.AzureDisk; import jp.primecloud.auto.entity.crud.CloudstackVolume; import jp.primecloud.auto.entity.crud.ComponentType; import jp.primecloud.auto.entity.crud.OpenstackVolume; import jp.primecloud.auto.entity.crud.VcloudDisk; import jp.primecloud.auto.entity.crud.VmwareDisk; import jp.primecloud.auto.service.ComponentService; import jp.primecloud.auto.service.dto.ComponentDto; import jp.primecloud.auto.service.dto.ComponentInstanceDto; import jp.primecloud.auto.service.dto.ImageDto; import jp.primecloud.auto.service.dto.InstanceDto; import jp.primecloud.auto.ui.util.BeanContext; import jp.primecloud.auto.ui.util.ContextUtils; import jp.primecloud.auto.ui.util.IconUtils; import jp.primecloud.auto.ui.util.Icons; import jp.primecloud.auto.ui.util.ViewContext; import jp.primecloud.auto.ui.util.ViewProperties; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.event.ItemClickEvent; import com.vaadin.event.ItemClickEvent.ItemClickListener; import com.vaadin.event.ShortcutAction.KeyCode; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.CheckBox; import com.vaadin.ui.Form; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Table; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; /** * <p> * サーバ作成(編集)画面からサービスの割当ボタンを押したときのサービス割当画面を生成します。 * </p> * */ @SuppressWarnings("serial") public class WinServerAttachService extends Window { private InstanceDto instance; private ImageDto image; private List<Long> selectedComponentNos; private AttachService attachService; private List<ComponentDto> components; public WinServerAttachService(InstanceDto instance, ImageDto image, List<Long> selectedComponentNos) { this.instance = instance; this.image = image; this.selectedComponentNos = selectedComponentNos; } @Override public void attach() { // モーダルウインドウ setIcon(Icons.ADD.resource()); setCaption(ViewProperties.getCaption("window.winServerAttachService")); setModal(true); setWidth("500px"); VerticalLayout layout = (VerticalLayout) getContent(); layout.setMargin(true, true, false, true); layout.setSpacing(false); // Form Form form = new Form(); // サーバ名 TextField serverNameField = new TextField(ViewProperties.getCaption("field.serverName")); if (instance != null) { serverNameField.setValue(instance.getInstance().getInstanceName()); } else { serverNameField.setValue(ViewProperties.getCaption("field.newServer")); } serverNameField.setReadOnly(true); form.getLayout().addComponent(serverNameField); attachService = new AttachService(instance, image, selectedComponentNos); form.getLayout().addComponent(attachService); layout.addComponent(form); // 下部のバー HorizontalLayout bottomLayout = new HorizontalLayout(); bottomLayout.setSpacing(true); bottomLayout.setMargin(false, false, true, false); layout.addComponent(bottomLayout); layout.setComponentAlignment(bottomLayout, Alignment.BOTTOM_RIGHT); // OKボタン Button okButton = new Button(ViewProperties.getCaption("button.ok")); okButton.setDescription(ViewProperties.getCaption("description.ok")); okButton.addListener(new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { addButtonClick(event); } }); okButton.setClickShortcut(KeyCode.ENTER); // [Enter]でokButtonクリック okButton.focus(); bottomLayout.addComponent(okButton); // Cancelボタン Button cancelButton = new Button(ViewProperties.getCaption("button.cancel")); cancelButton.setDescription(ViewProperties.getCaption("description.cancel")); cancelButton.addListener(new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { close(); } }); bottomLayout.addComponent(cancelButton); // サービス情報を表示 loadData(); attachService.show(components); } private class AttachService extends Table { private final String COLUMN_HEIGHT = "32px"; private InstanceDto instance; private ImageDto image; private List<Long> selectedComponentNos; private List<ComponentDto> components; public AttachService(InstanceDto instance, ImageDto image, List<Long> selectedComponentNos) { this.instance = instance; this.image = image; this.selectedComponentNos = (selectedComponentNos == null) ? new ArrayList<Long>() : selectedComponentNos; } @Override public void attach() { // テーブル基本設定 setColumnHeaderMode(Table.COLUMN_HEADER_MODE_EXPLICIT); addStyleName("win-server-attach-service"); setCaption(ViewProperties.getCaption("table.serverAttachServices")); setSortDisabled(true); setMultiSelect(false); setImmediate(false); setVisible(true); setWidth("100%"); setPageLength(5); // カラム設定 addContainerProperty("check", CheckBox.class, new CheckBox()); addContainerProperty("componentName", Label.class, new Label()); addContainerProperty("status", Label.class, new Label()); setColumnExpandRatio("componentName", 100); String[] headers = { "", ViewProperties.getCaption("field.serviceName"), ViewProperties.getCaption("field.serviceStatus") }; setColumnHeaders(headers); // テーブルのカラムに対してStyleNameを設定 setCellStyleGenerator(new StandardCellStyleGenerator() { @Override public String getStyle(Object itemId, Object propertyId) { String style = super.getStyle(itemId, propertyId); CheckBox checkBox = getCheckBox(getItem(itemId)); // チェックボックスが選択されていれば行の色を変える if (checkBox.booleanValue()) { style += " v-selected"; } // チェックボックスが無効なら色を変更する if (!checkBox.isEnabled()) { style += " v-disabled"; } return style; } }); // 行が選択された場合、行のチェックボックスの値を変える addListener(new ItemClickListener() { @Override public void itemClick(ItemClickEvent event) { CheckBox checkBox = getCheckBox(event.getItem()); if (checkBox.isEnabled()) { checkBox.setValue(!checkBox.booleanValue()); } } }); } public void show(List<ComponentDto> components) { this.components = components; removeAllItems(); if (components == null) { return; } for (ComponentDto component : components) { // チェックボックス CheckBox checkBox = new CheckBox(); checkBox.setImmediate(true); checkBox.setEnabled(false); if (selectedComponentNos.contains(component.getComponent().getComponentNo())) { checkBox.setValue(true); } else { checkBox.setValue(false); } checkBox.addListener(new Property.ValueChangeListener() { @Override public void valueChange(Property.ValueChangeEvent event) { // チェックボックスの有効/無効を制御 changeCheckEnabled(); // テーブル再描画 requestRepaint(); } }); // サービス名 String serviceName = component.getComponent().getComponentName(); if (StringUtils.isNotEmpty(component.getComponent().getComment())) { serviceName = component.getComponent().getComment() + "\n[" + serviceName + "]"; } Label serviceNameLabel = new Label(serviceName, Label.CONTENT_PREFORMATTED); serviceNameLabel.setHeight(COLUMN_HEIGHT); // ステータス String status = null; if (instance != null) { for (ComponentInstanceDto componentInstance : instance.getComponentInstances()) { if (componentInstance.getComponentInstance().getComponentNo() .equals(component.getComponent().getComponentNo())) { status = componentInstance.getComponentInstance().getStatus(); break; } } } if (StringUtils.isEmpty(status)) { status = "Stopped"; } else { status = StringUtils.capitalize(StringUtils.lowerCase(status)); } Icons statusIcon = Icons.fromName(status); Label statusLabel = new Label(IconUtils.createImageTag(getApplication(), statusIcon, status), Label.CONTENT_XHTML); statusLabel.setHeight(COLUMN_HEIGHT); addItem(new Object[] { checkBox, serviceNameLabel, statusLabel }, component.getComponent() .getComponentNo()); } changeCheckEnabled(); } @Override @SuppressWarnings("unchecked") public Collection<Long> getItemIds() { return (Collection<Long>) super.getItemIds(); } public List<Long> getSelectedValues() { List<Long> componentNos = new ArrayList<Long>(); for (Long componentNo : getItemIds()) { CheckBox checkBox = getCheckBox(getItem(componentNo)); if (checkBox.booleanValue()) { componentNos.add(componentNo); } } return componentNos; } private CheckBox getCheckBox(Item item) { return (CheckBox) item.getItemProperty("check").getValue(); } private void changeCheckEnabled() { // チェックボックスの有効/無効を制御する Set<Long> disableComponentNos = new HashSet<Long>(); // 利用可能でないサービスは無効 List<Long> componentTypeNos = new ArrayList<Long>(); for (ComponentType componentType : image.getComponentTypes()) { componentTypeNos.add(componentType.getComponentTypeNo()); } for (ComponentDto component : components) { if (!componentTypeNos.contains(component.getComponent().getComponentTypeNo())) { disableComponentNos.add(component.getComponent().getComponentNo()); } } if (instance != null) { // 割り当て済みでStoppedでないサービスは無効 for (ComponentInstanceDto componentInstance : instance.getComponentInstances()) { for (ComponentDto component : components) { if (componentInstance.getComponentInstance().getComponentNo() .equals(component.getComponent().getComponentNo())) { ComponentInstanceStatus status = ComponentInstanceStatus.fromStatus(componentInstance .getComponentInstance().getStatus()); if (status != ComponentInstanceStatus.STOPPED) { disableComponentNos.add(component.getComponent().getComponentNo()); } break; } } } // ディスクがアタッチされているサービスは無効 if (instance.getAwsVolumes() != null) { for (AwsVolume awsVolume : instance.getAwsVolumes()) { if (StringUtils.isNotEmpty(awsVolume.getInstanceId())) { disableComponentNos.add(awsVolume.getComponentNo()); } } } if (instance.getCloudstackVolumes() != null) { for (CloudstackVolume cloudstackVolume : instance.getCloudstackVolumes()) { if (StringUtils.isNotEmpty(cloudstackVolume.getInstanceId())) { disableComponentNos.add(cloudstackVolume.getComponentNo()); } } } if (instance.getVmwareDisks() != null) { for (VmwareDisk vmwareDisk : instance.getVmwareDisks()) { if (BooleanUtils.isTrue(vmwareDisk.getAttached())) { disableComponentNos.add(vmwareDisk.getComponentNo()); } } } if (instance.getVcloudDisks() != null) { for (VcloudDisk vcloudDisk : instance.getVcloudDisks()) { if (BooleanUtils.isTrue(vcloudDisk.getAttached())) { if (InstanceStatus.fromStatus(instance.getInstance().getStatus()) != InstanceStatus.STOPPED) { disableComponentNos.add(vcloudDisk.getComponentNo()); } } } } if (instance.getAzureDisks() != null) { for (AzureDisk azureDisk : instance.getAzureDisks()) { if (StringUtils.isNotEmpty(azureDisk.getInstanceName())) { if (InstanceStatus.fromStatus(instance.getInstance().getStatus()) != InstanceStatus.STOPPED) { disableComponentNos.add(azureDisk.getComponentNo()); } } } } if (instance.getOpenstackVolumes() != null) { for (OpenstackVolume openstackVolume : instance.getOpenstackVolumes()) { if (StringUtils.isNotEmpty(openstackVolume.getInstanceId())) { if (InstanceStatus.fromStatus(instance.getInstance().getStatus()) != InstanceStatus.STOPPED) { disableComponentNos.add(openstackVolume.getComponentNo()); } } } } } // 同一レイヤのサービス種類が選択されているサービスは無効 for (ComponentDto component : components) { CheckBox checkBox = getCheckBox(getItem(component.getComponent().getComponentNo())); if (checkBox.booleanValue()) { for (ComponentDto component2 : components) { if (component.getComponent().getComponentNo() .equals(component2.getComponent().getComponentNo())) { continue; } if (component.getComponentType().getLayer().equals(component2.getComponentType().getLayer())) { disableComponentNos.add(component2.getComponent().getComponentNo()); } } } } // 有効/無効を反映 for (Long componentNo : getItemIds()) { CheckBox checkBox = getCheckBox(getItem(componentNo)); if (disableComponentNos.contains(componentNo)) { checkBox.setEnabled(false); } else { checkBox.setEnabled(true); } } } } private void loadData() { // 全てのサービス情報を取得 ComponentService componentService = BeanContext.getBean(ComponentService.class); components = componentService.getComponents(ViewContext.getFarmNo()); } private void addButtonClick(ClickEvent event) { // 選択したサービスの番号を取得 List<Long> componentNos = attachService.getSelectedValues(); // 選択したサービス追加したサービスの番号をセッションに格納 ContextUtils.setAttribute("componentNos", componentNos); // 画面を閉じる close(); } }