Merge branch 'master' into 'master'

operation timeout feature

See merge request entgra/carbon-device-mgt!838
merge-requests/837/merge
Pahansith Gunathilake 3 years ago
commit ff1438ac09

@ -154,4 +154,6 @@ public interface OperationManager {
*/ */
boolean isOperationExist(DeviceIdentifier deviceId, int operationId) throws OperationManagementException; boolean isOperationExist(DeviceIdentifier deviceId, int operationId) throws OperationManagementException;
List<Activity> getActivities(List<String> deviceTypes, String operationCode, long updatedSince, String operationStatus)
throws OperationManagementException;
} }

@ -24,6 +24,7 @@ import org.wso2.carbon.device.mgt.core.config.archival.ArchivalConfiguration;
import org.wso2.carbon.device.mgt.core.config.cache.CertificateCacheConfiguration; import org.wso2.carbon.device.mgt.core.config.cache.CertificateCacheConfiguration;
import org.wso2.carbon.device.mgt.core.config.cache.DeviceCacheConfiguration; import org.wso2.carbon.device.mgt.core.config.cache.DeviceCacheConfiguration;
import org.wso2.carbon.device.mgt.core.config.cache.GeoFenceCacheConfiguration; import org.wso2.carbon.device.mgt.core.config.cache.GeoFenceCacheConfiguration;
import org.wso2.carbon.device.mgt.core.config.operation.timeout.OperationTimeoutConfiguration;
import org.wso2.carbon.device.mgt.core.event.config.EventOperationTaskConfiguration; import org.wso2.carbon.device.mgt.core.event.config.EventOperationTaskConfiguration;
import org.wso2.carbon.device.mgt.core.config.geo.location.GeoLocationConfiguration; import org.wso2.carbon.device.mgt.core.config.geo.location.GeoLocationConfiguration;
import org.wso2.carbon.device.mgt.core.config.identity.IdentityConfigurations; import org.wso2.carbon.device.mgt.core.config.identity.IdentityConfigurations;
@ -66,6 +67,7 @@ public final class DeviceManagementConfig {
private ArchivalConfiguration archivalConfiguration; private ArchivalConfiguration archivalConfiguration;
private EnrollmentNotificationConfiguration enrollmentNotificationConfiguration; private EnrollmentNotificationConfiguration enrollmentNotificationConfiguration;
private DefaultRoles defaultRoles; private DefaultRoles defaultRoles;
private OperationTimeoutConfiguration operationTimeoutConfiguration;
@XmlElement(name = "ManagementRepository", required = true) @XmlElement(name = "ManagementRepository", required = true)
public DeviceManagementConfigRepository getDeviceManagementConfigRepository() { public DeviceManagementConfigRepository getDeviceManagementConfigRepository() {
@ -243,5 +245,14 @@ public final class DeviceManagementConfig {
public DefaultRoles getDefaultRoles() { return defaultRoles; } public DefaultRoles getDefaultRoles() { return defaultRoles; }
public void setDefaultRoles(DefaultRoles defaultRoles) { this.defaultRoles = defaultRoles; } public void setDefaultRoles(DefaultRoles defaultRoles) { this.defaultRoles = defaultRoles; }
@XmlElement(name = "OperationTimeoutConfigurations", required = true)
public OperationTimeoutConfiguration getOperationTimeoutConfiguration() {
return operationTimeoutConfiguration;
}
public void setOperationTimeoutConfiguration(OperationTimeoutConfiguration operationTimeoutConfiguration) {
this.operationTimeoutConfiguration = operationTimeoutConfiguration;
}
} }

@ -0,0 +1,79 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.config.operation.timeout;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@XmlRootElement(name = "OperationTimeout")
public class OperationTimeout {
private String code;
private int timeout;
private List<String> deviceTypes;
private String initialStatus;
private String nextStatus;
public String getCode() {
return code;
}
@XmlElement(name = "Code", required = true)
public void setCode(String code) {
this.code = code;
}
public int getTimeout() {
return timeout;
}
@XmlElement(name = "Timeout", required = true)
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public List<String> getDeviceTypes() {
return deviceTypes;
}
@XmlElementWrapper(name = "DeviceTypes", required = true)
@XmlElement(name = "DeviceType", required = true)
public void setDeviceTypes(List<String> deviceTypes) {
this.deviceTypes = deviceTypes;
}
public String getInitialStatus() {
return initialStatus;
}
@XmlElement(name = "InitialStatus", required = true)
public void setInitialStatus(String initialStatus) {
this.initialStatus = initialStatus;
}
public String getNextStatus() {
return nextStatus;
}
@XmlElement(name = "NextStatus", required = true)
public void setNextStatus(String nextStatus) {
this.nextStatus = nextStatus;
}
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.config.operation.timeout;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@XmlRootElement(name = "OperationTimeoutConfigurations")
public class OperationTimeoutConfiguration {
private List<OperationTimeout> operationTimeoutList;
public List<OperationTimeout> getOperationTimeoutList() {
return operationTimeoutList;
}
@XmlElementWrapper(name = "OperationTimeouts", required = true)
@XmlElement(name = "OperationTimeout", required = false)
public void setOperationTimeoutList(List<OperationTimeout> operationTimeoutList) {
this.operationTimeoutList = operationTimeoutList;
}
}

@ -34,6 +34,7 @@ import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManag
import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.dto.DeviceTypeServiceIdentifier; import org.wso2.carbon.device.mgt.core.dto.DeviceTypeServiceIdentifier;
import org.wso2.carbon.device.mgt.core.geo.task.GeoFenceEventOperationManager; import org.wso2.carbon.device.mgt.core.geo.task.GeoFenceEventOperationManager;
import org.wso2.carbon.device.mgt.core.operation.timeout.task.OperationTimeoutTaskManagerService;
import org.wso2.carbon.device.mgt.core.privacy.PrivacyComplianceProvider; import org.wso2.carbon.device.mgt.core.privacy.PrivacyComplianceProvider;
import org.wso2.carbon.device.mgt.core.push.notification.mgt.PushNotificationProviderRepository; import org.wso2.carbon.device.mgt.core.push.notification.mgt.PushNotificationProviderRepository;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
@ -81,6 +82,7 @@ public class DeviceManagementDataHolder {
private GeoLocationProviderService geoLocationProviderService; private GeoLocationProviderService geoLocationProviderService;
private GeoFenceEventOperationManager geoFenceEventOperationManager; private GeoFenceEventOperationManager geoFenceEventOperationManager;
private ExecutorService eventConfigExecutors; private ExecutorService eventConfigExecutors;
private OperationTimeoutTaskManagerService operationTimeoutTaskManagerService;
private final Map<DeviceType, DeviceStatusTaskPluginConfig> deviceStatusTaskPluginConfigs = Collections.synchronizedMap( private final Map<DeviceType, DeviceStatusTaskPluginConfig> deviceStatusTaskPluginConfigs = Collections.synchronizedMap(
new HashMap<>()); new HashMap<>());
@ -338,4 +340,13 @@ public class DeviceManagementDataHolder {
public void setEventConfigExecutors(ExecutorService eventConfigExecutors) { public void setEventConfigExecutors(ExecutorService eventConfigExecutors) {
this.eventConfigExecutors = eventConfigExecutors; this.eventConfigExecutors = eventConfigExecutors;
} }
public OperationTimeoutTaskManagerService getOperationTimeoutTaskManagerService() {
return operationTimeoutTaskManagerService;
}
public void setOperationTimeoutTaskManagerService(
OperationTimeoutTaskManagerService operationTimeoutTaskManagerService) {
this.operationTimeoutTaskManagerService = operationTimeoutTaskManagerService;
}
} }

@ -26,7 +26,12 @@ import org.wso2.carbon.device.mgt.common.DeviceStatusTaskPluginConfig;
import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig; import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig;
import org.wso2.carbon.device.mgt.core.config.operation.timeout.OperationTimeout;
import org.wso2.carbon.device.mgt.core.config.operation.timeout.OperationTimeoutConfiguration;
import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.operation.timeout.task.OperationTimeoutTaskException;
import org.wso2.carbon.device.mgt.core.operation.timeout.task.OperationTimeoutTaskManagerService;
import org.wso2.carbon.device.mgt.core.operation.timeout.task.impl.OperationTimeoutTaskManagerServiceImpl;
import org.wso2.carbon.device.mgt.core.status.task.DeviceStatusTaskException; import org.wso2.carbon.device.mgt.core.status.task.DeviceStatusTaskException;
import org.wso2.carbon.device.mgt.core.status.task.DeviceStatusTaskManagerService; import org.wso2.carbon.device.mgt.core.status.task.DeviceStatusTaskManagerService;
import org.wso2.carbon.device.mgt.core.status.task.impl.DeviceStatusTaskManagerServiceImpl; import org.wso2.carbon.device.mgt.core.status.task.impl.DeviceStatusTaskManagerServiceImpl;
@ -66,6 +71,10 @@ public class DeviceTaskManagerServiceComponent {
if (deviceManagementConfig != null && deviceManagementConfig.getDeviceStatusTaskConfig().isEnabled()) { if (deviceManagementConfig != null && deviceManagementConfig.getDeviceStatusTaskConfig().isEnabled()) {
startDeviceStatusMonitoringTask(componentContext.getBundleContext()); startDeviceStatusMonitoringTask(componentContext.getBundleContext());
} }
if (deviceManagementConfig != null && deviceManagementConfig.getOperationTimeoutConfiguration() != null) {
startOperationTimeoutTask(componentContext.getBundleContext());
}
} catch (Throwable e) { } catch (Throwable e) {
log.error("Error occurred while initializing device task manager service.", e); log.error("Error occurred while initializing device task manager service.", e);
} }
@ -102,6 +111,27 @@ public class DeviceTaskManagerServiceComponent {
} }
} }
private void startOperationTimeoutTask(BundleContext bundleContext) {
OperationTimeoutTaskManagerService operationTimeoutTaskManagerService =
new OperationTimeoutTaskManagerServiceImpl();
DeviceManagementDataHolder.getInstance().setOperationTimeoutTaskManagerService(
operationTimeoutTaskManagerService);
bundleContext.registerService(OperationTimeoutTaskManagerService.class,
operationTimeoutTaskManagerService, null);
OperationTimeoutConfiguration configuration = deviceManagementConfig.getOperationTimeoutConfiguration();
for (OperationTimeout operationTimeout : configuration.getOperationTimeoutList()) {
try {
operationTimeoutTaskManagerService.startTask(operationTimeout);
} catch (OperationTimeoutTaskException e) {
log.error("Error while starting the operation timeout task for device type (s) : "
+ operationTimeout.getDeviceTypes() + ", operation code : "
+ operationTimeout.getInitialStatus());
}
}
}
@SuppressWarnings("unused") @SuppressWarnings("unused")
protected void deactivate(ComponentContext componentContext) { protected void deactivate(ComponentContext componentContext) {
try { try {
@ -109,6 +139,9 @@ public class DeviceTaskManagerServiceComponent {
if (deviceManagementConfig != null && deviceManagementConfig.getDeviceStatusTaskConfig().isEnabled()) { if (deviceManagementConfig != null && deviceManagementConfig.getDeviceStatusTaskConfig().isEnabled()) {
stopDeviceStatusMonitoringTask(); stopDeviceStatusMonitoringTask();
} }
if (deviceManagementConfig != null && deviceManagementConfig.getOperationTimeoutConfiguration() != null) {
stopOperationTimeoutTask();
}
} catch (Throwable e) { } catch (Throwable e) {
log.error("Error occurred while shutting down device task manager service.", e); log.error("Error occurred while shutting down device task manager service.", e);
} }
@ -143,6 +176,22 @@ public class DeviceTaskManagerServiceComponent {
} }
} }
private void stopOperationTimeoutTask() {
OperationTimeoutTaskManagerService operationTimeoutTaskManagerService =
DeviceManagementDataHolder.getInstance().getOperationTimeoutTaskManagerService();
OperationTimeoutConfiguration configuration = deviceManagementConfig.getOperationTimeoutConfiguration();
for (OperationTimeout operationTimeout : configuration.getOperationTimeoutList()) {
try {
operationTimeoutTaskManagerService.stopTask(operationTimeout);
} catch (OperationTimeoutTaskException e) {
log.error("Error while stopping the operation timeout task for device type (s) : "
+ operationTimeout.getDeviceTypes() + ", operation code : "
+ operationTimeout.getInitialStatus());
}
}
}
protected void setTaskService(TaskService taskService) { protected void setTaskService(TaskService taskService) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Setting the task service."); log.debug("Setting the task service.");

@ -1587,4 +1587,19 @@ public class OperationManagerImpl implements OperationManager {
OperationManagementDAOFactory.closeConnection(); OperationManagementDAOFactory.closeConnection();
} }
} }
@Override
public List<Activity> getActivities(List<String> deviceTypes, String operationCode, long updatedSince, String operationStatus)
throws OperationManagementException {
try {
OperationManagementDAOFactory.openConnection();
return operationDAO.getActivities(deviceTypes, operationCode, updatedSince, operationStatus);
} catch (SQLException e) {
throw new OperationManagementException("Error occurred while opening a connection to the data source.", e);
} catch (OperationManagementDAOException e) {
throw new OperationManagementException("Error occurred while getting the activity list.", e);
} finally {
OperationManagementDAOFactory.closeConnection();
}
}
} }

