Vinzenz Feenstra has uploaded a new change for review.

Change subject: WIP: Allow to avoid lock screen on spice disconnect
......................................................................

WIP: Allow to avoid lock screen on spice disconnect

Change-Id: Ia2ef5ffaceed619f6630b56a7156f25e9111fd9e
Bug-Url: https://bugzilla.redhat.com/758516
Signed-off-by: Vinzenz Feenstra <vfeen...@redhat.com>
---
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SetVmTicketCommand.java
A 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ConsoleDisconnectAction.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VM.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmStatic.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/SetVmTicketVDSCommandParameters.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmStaticDAODbFacadeImpl.java
M 
backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmStaticDAOTest.java
M 
backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/SetVmTicketVDSCommand.java
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.java
M 
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.ui.xml
M 
frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/UnitVmModel.java
M packaging/dbscripts/create_tables.sql
M packaging/dbscripts/create_views.sql
A 
packaging/dbscripts/upgrade/03_06_0410_add_vm_static_console_disconnect_action.sql
15 files changed, 92 insertions(+), 8 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/79/34079/1

diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SetVmTicketCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SetVmTicketCommand.java
index d7da3a0..2fed7a7 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SetVmTicketCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SetVmTicketCommand.java
@@ -196,7 +196,7 @@
         final DbUser user = getCurrentUser();
         final boolean sent =
                 runVdsCommand(VDSCommandType.SetVmTicket,
-                    new SetVmTicketVDSCommandParameters(getVdsId(), getVmId(), 
mTicket, mValidTime, user.getLoginName(), user.getId())).getSucceeded();
+                    new SetVmTicketVDSCommandParameters(getVdsId(), getVmId(), 
mTicket, mValidTime, user.getLoginName(), user.getId(), 
getVm().getConsoleDisconnectAction())).getSucceeded();
 
         // Return the ticket only if sending it to the virtual machine 
