Tomas Jelinek has uploaded a new change for review.

Change subject: webadmin,userporta: clone VM wip
......................................................................

webadmin,userporta: clone VM wip

Clone VM WIP

Change-Id: I6ae2bca7ce33412da3881ccadc9bb1543e32ace2
Signed-off-by: Tomas Jelinek <[email protected]>
---
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
A 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/vm/CloneVmWidget.java
A 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/vm/CloneVmWidget.ui.xml
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/userportal/UserPortalListModel.java
A 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/CloneVmModel.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmListModel.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmModelHelper.java
M 
frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
M 
frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
M 
frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/gin/PresenterModule.java
A 
frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/presenter/popup/vm/CloneVmPopupPresenterWidget.java
A 
frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/view/popup/vm/CloneVmPopupView.java
M 
frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/view/tab/extended/SideTabExtendedVirtualMachineView.java
M 
frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/uicommon/model/vm/UserPortalListProvider.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VirtualMachineModule.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/vm/CloneVmPopupPresenterWidget.java
A 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/vm/CloneVmPopupView.java
M 
frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVirtualMachineView.java
19 files changed, 559 insertions(+), 20 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/06/23806/1

diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
index 8832c68..a03c40a 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
@@ -378,6 +378,9 @@
     @DefaultStringValue("New VM")
     String newVm();
 
+    @DefaultStringValue("Clone VM")
+    String cloneVm();
+
     @DefaultStringValue("Power Off")
     String powerOffVm();
 
@@ -667,6 +670,12 @@
     @DefaultStringValue("Specific")
     String specificVmPopup();
 