@ -101,6 +101,9 @@ public interface OperationDAO {
Map<Integer, List<OperationMapping>> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus, Map<Integer, List<OperationMapping>> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus,
int limit) throws OperationManagementDAOException; int limit) throws OperationManagementDAOException;
List<Activity> getActivities(List<String> deviceTypes, String operationCode, long updatedSince, String operationStatus)
throws OperationManagementDAOException;
List<Activity> getActivities(ActivityPaginationRequest activityPaginationRequest) List<Activity> getActivities(ActivityPaginationRequest activityPaginationRequest)
throws OperationManagementDAOException; throws OperationManagementDAOException;

@ -1723,6 +1723,141 @@ public class GenericOperationDAOImpl implements OperationDAO {
return operationMappingsTenantMap; return operationMappingsTenantMap;
} }
public List<Activity> getActivities(List<String> deviceTypes, String operationCode, long updatedSince, String operationStatus)
throws OperationManagementDAOException {
try {
Connection conn = OperationManagementDAOFactory.getConnection();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
StringBuilder sql = new StringBuilder("SELECT " +
" eom.ENROLMENT_ID," +
" eom.CREATED_TIMESTAMP," +
" eom.UPDATED_TIMESTAMP," +
" eom.OPERATION_ID," +
" eom.OPERATION_CODE," +
" eom.INITIATED_BY," +
" eom.TYPE," +
" eom.STATUS," +
" eom.DEVICE_ID," +
" eom.DEVICE_IDENTIFICATION," +
" eom.DEVICE_TYPE," +
" opr.ID AS OP_RES_ID," +
" opr.RECEIVED_TIMESTAMP," +
" opr.OPERATION_RESPONSE," +
" opr.IS_LARGE_RESPONSE " +
"FROM " +
" DM_ENROLMENT_OP_MAPPING eom " +
"LEFT JOIN " +
" DM_DEVICE_OPERATION_RESPONSE opr ON opr.EN_OP_MAP_ID = eom.ID " +
"INNER JOIN " +
" (SELECT DISTINCT OPERATION_ID FROM DM_ENROLMENT_OP_MAPPING WHERE TENANT_ID = ? ");
if (deviceTypes != null && !deviceTypes.isEmpty()) {
sql.append("AND DEVICE_TYPE IN (");
for (int i = 0; i < deviceTypes.size() - 1; i++) {
sql.append("?, ");
}
sql.append("?) ");
}
if (operationCode != null) {
sql.append("AND OPERATION_CODE = ? ");
}
if (updatedSince != 0) {
sql.append("AND UPDATED_TIMESTAMP < ? ");
}
if (operationStatus != null) {
sql.append("AND STATUS = ? ");
}
sql.append("ORDER BY OPERATION_ID ASC ) eom_ordered " +
"ON eom_ordered.OPERATION_ID = eom.OPERATION_ID WHERE eom.TENANT_ID = ? ");
if (deviceTypes != null && !deviceTypes.isEmpty()) {
sql.append("AND DEVICE_TYPE IN (");
for (int i = 0; i < deviceTypes.size() - 1; i++) {
sql.append("?, ");
}
sql.append("?) ");
}
if (operationCode != null) {
sql.append("AND eom.OPERATION_CODE = ? ");
}
if (updatedSince != 0) {
sql.append("AND eom.UPDATED_TIMESTAMP < ? ");
}
if (operationStatus != null) {
sql.append("AND eom.STATUS = ? ");
}
sql.append("ORDER BY eom.OPERATION_ID, eom.UPDATED_TIMESTAMP");
int index = 1;
try (PreparedStatement stmt = conn.prepareStatement(sql.toString())) {
stmt.setInt(index++, tenantId);
if (deviceTypes != null && !deviceTypes.isEmpty()) {
for (String deviceId : deviceTypes) {
stmt.setString(index++, deviceId);
}
}
if (operationCode != null) {
stmt.setString(index++, operationCode);
}
if (updatedSince != 0) {
stmt.setLong(index++, updatedSince);
}
if (operationStatus != null) {
stmt.setString(index++, operationStatus);
}
stmt.setInt(index++, tenantId);
if (deviceTypes != null && !deviceTypes.isEmpty()) {
for (String deviceId : deviceTypes) {
stmt.setString(index++, deviceId);
}
}
if (operationCode != null) {
stmt.setString(index++, operationCode);
}
if (updatedSince != 0) {
stmt.setLong(index++, updatedSince);
}
if (operationStatus != null) {
stmt.setString(index, operationStatus);
}
try (ResultSet rs = stmt.executeQuery()) {
ActivityHolder activityHolder = OperationDAOUtil.getActivityHolder(rs);
List<Integer> largeResponseIDs = activityHolder.getLargeResponseIDs();
List<Activity> activities = activityHolder.getActivityList();
if (!largeResponseIDs.isEmpty()) {
populateLargeOperationResponses(activities, largeResponseIDs);
}
return activities;
}
}
} catch (SQLException e) {
String msg = "Error occurred while getting the operation details from the database.";
log.error(msg, e);
throw new OperationManagementDAOException(msg, e);
}
}
@Override @Override
public List<Activity> getActivities(ActivityPaginationRequest activityPaginationRequest) public List<Activity> getActivities(ActivityPaginationRequest activityPaginationRequest)
throws OperationManagementDAOException { throws OperationManagementDAOException {

@ -0,0 +1,62 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.operation.timeout.task;
/**
* This exception class defines the custom exceptions thrown by the OperationTimeoutTask related components.
*/
public class OperationTimeoutTaskException extends Exception {
private static final long serialVersionUID = -31222242646464497L;
private String errorMessage;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public OperationTimeoutTaskException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public OperationTimeoutTaskException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public OperationTimeoutTaskException(String msg) {
super(msg);
setErrorMessage(msg);
}
public OperationTimeoutTaskException() {
super();
}
public OperationTimeoutTaskException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,59 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.operation.timeout.task;
import org.wso2.carbon.device.mgt.core.config.operation.timeout.OperationTimeout;
/**
* This interface defines the methods that should be implemented by the management service of OperationTimeoutTask
*/
public interface OperationTimeoutTaskManagerService {
/**
* This method will start the task
* @param config
* @throws OperationTimeoutTaskException
*/
void startTask(OperationTimeout config)
throws OperationTimeoutTaskException;
/**
* This method will stop the task.
* @param config
* @throws OperationTimeoutTaskException
*/
void stopTask(OperationTimeout config)
throws OperationTimeoutTaskException;
/**
* This will update the task frequency which it runs.
*
* @param config
* @throws OperationTimeoutTaskException
*/
void updateTask(OperationTimeout config)
throws OperationTimeoutTaskException;
/**
* This will check weather the task is scheduled.
* @return
* @throws OperationTimeoutTaskException
*/
boolean isTaskScheduled(OperationTimeout config) throws OperationTimeoutTaskException;
}

@ -0,0 +1,106 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.operation.timeout.task.impl;
import com.google.gson.Gson;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.core.config.operation.timeout.OperationTimeout;
import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
import org.wso2.carbon.device.mgt.core.task.impl.DynamicPartitionedScheduleTask;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class OperationTimeoutTask extends DynamicPartitionedScheduleTask {
private static final Log log = LogFactory.getLog(OperationTimeoutTask.class);
private OperationTimeout operationTimeoutConfig;
@Override
public void setProperties(Map<String, String> properties) {
super.setProperties(properties);
String operationTimeoutTaskConfigStr = properties
.get(OperationTimeoutTaskManagerServiceImpl.OPERATION_TIMEOUT_TASK_CONFIG);
Gson gson = new Gson();
operationTimeoutConfig = gson.fromJson(operationTimeoutTaskConfigStr, OperationTimeout.class);
}
@Override
public String getProperty(String name) {
return super.getProperty(name);
}
@Override
public void refreshContext() {
super.refreshContext();
}
@Override
protected void setup() {
}
@Override
protected void executeDynamicTask() {
try {
long timeMillis = System.currentTimeMillis() - operationTimeoutConfig.getTimeout() * 60 * 1000;
List<String> deviceTypes = new ArrayList<>();
if (operationTimeoutConfig.getDeviceTypes().size() == 1 &&
"ALL".equals(operationTimeoutConfig.getDeviceTypes().get( 0))) {
try {
List<DeviceType> deviceTypeList = DeviceManagementDataHolder.getInstance()
.getDeviceManagementProvider().getDeviceTypes();
for (DeviceType deviceType : deviceTypeList) {
deviceTypes.add(deviceType.getName());
}
} catch (DeviceManagementException e) {
log.error("Error occurred while reading device types", e);
}
} else {
deviceTypes = operationTimeoutConfig.getDeviceTypes();
}
List<Activity> activities = DeviceManagementDataHolder.getInstance().getOperationManager()
.getActivities(deviceTypes, operationTimeoutConfig.getCode(), timeMillis,
operationTimeoutConfig.getInitialStatus());
for (Activity activity : activities) {
for (ActivityStatus activityStatus : activity.getActivityStatus()) {
String operationId = activity.getActivityId().replace("ACTIVITY_", "");
Operation operation = DeviceManagementDataHolder.getInstance().getOperationManager()
.getOperation(Integer.parseInt(operationId));
operation.setStatus(Operation.Status.valueOf(operationTimeoutConfig.getNextStatus()));
DeviceManagementDataHolder.getInstance().getOperationManager()
.updateOperation(activityStatus.getDeviceIdentifier(), operation);
}
}
} catch (OperationManagementException e) {
String msg = "Error occurred while retrieving operations.";
log.error(msg, e);
}
}
}

@ -0,0 +1,172 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.operation.timeout.task.impl;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.core.config.operation.timeout.OperationTimeout;
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
import org.wso2.carbon.device.mgt.core.operation.timeout.task.OperationTimeoutTaskException;
import org.wso2.carbon.device.mgt.core.operation.timeout.task.OperationTimeoutTaskManagerService;
import org.wso2.carbon.ntask.common.TaskException;
import org.wso2.carbon.ntask.core.TaskInfo;
import org.wso2.carbon.ntask.core.TaskManager;
import org.wso2.carbon.ntask.core.service.TaskService;
import java.util.HashMap;
import java.util.Map;
public class OperationTimeoutTaskManagerServiceImpl implements OperationTimeoutTaskManagerService {
private static final Log log = LogFactory.getLog(OperationTimeoutTaskManagerServiceImpl.class);
public static final String OPERATION_TIMEOUT_TASK = "OPERATION_TIMEOUT_TASK";
static final String DEVICE_TYPES = "DEVICE_TYPES";
static final String OPERATION_TIMEOUT_TASK_CONFIG = "OPERATION_TIMEOUT_TASK_CONFIG";
static final String INITIAL_STATUS = "INITIAL_STATUS";
private static final String TASK_CLASS = OperationTimeoutTask.class.getName();
@Override
public void startTask(OperationTimeout config)
throws OperationTimeoutTaskException {
log.info("Operation timeout task adding for device type(s) : " + config.getDeviceTypes()
+ ", operation code : " + config.getInitialStatus());
try {
TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService();
taskService.registerTaskType(OPERATION_TIMEOUT_TASK);
if (log.isDebugEnabled()) {
log.debug("Operation timeout task is started for the device type(s) : " + config.getDeviceTypes()
+ ", operation code : " + config.getInitialStatus());
log.debug(
"Operation timeout task is at frequency of : " + config.getTimeout() + " minutes");
}
TaskManager taskManager = taskService.getTaskManager(OPERATION_TIMEOUT_TASK);
TaskInfo.TriggerInfo triggerInfo = new TaskInfo.TriggerInfo();
//Convert to milli seconds
triggerInfo.setIntervalMillis(config.getTimeout() * 60 * 1000);
triggerInfo.setRepeatCount(-1);
Gson gson = new Gson();
String operationTimeoutConfig = gson.toJson(config);
Map<String, String> properties = new HashMap<>();
String deviceTypes = StringUtils.join(config.getDeviceTypes(), "_");
properties.put(DEVICE_TYPES, deviceTypes);
properties.put(INITIAL_STATUS, config.getInitialStatus());
properties.put(OPERATION_TIMEOUT_TASK_CONFIG, operationTimeoutConfig);
String taskName = OPERATION_TIMEOUT_TASK + "_" + config.getInitialStatus() + "_" + deviceTypes;
if (!taskManager.isTaskScheduled(taskName)) {
TaskInfo taskInfo = new TaskInfo(taskName, TASK_CLASS, properties, triggerInfo);
taskManager.registerTask(taskInfo);
taskManager.rescheduleTask(taskInfo.getName());
} else {
throw new OperationTimeoutTaskException(
"Operation Timeout task is already started for the device type(s) : " + config.getDeviceTypes()
+ ", operation code : " + config.getInitialStatus());
}
} catch (TaskException e) {
throw new OperationTimeoutTaskException("Error occurred while creating the Operation timeout task " +
"for the device type(s) : " + config.getDeviceTypes() + ", operation code : " + config
.getInitialStatus(), e);
}
}
@Override
public void stopTask(OperationTimeout config)
throws OperationTimeoutTaskException {
try {
TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService();
String deviceTypes = StringUtils.join(config.getDeviceTypes(), "_");
String taskName = OPERATION_TIMEOUT_TASK + "_" + config.getInitialStatus() + "_" + deviceTypes;
if (taskService != null && taskService.isServerInit()) {
TaskManager taskManager = taskService.getTaskManager(OPERATION_TIMEOUT_TASK);
taskManager.deleteTask(taskName);
}
} catch (TaskException e) {
throw new OperationTimeoutTaskException("Error occurred while deleting the Operation timeout task " +
"for the device type(s) : " + config.getDeviceTypes() + ", operation code : " + config
.getInitialStatus(), e);
}
}
@Override
public void updateTask(OperationTimeout config)
throws OperationTimeoutTaskException {
try {
TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService();
TaskManager taskManager = taskService.getTaskManager(OPERATION_TIMEOUT_TASK);
String deviceTypes = StringUtils.join(config.getDeviceTypes(), "_");
String taskName = OPERATION_TIMEOUT_TASK + "_" + config.getInitialStatus() + "_" + deviceTypes;
if (taskManager.isTaskScheduled(taskName)) {
taskManager.deleteTask(taskName);
TaskInfo.TriggerInfo triggerInfo = new TaskInfo.TriggerInfo();
triggerInfo.setIntervalMillis(config.getTimeout() * 60 * 1000);
triggerInfo.setRepeatCount(-1);
Map<String, String> properties = new HashMap<>();
properties.put(DEVICE_TYPES, deviceTypes);
properties.put(INITIAL_STATUS, config.getInitialStatus());
Gson gson = new Gson();
String deviceStatusTaskConfigs = gson.toJson(config);
properties.put(OPERATION_TIMEOUT_TASK_CONFIG, deviceStatusTaskConfigs);
TaskInfo taskInfo = new TaskInfo(taskName, TASK_CLASS, properties, triggerInfo);
taskManager.registerTask(taskInfo);
taskManager.rescheduleTask(taskInfo.getName());
} else {
throw new OperationTimeoutTaskException(
"Operation timeout task has not been started for this device-type the device type(s) : "
+ config.getDeviceTypes() + ", operation code : " + config.getInitialStatus() +
". Please start the task first.");
}
} catch (TaskException e) {
throw new OperationTimeoutTaskException("Error occurred while updating the Operation timeout task " +
"for the device type(s) : " + config.getDeviceTypes() + ", operation code : " +
config.getInitialStatus(), e);
}
}
@Override
public boolean isTaskScheduled(OperationTimeout config) throws OperationTimeoutTaskException {
String deviceTypes = StringUtils.join(config.getDeviceTypes(), "_");
String taskName = OPERATION_TIMEOUT_TASK + "_" + config.getInitialStatus() + "_" + deviceTypes;
TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService();
TaskManager taskManager;
try {
taskManager = taskService.getTaskManager(OPERATION_TIMEOUT_TASK);
return taskManager.isTaskScheduled(taskName);
} catch (TaskException e) {
throw new OperationTimeoutTaskException("Error occurred while checking the task schedule status " +
"of the Operation timeout task for the device type(s) : " + config.getDeviceTypes() +
", operation code : " + config.getInitialStatus(), e);
}
}
}

@ -178,5 +178,9 @@
</Role> </Role>
</Roles> </Roles>
</DefaultRoles> </DefaultRoles>
<OperationTimeoutConfigurations>
<OperationTimeouts>
</OperationTimeouts>
</OperationTimeoutConfigurations>
</DeviceMgtConfiguration> </DeviceMgtConfiguration>

@ -311,5 +311,34 @@
</Role> </Role>
</Roles> </Roles>
</DefaultRoles> </DefaultRoles>
<OperationTimeoutConfigurations>
<OperationTimeouts>
<!--<OperationTimeout>-->
<!--<DeviceTypes>-->
<!--<DeviceType>ALL</DeviceType>-->
<!--</DeviceTypes>-->
<!--<Code>DOUBLE_COMMAND</Code>-->
<!--<InitialStatus>REQUIRED_CONFIRMATION</InitialStatus>-->
<!--<Timeout>30</Timeout>-->
<!--<NextStatus>ERROR</NextStatus>-->
<!--</OperationTimeout>-->
{% if device_mgt_conf.operation_timeout_conf is defined %}
{% for timeout_conf in device_mgt_conf.operation_timeout_conf %}
<OperationTimeout>
<DeviceTypes>
{% for device_type in timeout_conf.device_types %}
<DeviceType>{{device_type}}</DeviceType>
{% endfor %}
</DeviceTypes>
<Code>{{timeout_conf.code}}</Code>
<InitialStatus>{{timeout_conf.initial_status}}</InitialStatus>
<Timeout>{{timeout_conf.timeout}}</Timeout>
<NextStatus>{{timeout_conf.next_status}}</NextStatus>
</OperationTimeout>
{% endfor %}
{% endif%}
</OperationTimeouts>
</OperationTimeoutConfigurations>
</DeviceMgtConfiguration> </DeviceMgtConfiguration>

Loading…
Cancel
Save