succeeded:
         if (sent) {
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ConsoleDisconnectAction.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ConsoleDisconnectAction.java
new file mode 100644
index 0000000..52023b5
--- /dev/null
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ConsoleDisconnectAction.java
@@ -0,0 +1,16 @@
+package org.ovirt.engine.core.common.businessentities;
+
+public enum ConsoleDisconnectAction {
+    NONE,
+    LOCK_SCREEN,
+    LOGOUT,
+    SHUTDOWN,
+    REBOOT;
+
+    public static ConsoleDisconnectAction fromDbString(String name) {
+        if(name == null) {
+            return LOCK_SCREEN;
+        }
+        return ConsoleDisconnectAction.valueOf(name);
+    }
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VM.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VM.java
index 8f3694c..638a813 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VM.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VM.java
@@ -1850,4 +1850,12 @@
     public void setCpuProfileId(Guid cpuProfileId) {
         vmStatic.setCpuProfileId(cpuProfileId);
     }
+    public ConsoleDisconnectAction getConsoleDisconnectAction() {
+        return vmStatic.getConsoleDisconnectAction();
+    }
+
+    public void setConsoleDisconnectAction(ConsoleDisconnectAction 
consoleDisconnectAction) {
+        vmStatic.setConsoleDisconnectAction(consoleDisconnectAction);
+    }
+
 }
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmStatic.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmStatic.java
index cbb9262..8b91e0c 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmStatic.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmStatic.java
@@ -50,6 +50,17 @@
     @EditableField
     private boolean useLatestVersion;
 
+    @EditableField
+    private ConsoleDisconnectAction consoleDisconnectAction;
+
+    public ConsoleDisconnectAction getConsoleDisconnectAction() {
+        return consoleDisconnectAction;
+    }
+
+    public void setConsoleDisconnectAction(ConsoleDisconnectAction 
consoleDisconnectAction) {
+        this.consoleDisconnectAction = consoleDisconnectAction;
+    }
+
     public VmStatic() {
         setNumOfMonitors(1);
         initialized = false;
@@ -57,6 +68,7 @@
         setCpuShares(0);
         setDefaultBootSequence(BootSequence.C);
         setDefaultDisplayType(DisplayType.qxl);
+        setConsoleDisconnectAction(ConsoleDisconnectAction.LOCK_SCREEN);
         setVmType(VmType.Desktop);
         vmtGuid = Guid.Empty;
         customProperties = "";
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/SetVmTicketVDSCommandParameters.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/SetVmTicketVDSCommandParameters.java
index 6851320..77aee81 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/SetVmTicketVDSCommandParameters.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/vdscommands/SetVmTicketVDSCommandParameters.java
@@ -1,5 +1,6 @@
 package org.ovirt.engine.core.common.vdscommands;
 
+import org.ovirt.engine.core.common.businessentities.ConsoleDisconnectAction;
 import org.ovirt.engine.core.compat.Guid;
 
 public class SetVmTicketVDSCommandParameters extends 
VdsAndVmIDVDSParametersBase {
@@ -7,13 +8,15 @@
     private int validTime;
     private String userName;
     private Guid userId;
+    private ConsoleDisconnectAction disconnectAction;
 
-    public SetVmTicketVDSCommandParameters(Guid vdsId, Guid vmId, String 
ticket, int validTime, String userName, Guid userId) {
+    public SetVmTicketVDSCommandParameters(Guid vdsId, Guid vmId, String 
ticket, int validTime, String userName, Guid userId, ConsoleDisconnectAction 
disconnectAction) {
         super(vdsId, vmId);
         this.ticket = ticket;
         this.validTime = validTime;
         this.userName = userName;
         this.userId = userId;
+        this.disconnectAction = disconnectAction;
     }
 
     public String getTicket() {
@@ -32,6 +35,10 @@
         return userName;
     }
 
+    public String getDisconnectAction() {
+        return disconnectAction.name();
+    }
+
     public SetVmTicketVDSCommandParameters() {
     }
 
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmStaticDAODbFacadeImpl.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmStaticDAODbFacadeImpl.java
index 375217b..3f80498 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmStaticDAODbFacadeImpl.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmStaticDAODbFacadeImpl.java
@@ -6,6 +6,7 @@
 
 import org.apache.commons.lang.NotImplementedException;
 import org.apache.commons.lang.StringUtils;
+import org.ovirt.engine.core.common.businessentities.ConsoleDisconnectAction;
 import org.ovirt.engine.core.common.businessentities.VmStatic;
 import org.ovirt.engine.core.common.utils.customprop.VmPropertiesUtils;
 import org.ovirt.engine.core.compat.Guid;
@@ -42,7 +43,8 @@
                 .addValue("original_template_name", 
vm.getOriginalTemplateName())
                 .addValue("original_template_id", vm.getOriginalTemplateGuid())
                 .addValue("template_version_number", vm.isUseLatestVersion() ?
-                        USE_LATEST_VERSION_NUMBER_INDICATOR : 
DONT_USE_LATEST_VERSION_NUMBER_INDICATOR);
+                        USE_LATEST_VERSION_NUMBER_INDICATOR : 
DONT_USE_LATEST_VERSION_NUMBER_INDICATOR)
+                .addValue("console_disconnect_action", 
vm.getConsoleDisconnectAction().toString());
     }
 
     @Override
@@ -186,7 +188,7 @@
             entity.setOriginalTemplateGuid(getGuid(rs, 
"original_template_id"));
             // if template_version_number is null it means use latest version
             entity.setUseLatestVersion(rs.getObject("template_version_number") 
== USE_LATEST_VERSION_NUMBER_INDICATOR);
-
+            
entity.setConsoleDisconnectAction(ConsoleDisconnectAction.fromDbString(rs.getString("console_disconnect_action")));
             return entity;
         }
     }
diff --git 
a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmStaticDAOTest.java
 
b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmStaticDAOTest.java
index 933119d..2cafbe2 100644
--- 
a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmStaticDAOTest.java
+++ 
b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmStaticDAOTest.java
@@ -14,6 +14,7 @@
 
 import org.apache.commons.lang.NotImplementedException;
 import org.junit.Test;
+import org.ovirt.engine.core.common.businessentities.ConsoleDisconnectAction;
 import org.ovirt.engine.core.common.businessentities.MigrationSupport;
 import org.ovirt.engine.core.common.businessentities.OriginType;
 import org.ovirt.engine.core.common.businessentities.Snapshot;
@@ -56,6 +57,7 @@
         newVmStatic.setOrigin(OriginType.OVIRT);
         newVmStatic.setQuotaId(QUOTA_ID);
         newVmStatic.setCpuProfileId(FixturesTool.CPU_PROFILE_1);