+    @DefaultStringValue("Clone Name")
+    String clonedVmName();
+
+    @DefaultStringValue("Include Memory")
+    String includeMemory();
+
     // Permissions
     @DefaultStringValue("Inherited Permission")
     String inheritedPermission();
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/vm/CloneVmWidget.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/vm/CloneVmWidget.java
new file mode 100644
index 0000000..490f92c
--- /dev/null
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/vm/CloneVmWidget.java
@@ -0,0 +1,94 @@
+package org.ovirt.engine.ui.common.widget.uicommon.popup.vm;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.editor.client.SimpleBeanEditorDriver;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Label;
+import org.ovirt.engine.ui.common.CommonApplicationConstants;
+import org.ovirt.engine.ui.common.idhandler.ElementIdHandler;
+import org.ovirt.engine.ui.common.idhandler.WithElementId;
+import 
org.ovirt.engine.ui.common.widget.editor.generic.EntityModelCheckBoxEditor;
+import 
org.ovirt.engine.ui.common.widget.editor.generic.StringEntityModelTextBoxEditor;
+import 
org.ovirt.engine.ui.common.widget.uicommon.popup.AbstractModelBoundPopupWidget;
+import org.ovirt.engine.ui.uicommonweb.models.vms.CloneVmModel;
+import org.ovirt.engine.ui.uicompat.Event;
+import org.ovirt.engine.ui.uicompat.EventArgs;
+import org.ovirt.engine.ui.uicompat.IEventListener;
+import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs;
+
+public class CloneVmWidget extends AbstractModelBoundPopupWidget<CloneVmModel> 
{
+
+    private final CommonApplicationConstants constants;
+
+    interface Driver extends SimpleBeanEditorDriver<CloneVmModel, 
CloneVmWidget> {
+    }
+
+    interface ViewUiBinder extends UiBinder<FlowPanel, CloneVmWidget> {
+        ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class);
+    }
+
+    interface ViewIdHandler extends ElementIdHandler<CloneVmWidget> {
+        ViewIdHandler idHandler = GWT.create(ViewIdHandler.class);
+    }
+
+    private final Driver driver = GWT.create(Driver.class);
+
+    @UiField
+    @Path(value = "cloneName.entity")
+    @WithElementId("cloneName")
+    StringEntityModelTextBoxEditor cloneNameEditor;
+
+    @UiField
+    @Path(value = "includeMemory.entity")
+    @WithElementId("includeMemory")
+    EntityModelCheckBoxEditor includeMemoryEditor;
+
+    @UiField
+    @Ignore
+    @WithElementId("warnings")
+    FlowPanel warningsPanel;
+
+    public CloneVmWidget(CommonApplicationConstants constants) {
+        this.constants = constants;
+
+        initWidget(ViewUiBinder.uiBinder.createAndBindUi(this));
+        ViewIdHandler.idHandler.generateAndSetIds(this);
+        driver.initialize(this);
+
+        localize();
+    }
+
+    private void localize() {
+        cloneNameEditor.setLabel(constants.clonedVmName());
+        includeMemoryEditor.setLabel(constants.includeMemory());
+    }
+
+    @Override
+    public void edit(final CloneVmModel object) {
+        driver.edit(object);
+
+        object.getPropertyChangedEvent().addListener(new IEventListener() {
+            @Override
+            public void eventRaised(Event ev, Object sender, EventArgs args) {
+                String propName = ((PropertyChangedEventArgs) 
args).propertyName;
+                if ("Message".equals(propName)) { //$NON-NLS-1$
+                    if (object.getMessage() != null) {
+                        warningsPanel.add(new Label(object.getMessage()));
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public CloneVmModel flush() {
+        return driver.flush();
+    }
+
+    @Override
+    public void focusInput() {
+        cloneNameEditor.setFocus(true);
+    }
+}
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/vm/CloneVmWidget.ui.xml
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/vm/CloneVmWidget.ui.xml
new file mode 100644
index 0000000..040391a
--- /dev/null
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/vm/CloneVmWidget.ui.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent";>
+<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" 
xmlns:g="urn:import:com.google.gwt.user.client.ui"
+             
xmlns:ge="urn:import:org.ovirt.engine.ui.common.widget.editor.generic">
+
+    <ui:style>
+        .messagePanel {
+            color: #CD2127;
+        }
+    </ui:style>
+
+    <g:FlowPanel>
+        <ge:StringEntityModelTextBoxEditor ui:field="cloneNameEditor" />
+        <ge:EntityModelCheckBoxEditor ui:field="includeMemoryEditor" />
+        <g:FlowPanel ui:field="warningsPanel" 
addStyleNames="{style.messagePanel}" />
+    </g:FlowPanel>
+
+</ui:UiBinder>
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/userportal/UserPortalListModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/userportal/UserPortalListModel.java
index fc33be4..a1937f0 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/userportal/UserPortalListModel.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/userportal/UserPortalListModel.java
@@ -1,12 +1,5 @@
 package org.ovirt.engine.ui.uicommonweb.models.userportal;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-
 import org.ovirt.engine.core.common.VdcActionUtils;
 import org.ovirt.engine.core.common.action.AddVmFromScratchParameters;
 import org.ovirt.engine.core.common.action.AddVmFromTemplateParameters;
@@ -54,6 +47,7 @@
 import org.ovirt.engine.ui.uicommonweb.models.pools.PoolDiskListModel;
 import org.ovirt.engine.ui.uicommonweb.models.pools.PoolGeneralModel;
 import org.ovirt.engine.ui.uicommonweb.models.pools.PoolInterfaceListModel;
+import org.ovirt.engine.ui.uicommonweb.models.vms.CloneVmModel;
 import org.ovirt.engine.ui.uicommonweb.models.vms.ConsoleModel;
 import org.ovirt.engine.ui.uicommonweb.models.vms.DataCenterWithCluster;
 import org.ovirt.engine.ui.uicommonweb.models.vms.RunOnceModel;
@@ -85,6 +79,13 @@
 import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs;
 import org.ovirt.engine.ui.uicompat.UIConstants;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
 public class UserPortalListModel extends AbstractUserPortalListModel {
 
     private final UIConstants constants = 
ConstantsManager.getInstance().getConstants();
@@ -99,6 +100,16 @@
     private void setSearchCompletedEvent(Event value)
     {
         privateSearchCompletedEvent = value;
+    }
+
+    private UICommand cloneVmCommand;
+
+    public UICommand getCloneVmCommand() {
+        return cloneVmCommand;
+    }
+
+    public void setCloneVmCommand(UICommand cloneVmCommand) {
+        this.cloneVmCommand = cloneVmCommand;
     }
 
     private UICommand privateNewVmCommand;
@@ -266,6 +277,7 @@
         setSearchCompletedEvent(new Event(searchCompletedEventDefinition));
 
         setNewVmCommand(new UICommand("NewVm", this)); //$NON-NLS-1$
+        setCloneVmCommand(new UICommand("CloneVm", this)); //$NON-NLS-1$
         setEditCommand(new UICommand("Edit", this)); //$NON-NLS-1$
         setRemoveCommand(new UICommand("Remove", this)); //$NON-NLS-1$
         setSaveCommand(new UICommand("Save", this)); //$NON-NLS-1$
@@ -455,6 +467,9 @@
     {
         super.executeCommand(command);
 
+        if (command == getCloneVmCommand()) {
+            cloneVm();
+        }
         if (command == getNewVmCommand())
         {
             newInternal();
@@ -505,7 +520,37 @@
         }
         else if (command.getName().equals("closeVncInfo")) { //$NON-NLS-1$
             setWindow(null);
+        } else if (StringHelper.stringsEqual(command.getName(), "OnClone")) { 
//$NON-NLS-1$
+            onClone();
         }
+    }
+
+    private void cloneVm() {
+        final UserPortalItemModel vm = (UserPortalItemModel) getSelectedItem();
+        if (vm == null) {
+            return;
+        }
+
+        CloneVmModel model = new CloneVmModel(vm.getVM(), constants);
+        setWindow(model);
+
+        model.initialize();
+        model.setTitle(ConstantsManager.getInstance()
+                .getConstants().cloneVmTitle());
+        model.setHashName("clone_vm"); //$NON-NLS-1$
+
+        UICommand okCommand = new UICommand("OnClone", this); //$NON-NLS-1$
+        okCommand.setTitle(ConstantsManager.getInstance().getConstants().ok());
+        okCommand.setIsDefault(true);
+        model.getCommands().add(okCommand);
+        UICommand cancelCommand = new UICommand("Cancel", this); //$NON-NLS-1$
+        
cancelCommand.setTitle(ConstantsManager.getInstance().getConstants().cancel());
+        cancelCommand.setIsCancel(true);
+        model.getCommands().add(cancelCommand);
+    }
+
+    private void onClone() {
+        ((CloneVmModel) getWindow()).onClone(this, true);
     }
 
     private void newTemplate()
@@ -705,6 +750,8 @@
 
         getEditCommand().setIsExecutionAllowed(selectedItem != null && 
!selectedItem.isPool());
 
+        getCloneVmCommand().setIsExecutionAllowed(selectedItem != null && 
!selectedItem.isPool());
+
         getRemoveCommand().setIsExecutionAllowed(selectedItem != null
                 && !selectedItem.isPool()
                 && VdcActionUtils.canExecute(new 
ArrayList<VM>(Arrays.asList(new VM[]{(VM) selectedItem.getEntity()})),
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/CloneVmModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/CloneVmModel.java
new file mode 100644
index 0000000..fc5a858
--- /dev/null
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/CloneVmModel.java
@@ -0,0 +1,171 @@
+package org.ovirt.engine.ui.uicommonweb.models.vms;
+
+import org.ovirt.engine.core.common.action.CloneVmParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Disk;
+import org.ovirt.engine.core.common.businessentities.DiskImage;
+import org.ovirt.engine.core.common.businessentities.VM;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.ui.frontend.AsyncQuery;
+import org.ovirt.engine.ui.frontend.Frontend;
+import org.ovirt.engine.ui.frontend.INewAsyncCallback;
+import org.ovirt.engine.ui.uicommonweb.Linq;
+import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider;
+import org.ovirt.engine.ui.uicommonweb.models.EntityModel;
+import org.ovirt.engine.ui.uicommonweb.models.Model;
+import org.ovirt.engine.ui.uicommonweb.validation.I18NNameValidation;
+import org.ovirt.engine.ui.uicommonweb.validation.IValidation;
+import org.ovirt.engine.ui.uicommonweb.validation.LengthValidation;
+import org.ovirt.engine.ui.uicommonweb.validation.NotEmptyValidation;
+import org.ovirt.engine.ui.uicompat.ConstantsManager;
+import org.ovirt.engine.ui.uicompat.FrontendActionAsyncResult;
+import org.ovirt.engine.ui.uicompat.IFrontendActionAsyncCallback;
+import org.ovirt.engine.ui.uicompat.UIConstants;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class CloneVmModel extends Model {
+
+    private VM vm;
+
+    private EntityModel<String> cloneName;
+
+    private EntityModel<Boolean> includeMemory;
+
+    private UIConstants constants;
+
+    private List<DiskImage> diskImages;
+
+    public CloneVmModel(VM vm, UIConstants constants) {
+        this.vm = vm;
+        this.constants = constants;
+
+        cloneName = new EntityModel<String>();
+        includeMemory = new EntityModel<Boolean>(false);
+        diskImages = new ArrayList<DiskImage>();
+    }
+
+    public void initialize() {
+        startProgress(null);
+        if (!vm.isStartingOrUp()) {
+            includeMemory.setIsChangable(false);
+            
includeMemory.setChangeProhibitionReason(constants.onlyUpVmsCanIncludeMemory());
+            includeMemory.setEntity(false);
+        } else {
+            includeMemory.setEntity(true);
+        }
+
+        initVmDisks();
+    }
+
+    private void initVmDisks() {
+        AsyncDataProvider.getVmDiskList(new AsyncQuery(this, new 
INewAsyncCallback() {
+            @Override
+            public void onSuccess(Object target, Object returnValue) {
+                CloneVmModel cloneVmModel = (CloneVmModel) target;
+                ArrayList<Disk> disks = (ArrayList<Disk>) returnValue;
+                diskImages =
+                        
Linq.toList(Linq.<DiskImage>filterDisksByStorageType(disks, 
Disk.DiskStorageType.IMAGE));
+
+                VmModelHelper.sendWarningForNonExportableDisks(cloneVmModel, 
disks, VmModelHelper.WarningType.VM_CLONE);
+                stopProgress();
+            }
+        }), vm.getId());
+    }
+
+    public EntityModel<String> getCloneName() {
+        return cloneName;
+    }
+
+    public void setCloneName(EntityModel<String> cloneName) {
+        this.cloneName = cloneName;
+    }
+
+    public EntityModel<Boolean> getIncludeMemory() {
+        return includeMemory;
+    }
+
+    public void setIncludeMemory(EntityModel<Boolean> includeMemory) {
+        this.includeMemory = includeMemory;
+    }
+
+    public VM getVm() {
+        return vm;
+    }
+
+    public List<DiskImage> getDiskImages() {
+        return diskImages;
+    }
+
+    public HashMap<Guid, DiskImage> getDiskInfoDestinationMap() {
+        final HashMap<Guid, DiskImage> diskInfoDestinationMap = new 
HashMap<Guid, DiskImage>();
+        for (Disk disk : getDiskImages()) {
+            if (disk.getDiskStorageType() == Disk.DiskStorageType.IMAGE) {
+                diskInfoDestinationMap.put(disk.getId(), (DiskImage) disk);
+            }
+        }
+
+        return diskInfoDestinationMap;
+    }
+
+    public void onClone(final Model targetModel, final boolean 
makeCreatorExplicitOwner) {
+        if (!validate()) {
+            return;
+        }
+
+        startProgress(null);
+
+        AsyncDataProvider.isVmNameUnique(new AsyncQuery(this, new 
INewAsyncCallback() {
+
+            @Override
+            public void onSuccess(Object target, Object returnValue) {
+                if ((Boolean) returnValue) {
+                    postCloneVmNameUnique(targetModel, 
makeCreatorExplicitOwner);
+                } else {
+                    stopProgress();
+                    getCloneName()
+                            .getInvalidityReasons()
+                            
.add(ConstantsManager.getInstance().getConstants().nameMustBeUniqueInvalidReason());
+                    getCloneName().setIsValid(false);
+                }
+            }
+        }), getCloneName().getEntity());
+
+    }
+
+    private void postCloneVmNameUnique(final Model targetModel, final boolean 
makeCreatorExplicitOwner) {
+        CloneVmParameters params = new CloneVmParameters(
+                getVm(),
+                getCloneName().getEntity(),
+                getDiskImages(),
+                getIncludeMemory().getEntity());
+
+        params.setDiskInfoDestinationMap(getDiskInfoDestinationMap());
+        params.setMakeCreatorExplicitOwner(makeCreatorExplicitOwner);
+
+        Frontend.getInstance().runAction(VdcActionType.CloneVm, params,
+                new IFrontendActionAsyncCallback() {
+                    @Override
+                    public void executed(FrontendActionAsyncResult result) {
+                        stopProgress();
+                        targetModel.setWindow(null);
+                    }
+                }, this);
+    }
+
+    public boolean validate() {
+        int nameLength = (AsyncDataProvider.isWindowsOsType(vm.getOs()) ? 
AsyncDataProvider.getMaxVmNameLengthWin()
+                : AsyncDataProvider.getMaxVmNameLengthNonWin());
+
+        getCloneName().validateEntity(
+                new IValidation[]{
+                        new NotEmptyValidation(),
+                        new LengthValidation(nameLength),
+                        new I18NNameValidation()
+                });
+
+        return getCloneName().getIsValid();
+    }
+}
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmListModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmListModel.java
index 02291a0..921862d 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmListModel.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmListModel.java
@@ -1,12 +1,5 @@
 package org.ovirt.engine.ui.uicommonweb.models.vms;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
 import org.ovirt.engine.core.common.VdcActionUtils;
 import org.ovirt.engine.core.common.action.AddVmFromScratchParameters;
 import org.ovirt.engine.core.common.action.AddVmFromTemplateParameters;
@@ -89,10 +82,28 @@
 import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs;
 import org.ovirt.engine.ui.uicompat.UIConstants;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
 public class VmListModel extends VmBaseListModel<VM> implements 
ISupportSystemTreeContext {
 
     private final UIConstants constants = 
ConstantsManager.getInstance().getConstants();
     public static final Version BALLOON_DEVICE_MIN_VERSION = Version.v3_2;
+
+    private UICommand cloneVmCommand;
+
+    public UICommand getCloneVmCommand() {
+        return cloneVmCommand;
+    }
+
+    public void setCloneVmCommand(UICommand cloneVmCommand) {
+        this.cloneVmCommand = cloneVmCommand;
+    }
+
     private UICommand newVMCommand;
 
     public UICommand getNewVmCommand() {
@@ -393,6 +404,7 @@
         setConsoleHelpers();
 
         setNewVmCommand(new UICommand("NewVm", this)); //$NON-NLS-1$
+        setCloneVmCommand(new UICommand("NewVm", this)); //$NON-NLS-1$
         setEditCommand(new UICommand("Edit", this)); //$NON-NLS-1$
         setRemoveCommand(new UICommand("Remove", this)); //$NON-NLS-1$
         setRunCommand(new UICommand("Run", this, true)); //$NON-NLS-1$
@@ -2259,6 +2271,7 @@
                 getSelectedItems() != null && getSelectedItem() != null ? 
getSelectedItems()
                         : new ArrayList();
 
+        getCloneVmCommand().setIsExecutionAllowed(items.size() == 1);
         
getEditCommand().setIsExecutionAllowed(isEditCommandExecutionAllowed(items));
         getRemoveCommand().setIsExecutionAllowed(items.size() > 0
                 && VdcActionUtils.canExecute(items, VM.class, 
VdcActionType.RemoveVm));
@@ -2345,7 +2358,9 @@
     {
         super.executeCommand(command);
 
-        if (command == getNewVmCommand())
+        if (command == getCloneVmCommand()) {
+            cloneVm();
+        } else if (command == getNewVmCommand())
         {
             newVm();
         }
@@ -2432,6 +2447,10 @@
         {
             preSave();
         }
+        else if (StringHelper.stringsEqual(command.getName(), "OnClone")) 
//$NON-NLS-1$
+        {
+            onClone();
+        }
         else if (StringHelper.stringsEqual(command.getName(), "OnRemove")) 
//$NON-NLS-1$
         {
             onRemove();
@@ -2487,6 +2506,34 @@
 
     }
 
+    private void cloneVm() {
+        final VM vm = (VM) getSelectedItem();
+        if (vm == null) {
+            return;
+        }
+
+        CloneVmModel model = new CloneVmModel(vm, constants);
+        setWindow(model);
+
+        model.initialize();
+        model.setTitle(ConstantsManager.getInstance()
+                .getConstants().cloneVmTitle());
+        model.setHashName("clone_vm"); //$NON-NLS-1$
+
+        UICommand okCommand = new UICommand("OnClone", this); //$NON-NLS-1$
+        okCommand.setTitle(ConstantsManager.getInstance().getConstants().ok());
+        okCommand.setIsDefault(true);
+        model.getCommands().add(okCommand);
+        UICommand cancelCommand = new UICommand("Cancel", this); //$NON-NLS-1$
+        
cancelCommand.setTitle(ConstantsManager.getInstance().getConstants().cancel());
+        cancelCommand.setIsCancel(true);
+        model.getCommands().add(cancelCommand);
+    }
+
+    private void onClone() {
+        ((CloneVmModel) getWindow()).onClone(this, false);
+    }
+
     private void connectToConsoles() {
         StringBuilder errorMessages = null;
 
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmModelHelper.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmModelHelper.java
index e85f899..304bd76 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmModelHelper.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmModelHelper.java
@@ -15,7 +15,8 @@
     public static enum WarningType {
         VM_EXPORT,
         VM_SNAPSHOT,
-        VM_TEMPLATE
+        VM_TEMPLATE,
+        VM_CLONE
     }
 
     public static void sendWarningForNonExportableDisks(Model model, 
ArrayList<Disk> vmDisks, WarningType warningType) {
@@ -46,6 +47,9 @@
             case VM_SNAPSHOT:
                 
model.setMessage(messages.noExportableDisksFoundForTheSnapshot());
                 break;
+            case VM_CLONE:
+                
model.setMessage(messages.noExportableDisksFoundForTheSnapshot());
+                break;
             case VM_TEMPLATE:
                 
model.setMessage(messages.noExportableDisksFoundForTheTemplate());
                 break;
@@ -59,6 +63,9 @@
                 
model.setMessage(messages.sharedDisksWillNotBePartOfTheExport(diskLabels));
                 break;
             case VM_SNAPSHOT:
+                
model.setMessage(messages.sharedDisksWillNotBePartOfTheSnapshot(diskLabels));
+                break;
+            case VM_CLONE:
                 
model.setMessage(messages.sharedDisksWillNotBePartOfTheSnapshot(diskLabels));
                 break;
             case VM_TEMPLATE:
@@ -76,6 +83,9 @@
             case VM_SNAPSHOT:
                 
model.setMessage(messages.directLUNDisksWillNotBePartOfTheSnapshot(diskLabels));
                 break;
+            case VM_CLONE:
+                
model.setMessage(messages.directLUNDisksWillNotBePartOfTheSnapshot(diskLabels));
+                break;
             case VM_TEMPLATE:
                 
model.setMessage(messages.directLUNDisksWillNotBePartOfTheTemplate(diskLabels));
                 break;
@@ -91,6 +101,9 @@
                 case VM_SNAPSHOT:
                     
model.setMessage(messages.snapshotDisksWillNotBePartOfTheSnapshot(diskLabels));
                     break;
+                case VM_CLONE:
+                    
model.setMessage(messages.snapshotDisksWillNotBePartOfTheSnapshot(diskLabels));
+                    break;
                 case VM_TEMPLATE:
                     
model.setMessage(messages.snapshotDisksWillNotBePartOfTheTemplate(diskLabels));
                     break;
diff --git 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
index 66e6e58..b72deb8 100644
--- 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
+++ 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIConstants.java
@@ -1,9 +1,8 @@
 package org.ovirt.engine.ui.uicompat;
 
 
-import org.ovirt.engine.core.common.businessentities.VmPool;
-
 import com.google.gwt.i18n.client.Constants;
+import org.ovirt.engine.core.common.businessentities.VmPool;
 
 public interface UIConstants extends com.google.gwt.i18n.client.Constants {
 
@@ -124,6 +123,9 @@
 
     @DefaultStringValue("Edit Virtual Machine")
     String editVmTitle();
+
+    @DefaultStringValue("Clone Virtual Machine")
+    String cloneVmTitle();
 
     // Tag
     @DefaultStringValue("Root")
@@ -2167,5 +2169,8 @@
 
     @DefaultStringValue("In case the vm is stateless, vm will be re-created 
with the LATEST template version")
     String latestTemplateVersionDescription();
+
+    @DefaultStringValue("Only available when the VM is UP or starting")
+    String onlyUpVmsCanIncludeMemory();
 }
 
diff --git 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
index a9634b0..9ad4b51 100644
--- 
a/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
+++ 
b/frontend/webadmin/modules/uicompat/src/main/java/org/ovirt/engine/ui/uicompat/UIMessages.java
@@ -111,15 +111,27 @@
     @DefaultMessage("Shared disk(s) will not be a part of the VM snapshot: 
{0}.")
     String sharedDisksWillNotBePartOfTheSnapshot(String diskList);
 
+    @DefaultMessage("Shared disk(s) will not be a part of the cloned VM: {0}.")
+    String sharedDisksWillNotBePartOfTheClone(String diskList);
+
     @DefaultMessage("Direct LUN disk(s) will not be a part of the VM snapshot: 
{0}.")
     String directLUNDisksWillNotBePartOfTheSnapshot(String diskList);
+
+    @DefaultMessage("Direct LUN disk(s) will not be a part of the cloned VM: 
{0}.")
+    String directLUNDisksWillNotBePartOfTheClone(String diskList);
 
     @DefaultMessage("Disk snapshot(s) will not be a part of the VM snapshot: 
{0}.")
     String snapshotDisksWillNotBePartOfTheSnapshot(String diskList);
 
+    @DefaultMessage("Disk snapshot(s) will not be a part of the cloned VM: 
{0}.")
+    String snapshotDisksWillNotBePartOfTheClone(String diskList);
+
     @DefaultMessage("There are no disks allowing a snapshot, only the 
configuration will be a part of the VM snapshot.")
     String noExportableDisksFoundForTheSnapshot();
 
+    @DefaultMessage("There are no disks allowing a snapshot, only the 
configuration will be a part of the cloned VM.")
+    String noExportableDisksFoundForTheClone();
+
     @DefaultMessage("Shared disk(s) will not be a part of the VM template: 
{0}.")
     String sharedDisksWillNotBePartOfTheTemplate(String diskList);
 
diff --git 
a/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/gin/PresenterModule.java
 
b/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/gin/PresenterModule.java
index 404be10..00f5a0a 100644
--- 
a/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/gin/PresenterModule.java
+++ 
b/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/gin/PresenterModule.java
@@ -12,6 +12,7 @@
 import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.permissions.PermissionsPopupPresenterWidget;
 import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.template.TemplateInterfacePopupPresenterWidget;
 import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.template.TemplateNewPopupPresenterWidget;
+import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.vm.CloneVmPopupPresenterWidget;
 import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.vm.VmChangeCDPopupPresenterWidget;
 import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.vm.VmClonePopupPresenterWidget;
 import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.vm.VmDiskPopupPresenterWidget;
@@ -58,6 +59,7 @@
 import 
org.ovirt.engine.ui.userportal.section.main.view.popup.permissions.PermissionsPopupView;
 import 
org.ovirt.engine.ui.userportal.section.main.view.popup.template.TemplateInterfacePopupView;
 import 
org.ovirt.engine.ui.userportal.section.main.view.popup.template.TemplateNewPopupView;
+import 
org.ovirt.engine.ui.userportal.section.main.view.popup.vm.CloneVmPopupView;
 import 
org.ovirt.engine.ui.userportal.section.main.view.popup.vm.VmChangeCDPopupView;
 import 
org.ovirt.engine.ui.userportal.section.main.view.popup.vm.VmClonePopupView;
 import 
org.ovirt.engine.ui.userportal.section.main.view.popup.vm.VmDiskPopupView;
@@ -267,6 +269,9 @@
         bindPresenterWidget(VmChangeCDPopupPresenterWidget.class,
                 VmChangeCDPopupPresenterWidget.ViewDef.class,
                 VmChangeCDPopupView.class);
+        bindPresenterWidget(CloneVmPopupPresenterWidget.class,
+                CloneVmPopupPresenterWidget.ViewDef.class,
+                CloneVmPopupView.class);
         bindPresenterWidget(VmMakeTemplatePopupPresenterWidget.class,
                 VmMakeTemplatePopupPresenterWidget.ViewDef.class,
                 VmMakeTemplatePopupView.class);
diff --git 
a/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/presenter/popup/vm/CloneVmPopupPresenterWidget.java
 
b/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/presenter/popup/vm/CloneVmPopupPresenterWidget.java
new file mode 100644
index 0000000..ab0e3d7
--- /dev/null
+++ 
b/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/presenter/popup/vm/CloneVmPopupPresenterWidget.java
@@ -0,0 +1,18 @@
+package org.ovirt.engine.ui.userportal.section.main.presenter.popup.vm;
+
+import com.google.gwt.event.shared.EventBus;
+import com.google.inject.Inject;
+import 
org.ovirt.engine.ui.common.presenter.AbstractModelBoundPopupPresenterWidget;
+import org.ovirt.engine.ui.uicommonweb.models.vms.CloneVmModel;
+
+public class CloneVmPopupPresenterWidget extends 
AbstractModelBoundPopupPresenterWidget<CloneVmModel, 
CloneVmPopupPresenterWidget.ViewDef> {
+
+    public interface ViewDef extends 
AbstractModelBoundPopupPresenterWidget.ViewDef<CloneVmModel> {
+    }
+
+    @Inject
+    public CloneVmPopupPresenterWidget(EventBus eventBus, ViewDef view) {
+        super(eventBus, view);
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/view/popup/vm/CloneVmPopupView.java
 
b/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/view/popup/vm/CloneVmPopupView.java
new file mode 100644
index 0000000..122939a
--- /dev/null
+++ 
b/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/view/popup/vm/CloneVmPopupView.java
@@ -0,0 +1,26 @@
+package org.ovirt.engine.ui.userportal.section.main.view.popup.vm;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.shared.EventBus;
+import com.google.inject.Inject;
+import org.ovirt.engine.ui.common.CommonApplicationConstants;
+import org.ovirt.engine.ui.common.idhandler.ElementIdHandler;
+import org.ovirt.engine.ui.common.view.popup.AbstractModelBoundWidgetPopupView;
+import org.ovirt.engine.ui.common.widget.uicommon.popup.vm.CloneVmWidget;
+import org.ovirt.engine.ui.uicommonweb.models.vms.CloneVmModel;
+import org.ovirt.engine.ui.userportal.ApplicationResources;
+import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.vm.CloneVmPopupPresenterWidget;
+
+public class CloneVmPopupView extends 
AbstractModelBoundWidgetPopupView<CloneVmModel> implements 
CloneVmPopupPresenterWidget.ViewDef {
+
+    interface ViewIdHandler extends ElementIdHandler<CloneVmPopupView> {
+        ViewIdHandler idHandler = GWT.create(ViewIdHandler.class);
+    }
+
+    @Inject
+    public CloneVmPopupView(EventBus eventBus, ApplicationResources resources, 
CommonApplicationConstants constants) {
+        super(eventBus, resources, new CloneVmWidget(constants), "400px", 
"170px"); //$NON-NLS-1$ //$NON-NLS-2$
+        ViewIdHandler.idHandler.generateAndSetIds(this);
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/view/tab/extended/SideTabExtendedVirtualMachineView.java
 
b/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/view/tab/extended/SideTabExtendedVirtualMachineView.java
index 93bff7a..b01c0f4 100644
--- 
a/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/view/tab/extended/SideTabExtendedVirtualMachineView.java
+++ 
b/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/section/main/view/tab/extended/SideTabExtendedVirtualMachineView.java
@@ -231,6 +231,12 @@
                 return getModel().getRemoveCommand();
             }
         });
+        getTable().addActionButton(new 
UserPortalButtonDefinition<UserPortalItemModel>(constants.cloneVm()) {
+            @Override
+            protected UICommand resolveCommand() {
+                return getModel().getCloneVmCommand();
+            }
+        });
         getTable().addActionButton(new 
UserPortalButtonDefinition<UserPortalItemModel>(constants.runOnceVm()) {
             @Override
             protected UICommand resolveCommand() {
diff --git 
a/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/uicommon/model/vm/UserPortalListProvider.java
 
b/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/uicommon/model/vm/UserPortalListProvider.java
index b4efb06..d34d752 100644
--- 
a/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/uicommon/model/vm/UserPortalListProvider.java
+++ 
b/frontend/webadmin/modules/userportal-gwtp/src/main/java/org/ovirt/engine/ui/userportal/uicommon/model/vm/UserPortalListProvider.java
@@ -11,6 +11,7 @@
 import org.ovirt.engine.ui.uicommonweb.models.userportal.UserPortalListModel;
 import 
org.ovirt.engine.ui.uicommonweb.models.vms.SpiceToGuestWithNonRespAgentModel;
 import org.ovirt.engine.ui.uicommonweb.models.vms.VncInfoModel;
+import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.vm.CloneVmPopupPresenterWidget;
 import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.vm.VmChangeCDPopupPresenterWidget;
 import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.vm.VmMakeTemplatePopupPresenterWidget;
 import 
org.ovirt.engine.ui.userportal.section.main.presenter.popup.vm.VmPopupPresenterWidget;
@@ -32,6 +33,7 @@
     private final Provider<VncInfoPopupPresenterWidget> vncInfoPopupProvider;
     private final Provider<ConsolePopupPresenterWidget> consolePopupProvider;
     private final Provider<DefaultConfirmationPopupPresenterWidget> 
spiceToGuestWithNonRespAgentPopupProvider;
+    private final Provider<CloneVmPopupPresenterWidget> cloneVmProvider;
 
     @Inject
     public UserPortalListProvider(EventBus eventBus,
@@ -44,7 +46,8 @@
             Provider<RemoveConfirmationPopupPresenterWidget> 
removeConfirmPopupProvider,
             Provider<VncInfoPopupPresenterWidget> vncInfoPopupProvider,
             Provider<DefaultConfirmationPopupPresenterWidget> 
spiceToGuestWithNonRespAgentPopupProvider,
-            Provider<ConsolePopupPresenterWidget> consolePopupProvider) {
+            Provider<ConsolePopupPresenterWidget> consolePopupProvider,
+            Provider<CloneVmPopupPresenterWidget> cloneVmProvider) {
         super(eventBus, defaultConfirmPopupProvider, user);
         this.newVmPopupProvider = newVmPopupProvider;
         this.runOncePopupProvider = runOncePopupProvider;
@@ -54,6 +57,7 @@
         this.vncInfoPopupProvider = vncInfoPopupProvider;
         this.consolePopupProvider = consolePopupProvider;
         this.spiceToGuestWithNonRespAgentPopupProvider = 
spiceToGuestWithNonRespAgentPopupProvider;
+        this.cloneVmProvider = cloneVmProvider;
     }
 
     @Override
@@ -80,6 +84,8 @@
             return spiceToGuestWithNonRespAgentPopupProvider.get();
         } else if (lastExecutedCommand == getModel().getEditConsoleCommand()) {
             return consolePopupProvider.get();
+        } else if (lastExecutedCommand == getModel().getCloneVmCommand()) {
+            return cloneVmProvider.get();
         }
         else {
             return super.getModelPopup(source, lastExecutedCommand, 
windowModel);
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java
index 34d6622..7b63d22 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/PresenterModule.java
@@ -90,6 +90,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.template.TemplateInterfacePopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.template.TemplateNewPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.user.ManageEventsPopupPresenterWidget;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.vm.CloneVmPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.vm.VmChangeCDPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.vm.VmClonePopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.vm.VmDiskPopupPresenterWidget;
@@ -309,6 +310,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.template.TemplateInterfacePopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.template.TemplateNewPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.user.ManageEventsPopupView;
+import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.vm.CloneVmPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.vm.VmChangeCDPopupView;
 import 
org.ovirt.engine.ui.webadmin.section.main.view.popup.vm.VmClonePopupView;
 import org.ovirt.engine.ui.webadmin.section.main.view.popup.vm.VmDiskPopupView;
@@ -1220,6 +1222,11 @@
                 VmChangeCDPopupPresenterWidget.ViewDef.class,
                 VmChangeCDPopupView.class);
 
+        // Clone VM
+        bindPresenterWidget(CloneVmPopupPresenterWidget.class,
+                CloneVmPopupPresenterWidget.ViewDef.class,
+                CloneVmPopupView.class);
+
         // VM Migrate
         bindPresenterWidget(VmMigratePopupPresenterWidget.class,
                 VmMigratePopupPresenterWidget.ViewDef.class,
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VirtualMachineModule.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VirtualMachineModule.java
index 37321d8..d9e4ae6 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VirtualMachineModule.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/gin/uicommon/VirtualMachineModule.java
@@ -42,6 +42,7 @@
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.quota.ChangeQuotaPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.scheduling.AffinityGroupPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.storage.DisksAllocationPopupPresenterWidget;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.vm.CloneVmPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.vm.VmChangeCDPopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.vm.VmClonePopupPresenterWidget;
 import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.vm.VmDiskPopupPresenterWidget;
@@ -85,7 +86,8 @@
             final Provider<VmRemovePopupPresenterWidget> 
vmRemoveConfirmPopupProvider,
             final Provider<ReportPresenterWidget> reportWindowProvider,
             final Provider<ConsolePopupPresenterWidget> consolePopupProvider,
-            final Provider<VncInfoPopupPresenterWidget> vncWindoProvider) {
+            final Provider<VncInfoPopupPresenterWidget> vncWindoProvider,
+            final Provider<CloneVmPopupPresenterWidget> cloneVmProvider) {
         return new MainTabModelProvider<VM, VmListModel>(eventBus, 
defaultConfirmPopupProvider, VmListModel.class) {
             @Override
             public AbstractModelBoundPopupPresenterWidget<? extends Model, ?> 
getModelPopup(VmListModel source,
@@ -114,6 +116,8 @@
                     return vncWindoProvider.get();
                 } else if (lastExecutedCommand == 
getModel().getEditConsoleCommand()) {
                     return consolePopupProvider.get();
+                } else if (lastExecutedCommand == 
getModel().getCloneVmCommand()) {
+                    return cloneVmProvider.get();
                 }
                 else {
                     return super.getModelPopup(source, lastExecutedCommand, 
windowModel);
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/vm/CloneVmPopupPresenterWidget.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/vm/CloneVmPopupPresenterWidget.java
new file mode 100644
index 0000000..f31d2ce
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/vm/CloneVmPopupPresenterWidget.java
@@ -0,0 +1,18 @@
+package org.ovirt.engine.ui.webadmin.section.main.presenter.popup.vm;
+
+import com.google.gwt.event.shared.EventBus;
+import com.google.inject.Inject;
+import 
org.ovirt.engine.ui.common.presenter.AbstractModelBoundPopupPresenterWidget;
+import org.ovirt.engine.ui.uicommonweb.models.vms.CloneVmModel;
+
+public class CloneVmPopupPresenterWidget extends 
AbstractModelBoundPopupPresenterWidget<CloneVmModel, 
CloneVmPopupPresenterWidget.ViewDef> {
+
+    public interface ViewDef extends 
AbstractModelBoundPopupPresenterWidget.ViewDef<CloneVmModel> {
+    }
+
+    @Inject
+    public CloneVmPopupPresenterWidget(EventBus eventBus, ViewDef view) {
+        super(eventBus, view);
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/vm/CloneVmPopupView.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/vm/CloneVmPopupView.java
new file mode 100644
index 0000000..92a21e4
--- /dev/null
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/vm/CloneVmPopupView.java
@@ -0,0 +1,26 @@
+package org.ovirt.engine.ui.webadmin.section.main.view.popup.vm;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.shared.EventBus;
+import com.google.inject.Inject;
+import org.ovirt.engine.ui.common.CommonApplicationConstants;
+import org.ovirt.engine.ui.common.idhandler.ElementIdHandler;
+import org.ovirt.engine.ui.common.view.popup.AbstractModelBoundWidgetPopupView;
+import org.ovirt.engine.ui.common.widget.uicommon.popup.vm.CloneVmWidget;
+import org.ovirt.engine.ui.uicommonweb.models.vms.CloneVmModel;
+import org.ovirt.engine.ui.webadmin.ApplicationResources;
+import 
org.ovirt.engine.ui.webadmin.section.main.presenter.popup.vm.CloneVmPopupPresenterWidget;
+
+public class CloneVmPopupView extends 
AbstractModelBoundWidgetPopupView<CloneVmModel> implements 
CloneVmPopupPresenterWidget.ViewDef {
+
+    interface ViewIdHandler extends ElementIdHandler<CloneVmPopupView> {
+        ViewIdHandler idHandler = GWT.create(ViewIdHandler.class);
+    }
+
+    @Inject
+    public CloneVmPopupView(EventBus eventBus, ApplicationResources resources, 
CommonApplicationConstants constants) {
+        super(eventBus, resources, new CloneVmWidget(constants), "400px", 
"170px"); //$NON-NLS-1$ //$NON-NLS-2$
+        ViewIdHandler.idHandler.generateAndSetIds(this);
+    }
+
+}
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVirtualMachineView.java
 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVirtualMachineView.java
index 08c11c5..9b73883 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVirtualMachineView.java
+++ 
b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVirtualMachineView.java
@@ -191,6 +191,13 @@
                 return getMainModel().getRemoveCommand();
             }
         });
+        getTable().addActionButton(new 
WebAdminButtonDefinition<VM>(constants.cloneVm()) {
+
+            @Override
+            protected UICommand resolveCommand() {
+                return getMainModel().getCloneVmCommand();
+            }
+        });
         // TODO: separator
         getTable().addActionButton(new 
WebAdminButtonDefinition<VM>(constants.runOnceVm()) {
             @Override


-- 
To view, visit http://gerrit.ovirt.org/23806
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6ae2bca7ce33412da3881ccadc9bb1543e32ace2
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Tomas Jelinek <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to