+        newVmStatic.setConsoleDisconnectAction(ConsoleDisconnectAction.REBOOT);
     }
 
     /**
@@ -446,4 +448,12 @@
         }
         assertEquals(isAllNull, allValues);
     }
+
+    @Test
+    public void testConsoleDisconnectAction() {
+        List<VmStatic> vmStatics = dao.getAllByName(STATIC_VM_NAME);
+        for(VmStatic vmStatic : vmStatics) {
+            assertEquals(vmStatic.getConsoleDisconnectAction(), 
ConsoleDisconnectAction.REBOOT);
+        }
+    }
 }
diff --git 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/SetVmTicketVDSCommand.java
 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/SetVmTicketVDSCommand.java
index db5e202..c87aeaf 100644
--- 
a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/SetVmTicketVDSCommand.java
+++ 
b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/SetVmTicketVDSCommand.java
@@ -14,6 +14,7 @@
     private String mTicket;
     private int mValidTime; // in seconds
     private String connectionAction = "disconnect";
+    private String mConsoleDisconnectAction;
 
     public SetVmTicketVDSCommand(P parameters) {
         super(parameters, 
DbFacade.getInstance().getVdsDao().get(parameters.getVdsId()));
@@ -29,6 +30,7 @@
             Map<String, String> params = new HashMap<String, String>();
             params.put("userName", getParameters().getUserName());
             params.put("userId", getParameters().getUserId().toString());
+            params.put("disconnectAction", 
getParameters().getDisconnectAction());
             status = getBroker().setVmTicket(mVmId.toString(), mTicket, 
String.valueOf(mValidTime),
                     connectionAction, params);
         }
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.java
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.java
index c515718..b787d8f 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.java
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.java
@@ -10,6 +10,7 @@
 import java.util.Map;
 
 import org.ovirt.engine.core.common.businessentities.BootSequence;
+import org.ovirt.engine.core.common.businessentities.ConsoleDisconnectAction;
 import org.ovirt.engine.core.common.businessentities.Disk;
 import org.ovirt.engine.core.common.businessentities.Disk.DiskStorageType;
 import org.ovirt.engine.core.common.businessentities.DiskImage;
@@ -455,6 +456,11 @@
     public ListModelListBoxEditor<UsbPolicy> usbSupportEditor;
 
     @UiField(provided = true)
+    @Path(value = "disconnectPolicy.selectedItem")
+    @WithElementId("disconnectPolicy")
+    public ListModelListBoxEditor<ConsoleDisconnectAction> 
disconnectPolicyEditor;
+
+    @UiField(provided = true)
     @Path(value = "numOfMonitors.selectedItem")
     @WithElementId("numOfMonitors")
     public ListModelListBoxEditor<Integer> numOfMonitorsEditor;
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.ui.xml
 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.ui.xml
index cea7939..7fe4f9f 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.ui.xml
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/uicommon/popup/AbstractVmPopupWidget.ui.xml
@@ -552,6 +552,7 @@
                         <e:ListModelListBoxEditor 
ui:field="displayProtocolEditor" />
                         <e:ListModelListBoxEditor 
ui:field="vncKeyboardLayoutEditor" />
                         <e:ListModelListBoxEditor ui:field="usbSupportEditor" 
/>
+                        <e:ListModelListBoxEditor 
ui:field="disconnectPolicyEditor" />
                         <g:FlowPanel width="100%">
                               <g:FlowPanel 
addStyleNames="{style.monitorPanel}">
                                  <g:HorizontalPanel verticalAlignment="middle">
diff --git 
a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml
 
b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml
index 65bbc08..645793c 100644
--- 
a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml
+++ 
b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml
@@ -28,6 +28,7 @@
                <include name="common/businessentities/AuditLog.java" />
                <include name="common/businessentities/Bookmark.java" />
                <include name="common/businessentities/BaseDisk.java" />
+               <include 
name="common/businessentities/ConsoleDisconnectAction.java" />
                <include name="common/businessentities/CommandEntity.java" />
                <include name="common/businessentities/DiskLunMap.java" />
                <include name="common/businessentities/DiskLunMapId.java" />
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/UnitVmModel.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/UnitVmModel.java
index 8b35ed4..1d6df6e 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/UnitVmModel.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/UnitVmModel.java
@@ -11,6 +11,7 @@
 import java.util.Set;
 
 import org.ovirt.engine.core.common.businessentities.BootSequence;
+import org.ovirt.engine.core.common.businessentities.ConsoleDisconnectAction;
 import org.ovirt.engine.core.common.businessentities.DisplayType;
 import org.ovirt.engine.core.common.businessentities.InstanceType;
 import org.ovirt.engine.core.common.businessentities.MigrationSupport;
@@ -232,6 +233,7 @@
             // ==Console Tab==
             getDisplayProtocol().setIsChangable(false);
             getUsbPolicy().setIsChangable(false);
+            getConsoleDisconnectAction().setIsChangable(false);
             getNumOfMonitors().setIsChangable(false);
             getIsSingleQxlEnabled().setIsChangable(false);
             getIsSmartcardEnabled().setIsChangable(false);
@@ -570,6 +572,18 @@
         privateUsbPolicy = value;
     }
 
+    private NotChangableForVmInPoolListModel<ConsoleDisconnectAction> 
privateConsoleDisconnectAction;
+
+    public ListModel<ConsoleDisconnectAction> getConsoleDisconnectAction()
+    {
+        return privateConsoleDisconnectAction;
+    }
+
+    public void 
setPrivateConsoleDisconnectAction(NotChangableForVmInPoolListModel<ConsoleDisconnectAction>
 value)
+    {
+        privateConsoleDisconnectAction = value;
+    }
+
     private NotChangableForVmInPoolListModel<TimeZoneModel> privateTimeZone;
 
     public ListModel<TimeZoneModel> getTimeZone()
diff --git a/packaging/dbscripts/create_tables.sql 
b/packaging/dbscripts/create_tables.sql
index 04ce154..ce5d816 100644
--- a/packaging/dbscripts/create_tables.sql
+++ b/packaging/dbscripts/create_tables.sql
@@ -1226,7 +1226,8 @@
     host_cpu_flags boolean DEFAULT false,
     db_generation bigint DEFAULT 1,
     is_delete_protected boolean DEFAULT false,
-    is_disabled boolean DEFAULT false
+    is_disabled boolean DEFAULT false,
+    console_disconnect_action character varying(64)
 );
 
 
diff --git a/packaging/dbscripts/create_views.sql 
b/packaging/dbscripts/create_views.sql
index 60d9a16..6f2e79f 100644
--- a/packaging/dbscripts/create_views.sql
+++ b/packaging/dbscripts/create_views.sql
@@ -447,7 +447,8 @@
        vm_templates.is_spice_file_transfer_enabled as 
is_spice_file_transfer_enabled,
        vm_templates.is_spice_copy_paste_enabled as is_spice_copy_paste_enabled,
        vm_templates.cpu_profile_id as cpu_profile_id,
-       vm_templates.numatune_mode as numatune_mode
+       vm_templates.numatune_mode as numatune_mode,
+       vm_templates.console_disconnect_action as console_disconnect_action
 FROM       vm_static AS vm_templates  LEFT OUTER JOIN
 vds_groups ON vm_templates.vds_group_id = vds_groups.vds_group_id
 left outer JOIN
@@ -667,7 +668,8 @@
                       (snapshots.snapshot_id is not null) as 
next_run_config_exists,
                       vm_static.numatune_mode as numatune_mode,
                       vm_static.is_spice_file_transfer_enabled as 
is_spice_file_transfer_enabled, vm_static.is_spice_copy_paste_enabled as 
is_spice_copy_paste_enabled,
-                      vm_static.cpu_profile_id as cpu_profile_id
+                      vm_static.cpu_profile_id as cpu_profile_id,
+                      vm_static.console_disconnect_action as 
console_disconnect_action
 FROM         vm_static INNER JOIN
 vm_dynamic ON vm_static.vm_guid = vm_dynamic.vm_guid INNER JOIN
 vm_static AS vm_templates ON vm_static.vmt_guid = vm_templates.vm_guid INNER 
JOIN
@@ -715,7 +717,8 @@
             (snapshots.snapshot_id is not null) as next_run_config_exists,
             vms.numatune_mode,
             vms.is_spice_file_transfer_enabled, 
vms.is_spice_copy_paste_enabled,
-            vms.cpu_profile_id
+            vms.cpu_profile_id,
+            vms.console_disconnect_action
 FROM        vms LEFT OUTER JOIN
             tags_vm_map_view ON vms.vm_guid = tags_vm_map_view.vm_id LEFT 
OUTER JOIN
             vm_device ON vm_device.vm_id = vms.vm_guid LEFT OUTER JOIN
diff --git 
a/packaging/dbscripts/upgrade/03_06_0410_add_vm_static_console_disconnect_action.sql
 
b/packaging/dbscripts/upgrade/03_06_0410_add_vm_static_console_disconnect_action.sql
new file mode 100644
index 0000000..4a003b6
--- /dev/null
+++ 
b/packaging/dbscripts/upgrade/03_06_0410_add_vm_static_console_disconnect_action.sql
@@ -0,0 +1 @@
+select fn_db_add_column('vm_static', 'console_disconnect_action', 
'VARCHAR(64)');
\ No newline at end of file


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia2ef5ffaceed619f6630b56a7156f25e9111fd9e
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Vinzenz Feenstra <vfeen...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to