WIP: Add Tenanted Device Task Configurations #370

Draft
pramilaniroshan wants to merge 7 commits from pramilaniroshan/device-mgt-core:device-tenant-task-configuration into master

@ -473,5 +473,15 @@
<artifactId>io.entgra.device.mgt.core.tenant.mgt.common</artifactId> <artifactId>io.entgra.device.mgt.core.tenant.mgt.common</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.task.mgt.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.task.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -29,6 +29,15 @@ public class OperationMonitoringTaskConfig {
private boolean isEnabled; private boolean isEnabled;
private int frequency; private int frequency;
private List<MonitoringOperation> monitoringOperation = new ArrayList<>(); private List<MonitoringOperation> monitoringOperation = new ArrayList<>();
private String cronExpression;
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
public boolean isEnabled() { public boolean isEnabled() {
return isEnabled; return isEnabled;

@ -0,0 +1,35 @@
/*
* Copyright (c) 2018 - 2024, 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 io.entgra.device.mgt.core.device.mgt.common.metadata.mgt;
import java.util.HashMap;
public class DeviceFrequencyMap extends HashMap<String, DeviceFrequencyMap.Device> {
public static class Device {
private int frequency;
public int getFrequency() {
return frequency;
}
public void setFrequency(int frequency) {
this.frequency = frequency;
}
}
}

@ -0,0 +1,50 @@
/*
* Copyright (c) 2018 - 2024, 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 io.entgra.device.mgt.core.device.mgt.common.metadata.mgt;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
public interface DeviceTaskConfigurationService {
/**
* This method is useful to add Default Task Frequency from device type xml
*
* @throws MetadataManagementException if error while adding default TaskFrequency
*/
void addDefaultTaskFrequency(int tenantId) throws MetadataManagementException;
/**
* This method is useful to add custom Task Frequency for device types
*
* @throws MetadataManagementException if error while adding TaskFrequency
*/
void addTaskFrequency(int tenantId, int frequency, String deviceType) throws MetadataManagementException;
/**
* Retrieves the task frequency for a specific device type and tenant from the cache or metadata service.
*
* @param deviceType the type of the device for which the task frequency is being retrieved.
* @param tenantId the ID of the tenant associated with the device.
* @return the task frequency for the specified device type and tenant.
* @throws MetadataManagementException if there is an error managing the metadata.
*/
int getTaskFrequency(String deviceType, int tenantId) throws MetadataManagementException;
}

@ -41,6 +41,17 @@ public interface MetadataManagementService {
*/ */
Metadata createMetadata(Metadata metadata) throws MetadataManagementException, MetadataKeyAlreadyExistsException; Metadata createMetadata(Metadata metadata) throws MetadataManagementException, MetadataKeyAlreadyExistsException;
/**
* Persist the provided Metadata entry.
*
* @param metadata the Metadata entry to be persisted
* @param tenantId the Metadata entry to be persisted in given tenantId
* @return the Metadata entry along with the updated Metadata.id
* @throws MetadataManagementException If a data source related exception occurred
* @throws MetadataKeyAlreadyExistsException If the provided Metadata.metaKey already exist
*/
Metadata createMetadata(Metadata metadata, int tenantId) throws MetadataManagementException, MetadataKeyAlreadyExistsException;
/** /**
* Get the specified Metadata entry. * Get the specified Metadata entry.
* *

@ -460,6 +460,16 @@
<groupId>io.entgra.device.mgt.core</groupId> <groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.apimgt.extension.rest.api</artifactId> <artifactId>io.entgra.device.mgt.core.apimgt.extension.rest.api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.task.mgt.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.entgra.device.mgt.core</groupId>
<artifactId>io.entgra.device.mgt.core.task.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -18,6 +18,14 @@
package io.entgra.device.mgt.core.device.mgt.core; package io.entgra.device.mgt.core.device.mgt.core;
import com.google.gson.Gson; import com.google.gson.Gson;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceTaskManagerWrapper;
import io.entgra.device.mgt.core.task.mgt.common.bean.DynamicTask;
import io.entgra.device.mgt.core.task.mgt.common.exception.TaskManagementException;
import io.entgra.device.mgt.core.task.mgt.common.spi.TaskManagementService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import io.entgra.device.mgt.core.device.mgt.common.DeviceStatusTaskPluginConfig; import io.entgra.device.mgt.core.device.mgt.common.DeviceStatusTaskPluginConfig;
import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig; import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig;
import io.entgra.device.mgt.core.device.mgt.common.ProvisioningConfig; import io.entgra.device.mgt.core.device.mgt.common.ProvisioningConfig;
@ -52,6 +60,7 @@ import org.wso2.carbon.context.PrivilegedCarbonContext;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
public class DeviceManagementPluginRepository implements DeviceManagerStartupListener { public class DeviceManagementPluginRepository implements DeviceManagerStartupListener {
@ -299,14 +308,16 @@ public class DeviceManagementPluginRepository implements DeviceManagerStartupLis
getDeviceTaskManagerService(); getDeviceTaskManagerService();
OperationMonitoringTaskConfig operationMonitoringTaskConfig = deviceManagementService. OperationMonitoringTaskConfig operationMonitoringTaskConfig = deviceManagementService.
getOperationMonitoringConfig(); getOperationMonitoringConfig();
DeviceTaskManagerWrapper deviceTaskManagerWrapper = new DeviceTaskManagerWrapper();
deviceTaskManagerWrapper.setDeviceType(deviceManagementService.getType());
deviceTaskManagerWrapper.setOperationMonitoringTaskConfig(operationMonitoringTaskConfig);
if (operationMonitoringTaskConfig != null && operationMonitoringTaskConfig.isEnabled()) { if (operationMonitoringTaskConfig != null && operationMonitoringTaskConfig.isEnabled()) {
if (deviceTaskManagerService == null) { if (deviceTaskManagerService == null) {
DeviceMonitoringOperationDataHolder.getInstance().addOperationMonitoringConfigToMap( DeviceMonitoringOperationDataHolder.getInstance().addOperationMonitoringConfigToMap(
deviceManagementService.getType(), operationMonitoringTaskConfig); deviceManagementService.getType(), operationMonitoringTaskConfig);
} else { } else {
deviceTaskManagerService.startTask(deviceManagementService.getType(), deviceTaskManagerService.startTask(deviceTaskManagerWrapper);
operationMonitoringTaskConfig);
} }
} }
} catch (DeviceMgtTaskException e) { } catch (DeviceMgtTaskException e) {
@ -322,14 +333,24 @@ public class DeviceManagementPluginRepository implements DeviceManagerStartupLis
getDeviceTaskManagerService(); getDeviceTaskManagerService();
OperationMonitoringTaskConfig operationMonitoringTaskConfig = deviceManagementService. OperationMonitoringTaskConfig operationMonitoringTaskConfig = deviceManagementService.
getOperationMonitoringConfig(); getOperationMonitoringConfig();
TaskManagementService taskManagementService= DeviceManagementDataHolder.getInstance().getTaskManagementService();
if (operationMonitoringTaskConfig != null && operationMonitoringTaskConfig.isEnabled()) { if (operationMonitoringTaskConfig != null && operationMonitoringTaskConfig.isEnabled()) {
deviceTaskManagerService.stopTask(deviceManagementService.getType(), Map<Integer, List<DynamicTask>> dynamicTasksForAllTenants = taskManagementService.getDynamicTasksForAllTenants();
deviceManagementService.getOperationMonitoringConfig());
for (Map.Entry<Integer, List<DynamicTask>> entry : dynamicTasksForAllTenants.entrySet()) {
List<DynamicTask> dynamicTasks = entry.getValue();
for (DynamicTask task : dynamicTasks) {
deviceTaskManagerService.stopTask(task.getDynamicTaskId());
}
}
} }
} catch (DeviceMgtTaskException e) { } catch (DeviceMgtTaskException e) {
throw new DeviceManagementException("Error occurred while removing task service for '" + throw new DeviceManagementException("Error occurred while removing task service for '" +
deviceManagementService.getType() + "'", e); deviceManagementService.getType() + "'", e);
} } catch (TaskManagementException e) {
throw new DeviceManagementException("Error occurred while deleting task service for '" +
deviceManagementService.getType() + "'", e);
}
} }
private void registerDeviceStatusMonitoringTask(DeviceType deviceType, DeviceManagementService deviceManagementService) throws private void registerDeviceStatusMonitoringTask(DeviceType deviceType, DeviceManagementService deviceManagementService) throws

@ -0,0 +1,80 @@
/*
* Copyright (C) 2018 - 2024 Entgra (Pvt) Ltd, Inc - All Rights Reserved.
*
* Unauthorised copying/redistribution of this file, via any medium is strictly prohibited.
*
* Licensed under the Entgra Commercial License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://entgra.io/licenses/entgra-commercial/1.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 io.entgra.device.mgt.core.device.mgt.core.dto;
import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel(
value = "DeviceTaskManagerWrapper",
description = "DeviceTaskManagerWrapper represents request payload of scheduling device details retriever task")
public class DeviceTaskManagerWrapper {
@ApiModelProperty(name = "cron",
value = "Cron to be scheduled",
example = "0 0 * * * ? *, 0 0 0/8 * * ? *",
required = true)
private String cron;
@ApiModelProperty(name = "payload",
value = "Operation payload")
private Object payload;
@ApiModelProperty(name = "deviceType",
value = "Device type")
private String deviceType;
public OperationMonitoringTaskConfig getOperationMonitoringTaskConfig() {
return operationMonitoringTaskConfig;
}
public void setOperationMonitoringTaskConfig(OperationMonitoringTaskConfig operationMonitoringTaskConfig) {
this.operationMonitoringTaskConfig = operationMonitoringTaskConfig;
}
private OperationMonitoringTaskConfig operationMonitoringTaskConfig;
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
public String getCron() {
return cron;
}
public void setCron(String cron) {
this.cron = cron;
}
public Object getPayload() {
return payload;
}
public void setPayload(Object payload) {
this.payload = payload;
}
}

@ -23,6 +23,7 @@ import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServi
import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuthorizationService; import io.entgra.device.mgt.core.device.mgt.common.authorization.GroupAccessAuthorizationService;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService;
import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService; import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
import io.entgra.device.mgt.core.task.mgt.common.spi.TaskManagementService;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import io.entgra.device.mgt.core.device.mgt.common.DeviceStatusTaskPluginConfig; import io.entgra.device.mgt.core.device.mgt.common.DeviceStatusTaskPluginConfig;
import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig; import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig;
@ -100,6 +101,7 @@ public class DeviceManagementDataHolder {
private DeviceStatusManagementService deviceStatusManagementService; private DeviceStatusManagementService deviceStatusManagementService;
private APIApplicationServices apiApplicationServices; private APIApplicationServices apiApplicationServices;
private PublisherRESTAPIServices publisherRESTAPIServices; private PublisherRESTAPIServices publisherRESTAPIServices;
private TaskManagementService taskManagementService;
private DeviceManagementStartupHandler deviceManagementStartupHandler; private DeviceManagementStartupHandler deviceManagementStartupHandler;
private final Map<DeviceType, DeviceStatusTaskPluginConfig> deviceStatusTaskPluginConfigs = Collections.synchronizedMap( private final Map<DeviceType, DeviceStatusTaskPluginConfig> deviceStatusTaskPluginConfigs = Collections.synchronizedMap(
@ -459,6 +461,14 @@ public class DeviceManagementDataHolder {
this.groupAccessAuthorizationService = groupAccessAuthorizationService; this.groupAccessAuthorizationService = groupAccessAuthorizationService;
} }
public TaskManagementService getTaskManagementService() {
return taskManagementService;
}
public void setTaskManagementService(TaskManagementService taskManagementService) {
this.taskManagementService = taskManagementService;
}
public DeviceManagementStartupHandler getDeviceManagementStartupHandler() { public DeviceManagementStartupHandler getDeviceManagementStartupHandler() {
return deviceManagementStartupHandler; return deviceManagementStartupHandler;
} }

@ -22,6 +22,7 @@ import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagement
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService;
import io.entgra.device.mgt.core.device.mgt.core.authorization.GroupAccessAuthorizationServiceImpl; import io.entgra.device.mgt.core.device.mgt.core.authorization.GroupAccessAuthorizationServiceImpl;
import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.DeviceStatusManagementServiceImpl; import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.DeviceStatusManagementServiceImpl;
import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.TaskConfigurationStartupHandler;
import io.entgra.device.mgt.core.device.mgt.core.service.TagManagementProviderService; import io.entgra.device.mgt.core.device.mgt.core.service.TagManagementProviderService;
import io.entgra.device.mgt.core.device.mgt.core.service.TagManagementProviderServiceImpl; import io.entgra.device.mgt.core.device.mgt.core.service.TagManagementProviderServiceImpl;
import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService; import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
@ -387,6 +388,9 @@ public class DeviceManagementServiceComponent {
ExecutorService executorService = Executors.newFixedThreadPool(50); ExecutorService executorService = Executors.newFixedThreadPool(50);
DeviceManagementDataHolder.getInstance().setEventConfigExecutors(executorService); DeviceManagementDataHolder.getInstance().setEventConfigExecutors(executorService);
/* Registering Task Configuration StartupHandler Service */
bundleContext.registerService(ServerStartupObserver.class, new TaskConfigurationStartupHandler(), null);
} }
private void setupDeviceManagementSchema(DataSourceConfig config) throws DeviceManagementException { private void setupDeviceManagementSchema(DataSourceConfig config) throws DeviceManagementException {

@ -18,6 +18,14 @@
package io.entgra.device.mgt.core.device.mgt.core.internal; package io.entgra.device.mgt.core.device.mgt.core.internal;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceTaskManagerWrapper;
import io.entgra.device.mgt.core.task.mgt.common.bean.DynamicTask;
import io.entgra.device.mgt.core.task.mgt.common.exception.TaskManagementException;
import io.entgra.device.mgt.core.task.mgt.common.spi.TaskManagementService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import io.entgra.device.mgt.core.device.mgt.common.DeviceStatusTaskPluginConfig; import io.entgra.device.mgt.core.device.mgt.common.DeviceStatusTaskPluginConfig;
import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig; import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig;
import io.entgra.device.mgt.core.device.mgt.core.config.DeviceConfigurationManager; import io.entgra.device.mgt.core.device.mgt.core.config.DeviceConfigurationManager;
@ -39,9 +47,34 @@ import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext; import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext; import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.*; import org.osgi.service.component.annotations.*;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.ntask.core.service.TaskService; import org.wso2.carbon.ntask.core.service.TaskService;
import org.wso2.carbon.user.api.Tenant;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map; import java.util.Map;
/**
* @scr.component name="org.wso2.carbon.device.task.manager" immediate="true"
* @scr.reference name="device.ntask.component"
* interface="org.wso2.carbon.ntask.core.service.TaskService"
* cardinality="1..1"
* policy="dynamic"
* bind="setTaskService"
* unbind="unsetTaskService"
* @scr.reference name="io.entgra.task.mgt.service"
* interface="io.entgra.device.mgt.core.task.mgt.common.spi.TaskManagementService"
* cardinality="1..1"
* policy="dynamic"
* bind="setTaskMgtService"
* unbind="unsetTaskMgtService"
*/
@Component( @Component(
name = "io.entgra.device.mgt.core.device.mgt.core.internal.DeviceTaskManagerServiceComponent", name = "io.entgra.device.mgt.core.device.mgt.core.internal.DeviceTaskManagerServiceComponent",
immediate = true) immediate = true)
@ -81,11 +114,38 @@ public class DeviceTaskManagerServiceComponent {
bundleContext.registerService(DeviceTaskManagerService.class, deviceTaskManagerService, null); bundleContext.registerService(DeviceTaskManagerService.class, deviceTaskManagerService, null);
Map<String, OperationMonitoringTaskConfig> deviceConfigMap = DeviceMonitoringOperationDataHolder Map<String, OperationMonitoringTaskConfig> deviceConfigMap = DeviceMonitoringOperationDataHolder
.getInstance().getOperationMonitoringConfigFromMap(); .getInstance().getOperationMonitoringConfigFromMap();
for (String platformType : deviceConfigMap.keySet()) { List<Tenant> tenants = getAllTenants();
OperationMonitoringTaskConfig taskConfig = deviceConfigMap.get(platformType); for (Tenant tenant : tenants) {
if (taskConfig.isEnabled()) { if (MultitenantConstants.SUPER_TENANT_ID == tenant.getId()) {
deviceTaskManagerService.startTask(platformType, taskConfig); startTasksForTenant(deviceConfigMap,deviceTaskManagerService);
continue;
} }
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenant.getId(), true);
startTasksForTenant(deviceConfigMap,deviceTaskManagerService);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}
private List<Tenant> getAllTenants() {
List<Tenant> tenants = new ArrayList<>();
try {
RealmService realmService = DeviceManagementDataHolder.getInstance().getRealmService();
Tenant[] tenantArray = realmService.getTenantManager().getAllTenants();
if (tenantArray != null && tenantArray.length != 0) {
tenants.addAll(Arrays.asList(tenantArray));
}
Tenant superTenant = new Tenant();
superTenant.setId(-1234);
tenants.add(superTenant);
return tenants;
} catch (UserStoreException e) {
String msg = "Unable to load tenants";
log.error(msg, e);
return new ArrayList<>();
} }
} }
@ -105,6 +165,18 @@ public class DeviceTaskManagerServiceComponent {
} }
} }
private void startTasksForTenant(Map<String, OperationMonitoringTaskConfig> deviceConfigMap,DeviceTaskManagerService deviceTaskManagerService) throws DeviceMgtTaskException {
DeviceTaskManagerWrapper deviceTaskManagerWrapper = new DeviceTaskManagerWrapper();
for (String platformType : deviceConfigMap.keySet()) {
deviceTaskManagerWrapper.setDeviceType(platformType);
OperationMonitoringTaskConfig taskConfig = deviceConfigMap.get(platformType);
deviceTaskManagerWrapper.setOperationMonitoringTaskConfig(taskConfig);
if (taskConfig.isEnabled()) {
deviceTaskManagerService.startTask(deviceTaskManagerWrapper);
}
}
}
private void startOperationTimeoutTask(BundleContext bundleContext) { private void startOperationTimeoutTask(BundleContext bundleContext) {
OperationTimeoutTaskManagerService operationTimeoutTaskManagerService = OperationTimeoutTaskManagerService operationTimeoutTaskManagerService =
new OperationTimeoutTaskManagerServiceImpl(); new OperationTimeoutTaskManagerServiceImpl();
@ -143,15 +215,19 @@ public class DeviceTaskManagerServiceComponent {
} }
private void stopOperationMonitoringTask() private void stopOperationMonitoringTask()
throws DeviceMgtTaskException { throws DeviceMgtTaskException, TaskManagementException {
DeviceTaskManagerService deviceTaskManagerService = DeviceManagementDataHolder.getInstance() DeviceTaskManagerService deviceTaskManagerService = DeviceManagementDataHolder.getInstance()
.getDeviceTaskManagerService(); .getDeviceTaskManagerService();
TaskManagementService taskManagementService= DeviceManagementDataHolder.getInstance().getTaskManagementService();
Map<String, OperationMonitoringTaskConfig> deviceConfigMap = DeviceMonitoringOperationDataHolder Map<String, OperationMonitoringTaskConfig> deviceConfigMap = DeviceMonitoringOperationDataHolder
.getInstance().getOperationMonitoringConfigFromMap(); .getInstance().getOperationMonitoringConfigFromMap();
for (String platformType : deviceConfigMap.keySet()) { Map<Integer, List<DynamicTask>> dynamicTasksForAllTenants = taskManagementService.getDynamicTasksForAllTenants();
OperationMonitoringTaskConfig taskConfig = deviceConfigMap.get(platformType);
if (taskConfig.isEnabled()) { for (Map.Entry<Integer, List<DynamicTask>> entry : dynamicTasksForAllTenants.entrySet()) {
deviceTaskManagerService.stopTask(platformType, taskConfig); Integer tenantId = entry.getKey();
List<DynamicTask> dynamicTasks = entry.getValue();
for (DynamicTask task : dynamicTasks) {
deviceTaskManagerService.stopTask(task.getDynamicTaskId());
} }
} }
} }
@ -206,4 +282,20 @@ public class DeviceTaskManagerServiceComponent {
} }
DeviceManagementDataHolder.getInstance().setTaskService(null); DeviceManagementDataHolder.getInstance().setTaskService(null);
} }
@SuppressWarnings("unused")
protected void setTaskMgtService(TaskManagementService taskManagementService) {
if (log.isDebugEnabled()) {
log.debug("Setting the task service");
}
DeviceManagementDataHolder.getInstance().setTaskManagementService(taskManagementService);
}
@SuppressWarnings("unused")
protected void unsetTaskMgtService(TaskManagementService taskManagementService) {
if (log.isDebugEnabled()) {
log.debug("Removing the task service");
}
DeviceManagementDataHolder.getInstance().setTaskManagementService(null);
}
} }

@ -0,0 +1,171 @@
/*
* Copyright (c) 2018 - 2024, 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 io.entgra.device.mgt.core.device.mgt.core.metadata.mgt;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataKeyAlreadyExistsException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceFrequencyMap;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceTaskConfigurationService;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.MetadataManagementService;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceType;
import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder;
import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.dao.util.MetadataConstants;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class DeviceTaskConfigurationServiceImpl implements DeviceTaskConfigurationService {
private static final Log log = LogFactory.getLog(DeviceTaskConfigurationServiceImpl.class);
private final MetadataManagementService metadataManagementService;
private static DeviceTaskConfigurationServiceImpl instance;
Review

Make volatile

Make volatile
private static final Cache<String, DeviceFrequencyMap> cache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS)
.build();
private DeviceTaskConfigurationServiceImpl() {
this.metadataManagementService = new MetadataManagementServiceImpl();
}
public static synchronized DeviceTaskConfigurationServiceImpl getInstance() {
if (instance == null) {
instance = new DeviceTaskConfigurationServiceImpl();
}
return instance;
}
private Metadata constructTaskFrequencyMetadata(Map<String, Integer> deviceFrequencies) {
JsonObject jsonObject = new JsonObject();
pramilaniroshan marked this conversation as resolved
Review

Move declaration out side the loop.

Move declaration out side the loop.

this deviceObject should be created for each entry in the deviceFrequencies map; otherwise,it'll adding the same deviceObject/frequencies for all device types

this deviceObject should be created for each entry in the deviceFrequencies map; otherwise,it'll adding the same deviceObject/frequencies for all device types
int frequency;
for (Map.Entry<String, Integer> entry : deviceFrequencies.entrySet()) {
String deviceType = entry.getKey();
frequency = entry.getValue();
JsonObject deviceObject = new JsonObject();
deviceObject.addProperty("frequency", String.valueOf(frequency));
jsonObject.add(deviceType, deviceObject);
}
Metadata metadata = new Metadata();
metadata.setMetaKey(MetadataConstants.DEVICE_TASK_FREQUENCY);
metadata.setMetaValue(jsonObject.toString());
return metadata;
}
/**
* Retrieves the default task frequency for a specific device type using device type xml.
*
* @param dms the DeviceManagementProviderService used to fetch the device monitoring configuration.
* @param deviceType the type of the device for which the frequency is being retrieved.
* @return the task frequency for the specified device type.
* @throws DeviceManagementException if the frequency configuration is not found for the specified device type.
*/
private int getDefaultTaskFrequency(DeviceManagementProviderService dms, String deviceType) throws DeviceManagementException {
OperationMonitoringTaskConfig operationMonitoringTaskConfig = dms.getDeviceMonitoringConfig(deviceType);
if (operationMonitoringTaskConfig == null) {
log.error("Frequency configuration not found for device type: " + deviceType);
throw new DeviceManagementException("Frequency configuration not found for device type: " + deviceType);
}
return operationMonitoringTaskConfig.getFrequency();
}
@Override
public void addDefaultTaskFrequency(int tenantId) throws MetadataManagementException {
try {
Map<String, Integer> deviceFrequencies = new HashMap<>();
DeviceManagementProviderService dms = DeviceManagementDataHolder.getInstance().getDeviceManagementProvider();
List<DeviceType> deviceTypes = dms.getDeviceTypes();
for (DeviceType deviceType : deviceTypes) {
deviceFrequencies.put(deviceType.getName(), getDefaultTaskFrequency(dms, deviceType.getName()));
}
addMetaData(deviceFrequencies, tenantId);
} catch (DeviceManagementException e) {
log.error("Error occurred while trying to obtain device types.", e);
} catch (MetadataKeyAlreadyExistsException e) {
log.error("Specified metaKey is already exist.", e);
}
}
@Override
public void addTaskFrequency(int tenantId, int frequency, String deviceType) throws MetadataManagementException {
try {
Map<String, Integer> deviceFrequencies = new HashMap<>();
deviceFrequencies.put(deviceType, frequency);
addMetaData(deviceFrequencies, tenantId);
} catch (MetadataKeyAlreadyExistsException e) {
log.error("Specified metaKey is already exist.", e);
}
}
/**
* Loads the device frequency map from the metadata management service.
*
* @return the device frequency map parsed from the stored metadata.
* @throws MetadataManagementException if an error occurs while retrieving the metadata.
*/
private DeviceFrequencyMap loadDeviceFrequencyMap() throws MetadataManagementException {
Metadata metadata = metadataManagementService.retrieveMetadata(MetadataConstants.DEVICE_TASK_FREQUENCY);
String metaValue = metadata.getMetaValue();
Gson gson = new Gson();
return gson.fromJson(metaValue, DeviceFrequencyMap.class);
}
/**
* Adds metadata for device frequencies to the metadata management service.
*
* @param deviceFrequencies a map containing device types as keys and their corresponding frequencies as values.
* @param tenantId the tenant ID for which the metadata is being added.
* @throws MetadataManagementException if there is an error managing the metadata.
* @throws MetadataKeyAlreadyExistsException if the metadata key already exists.
*/
private void addMetaData(Map<String, Integer> deviceFrequencies, int tenantId) throws MetadataManagementException, MetadataKeyAlreadyExistsException {
Metadata taskFrequencyMetadata = constructTaskFrequencyMetadata(deviceFrequencies);
taskFrequencyMetadata.setMetaKey(MetadataConstants.DEVICE_TASK_FREQUENCY);
metadataManagementService.createMetadata(taskFrequencyMetadata, tenantId);
}
@Override
public int getTaskFrequency(String deviceType, int tenantId) throws MetadataManagementException {
DeviceFrequencyMap deviceFrequencyMap = cache.getIfPresent(Integer.toString(tenantId));
if (deviceFrequencyMap == null) {
deviceFrequencyMap = loadDeviceFrequencyMap();
cache.put(Integer.toString(tenantId), deviceFrequencyMap);
}
if (deviceFrequencyMap.containsKey(deviceType)) {
return deviceFrequencyMap.get(deviceType).getFrequency();
} else {
log.error("Device type not found: " + deviceType);
throw new MetadataManagementException("Device type not found: " + deviceType);
}
}
}

@ -54,10 +54,20 @@ public class MetadataManagementServiceImpl implements MetadataManagementService
@Override @Override
public Metadata createMetadata(Metadata metadata) public Metadata createMetadata(Metadata metadata)
throws MetadataManagementException, MetadataKeyAlreadyExistsException { throws MetadataManagementException, MetadataKeyAlreadyExistsException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
return createMetadata(tenantId, metadata);
}
@Override
public Metadata createMetadata(Metadata metadata, int tenantId)
throws MetadataManagementException, MetadataKeyAlreadyExistsException {
return createMetadata(tenantId, metadata);
}
private Metadata createMetadata (int tenantId, Metadata metadata) throws MetadataManagementException, MetadataKeyAlreadyExistsException {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Creating Metadata : [" + metadata.toString() + "]"); log.debug("Creating Metadata : [" + metadata.toString() + "]");
} }
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
try { try {
MetadataManagementDAOFactory.beginTransaction(); MetadataManagementDAOFactory.beginTransaction();
if (metadataDAO.isExist(tenantId, metadata.getMetaKey())) { if (metadataDAO.isExist(tenantId, metadata.getMetaKey())) {

@ -0,0 +1,70 @@
/*
* Copyright (c) 2018 - 2024, 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 io.entgra.device.mgt.core.device.mgt.core.metadata.mgt;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceTaskConfigurationService;
import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.user.api.Tenant;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
public class TaskConfigurationStartupHandler implements ServerStartupObserver {
private static final Log log = LogFactory.getLog(TaskConfigurationStartupHandler.class);
@Override
public void completingServerStartup() {
}
@Override
public void completedServerStartup() {
rajitha marked this conversation as resolved
Review

In here, frequencies are setting back to the default frequencies on every server startup. Isn't this an issue?

In here, frequencies are setting back to the default frequencies on every server startup. Isn't this an issue?

No. we checking if task frequencies already added or not, this run when migration happen

if (!metadataDAO.isExist(tenantId, MetadataConstants.DEVICE_TASK_FREQUENCY))

No. we checking if task frequencies already added or not, this run when migration happen if (!metadataDAO.isExist(tenantId, MetadataConstants.DEVICE_TASK_FREQUENCY))
Review

Can't we use already existing 'completedServerStartup' listener?

Can't we use already existing 'completedServerStartup' listener?
Review

Got it :)

Got it :)

yes we can, but i decided to create a new one with new thread

yes we can, but i decided to create a new one with new thread
Thread t = new Thread(new Runnable() {
@Override
public void run() {
DeviceTaskConfigurationService deviceTaskConfigurationService = DeviceTaskConfigurationServiceImpl.getInstance();
RealmService realmService = DeviceManagementDataHolder.getInstance().getRealmService();
if (log.isDebugEnabled()) {
log.debug("Server has just started, hence started adding default task frequencies");
}
try {
deviceTaskConfigurationService.addDefaultTaskFrequency(MultitenantConstants.SUPER_TENANT_ID);
Tenant[] tenantArray = realmService.getTenantManager().getAllTenants();
pramilaniroshan marked this conversation as resolved
Review

From this call, doesn't it return super tenant details?

From this call, doesn't it return super tenant details?

No. It's doesn't return super tenant details

No. It's doesn't return super tenant details
if (tenantArray != null) {
for (Tenant tenant : tenantArray) {
deviceTaskConfigurationService.addDefaultTaskFrequency(tenant.getId());
}
}
} catch (MetadataManagementException e) {
String msg = "Error occurred while adding default task frequency metadata entry.";
pramilaniroshan marked this conversation as resolved
Review

It is not required to assign the log message to variable since there is only one usage.

It is not required to assign the log message to variable since there is only one usage.
log.error(msg, e);
} catch (UserStoreException e) {
log.error("Error occurred while trying to get the available tenants.", e);
}
log.info("Finish adding default task frequencies");
}
});
t.start();
}
}

@ -23,4 +23,5 @@ public class MetadataConstants {
public static final String ALLOWED_DEVICE_STATUS_META_KEY = "allowed_device_status"; public static final String ALLOWED_DEVICE_STATUS_META_KEY = "allowed_device_status";
public static final String IS_DEVICE_STATUS_CHECK_META_KEY = "device-status-check"; public static final String IS_DEVICE_STATUS_CHECK_META_KEY = "device-status-check";
public static final String DEVICE_TASK_FREQUENCY = "device_task_frequency";
} }

@ -20,6 +20,7 @@
package io.entgra.device.mgt.core.device.mgt.core.task; package io.entgra.device.mgt.core.device.mgt.core.task;
import io.entgra.device.mgt.core.device.mgt.common.DynamicTaskContext; import io.entgra.device.mgt.core.device.mgt.common.DynamicTaskContext;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
public interface DeviceTaskManager { public interface DeviceTaskManager {
@ -58,7 +59,7 @@ public interface DeviceTaskManager {
* This method will add the operations to devices * This method will add the operations to devices
* @throws DeviceMgtTaskException * @throws DeviceMgtTaskException
*/ */
void addOperations(DynamicTaskContext dynamicTaskContext) throws DeviceMgtTaskException; void addOperations(DynamicTaskContext dynamicTaskContext, int frequency) throws DeviceMgtTaskException, MetadataManagementException;
// /** // /**

@ -19,33 +19,34 @@
package io.entgra.device.mgt.core.device.mgt.core.task; package io.entgra.device.mgt.core.device.mgt.core.task;
import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig; import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceTaskManagerWrapper;
import io.entgra.device.mgt.core.task.mgt.common.exception.TaskManagementException;
import io.entgra.device.mgt.core.task.mgt.common.exception.TaskNotFoundException;
public interface DeviceTaskManagerService { public interface DeviceTaskManagerService {
/** /**
* This method will start the task. * This method will start the task.
* @param operationMonitoringTaskConfig - OperationMonitoringTaskConfig * @param deviceTaskManagerWrapper - DeviceTaskManagerWrapper
* @throws DeviceMgtTaskException * @throws DeviceMgtTaskException
*/ */
void startTask(String deviceType, OperationMonitoringTaskConfig operationMonitoringTaskConfig) void startTask(DeviceTaskManagerWrapper deviceTaskManagerWrapper)
throws DeviceMgtTaskException; throws DeviceMgtTaskException;
/** /**
* This method will stop the task. * This method will stop the task.
* @param operationMonitoringTaskConfig - OperationMonitoringTaskConfig
* @throws DeviceMgtTaskException * @throws DeviceMgtTaskException
*/ */
void stopTask(String deviceType, OperationMonitoringTaskConfig operationMonitoringTaskConfig) void stopTask(int taskId)
throws DeviceMgtTaskException; throws DeviceMgtTaskException;
/** /**
* This will update the task frequency which it runs. * This will update the task frequency which it runs.
* @param operationMonitoringTaskConfig - OperationMonitoringTaskConfig * @param deviceTaskManagerWrapper - DeviceTaskManagerWrapper
* @throws DeviceMgtTaskException * @throws DeviceMgtTaskException
*/ */
void updateTask(String deviceType, OperationMonitoringTaskConfig operationMonitoringTaskConfig) void updateTask(int taskId,DeviceTaskManagerWrapper deviceTaskManagerWrapper)
throws DeviceMgtTaskException; throws DeviceMgtTaskException, TaskNotFoundException, TaskManagementException;
} }

@ -18,6 +18,9 @@
package io.entgra.device.mgt.core.device.mgt.core.task; package io.entgra.device.mgt.core.device.mgt.core.task;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceTaskConfigurationService;
import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.DeviceTaskConfigurationServiceImpl;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import java.util.ArrayList; import java.util.ArrayList;
@ -67,4 +70,10 @@ public class Utils {
} }
} }
public static int getTenantedTaskFrequency(int tenantId, String deviceType) throws MetadataManagementException {
DeviceTaskConfigurationService deviceTaskConfigurationService = DeviceTaskConfigurationServiceImpl.getInstance();
return deviceTaskConfigurationService.getTaskFrequency(deviceType, tenantId);
}
} }

@ -18,13 +18,21 @@
package io.entgra.device.mgt.core.device.mgt.core.task.impl; package io.entgra.device.mgt.core.device.mgt.core.task.impl;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.core.task.Utils;
import io.entgra.device.mgt.core.task.mgt.common.bean.DynamicTask;
import io.entgra.device.mgt.core.task.mgt.common.constant.TaskMgtConstants;
import io.entgra.device.mgt.core.task.mgt.common.exception.TaskManagementException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig; import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig;
import io.entgra.device.mgt.core.device.mgt.common.StartupOperationConfig; import io.entgra.device.mgt.core.device.mgt.common.StartupOperationConfig;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder; import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService; import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import io.entgra.device.mgt.core.device.mgt.core.task.DeviceMgtTaskException; import io.entgra.device.mgt.core.device.mgt.core.task.DeviceMgtTaskException;
import io.entgra.device.mgt.core.device.mgt.core.task.DeviceTaskManager; import io.entgra.device.mgt.core.device.mgt.core.task.DeviceTaskManager;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.base.MultitenantConstants;
@ -40,44 +48,65 @@ public class DeviceDetailsRetrieverTask extends DynamicPartitionedScheduleTask {
@Override @Override
public void executeDynamicTask() { public void executeDynamicTask() {
deviceType = getProperty("DEVICE_TYPE"); String taskId = getProperty(TaskMgtConstants.Task.DYNAMIC_TASK_ID);
String taskName = getProperty(TaskMgtConstants.Task.LOCAL_TASK_NAME);
if (StringUtils.isEmpty(taskId)) {
log.warn("Not executing the task as Task ID is undefined");
if (log.isDebugEnabled()) {
log.debug("[Undefined Task] Task Name: " + taskName);
}
return;
}
DynamicTask dynamicTask;
try {
dynamicTask = DeviceManagementDataHolder.getInstance().getTaskManagementService()
.getDynamicTask(Integer.parseInt(taskId));
} catch (TaskManagementException e) {
log.error("Task [" + taskId + "] " + taskName
+ " won't execute as unable to get task management service.", e);
return;
}
if (dynamicTask == null) {
log.error("Task [" + taskId + "] " + taskName
+ " won't execute as definition not available in the database.");
return;
}
deviceType = dynamicTask.getProperties().get("DEVICE_TYPE");
int tenantId = dynamicTask.getTenantId();
deviceManagementProviderService = DeviceManagementDataHolder.getInstance() deviceManagementProviderService = DeviceManagementDataHolder.getInstance()
.getDeviceManagementProvider(); .getDeviceManagementProvider();
OperationMonitoringTaskConfig operationMonitoringTaskConfig = deviceManagementProviderService OperationMonitoringTaskConfig operationMonitoringTaskConfig = deviceManagementProviderService
.getDeviceMonitoringConfig(deviceType); .getDeviceMonitoringConfig(deviceType);
StartupOperationConfig startupOperationConfig = deviceManagementProviderService StartupOperationConfig startupOperationConfig = deviceManagementProviderService
.getStartupOperationConfig(deviceType); .getStartupOperationConfig(deviceType);
this.executeForAllTenants(operationMonitoringTaskConfig, startupOperationConfig); this.executeForATenant(operationMonitoringTaskConfig, startupOperationConfig, tenantId);
} }
private void executeForAllTenants(OperationMonitoringTaskConfig operationMonitoringTaskConfig, private void executeForATenant(OperationMonitoringTaskConfig operationMonitoringTaskConfig,
StartupOperationConfig startupOperationConfig) { StartupOperationConfig startupOperationConfig,int tenantId) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Device details retrieving task started to run for all tenants."); log.debug("Device details retrieving task started to run for tenant " + tenantId);
} }
try { try {
List<Integer> tenants = DeviceManagementDataHolder.getInstance(). try {
getDeviceManagementProvider().getDeviceEnrolledTenants(); PrivilegedCarbonContext.startTenantFlow();
if (log.isDebugEnabled()) { PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
log.debug("Task is running for " + tenants.size() + " tenants and the device type is " + deviceType); this.executeTask(operationMonitoringTaskConfig, startupOperationConfig, Utils.getTenantedTaskFrequency(tenantId, deviceType));
} finally {
PrivilegedCarbonContext.endTenantFlow();
} }
for (Integer tenant : tenants) { if (log.isDebugEnabled()) {
if (MultitenantConstants.SUPER_TENANT_ID == tenant) { log.debug("Task is running for " + tenantId+ " tenants and the device type is " + deviceType);
this.executeTask(operationMonitoringTaskConfig, startupOperationConfig);
continue;
}
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenant, true);
this.executeTask(operationMonitoringTaskConfig, startupOperationConfig);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
} }
} catch (DeviceManagementException e) { } catch (MetadataManagementException e) {
log.error("Error occurred while trying to get the available tenants " + String msg = "Error occurred while getting task frequency metadata entry.";
"from device manager provider service.", e); log.error(msg, e);
} }
} }
@ -87,7 +116,7 @@ public class DeviceDetailsRetrieverTask extends DynamicPartitionedScheduleTask {
* @param startupOperationConfig which contains startup operations and realted details * @param startupOperationConfig which contains startup operations and realted details
*/ */
private void executeTask(OperationMonitoringTaskConfig operationMonitoringTaskConfig, private void executeTask(OperationMonitoringTaskConfig operationMonitoringTaskConfig,
StartupOperationConfig startupOperationConfig) { StartupOperationConfig startupOperationConfig, int frequency) {
DeviceTaskManager deviceTaskManager = new DeviceTaskManagerImpl(deviceType, DeviceTaskManager deviceTaskManager = new DeviceTaskManagerImpl(deviceType,
operationMonitoringTaskConfig, operationMonitoringTaskConfig,
startupOperationConfig); startupOperationConfig);
@ -97,11 +126,14 @@ public class DeviceDetailsRetrieverTask extends DynamicPartitionedScheduleTask {
//pass the configurations also from here, monitoring tasks //pass the configurations also from here, monitoring tasks
try { try {
if (deviceManagementProviderService.isDeviceMonitoringEnabled(deviceType)) { if (deviceManagementProviderService.isDeviceMonitoringEnabled(deviceType)) {
deviceTaskManager.addOperations(getTaskContext()); deviceTaskManager.addOperations(getTaskContext(), frequency);
} }
} catch (DeviceMgtTaskException e) { } catch (DeviceMgtTaskException e) {
log.error("Error occurred while trying to add the operations to " + log.error("Error occurred while trying to add the operations to " +
"device to retrieve device details.", e); "device to retrieve device details.", e);
} catch (MetadataManagementException e) {
String msg = "Error occurred while getting task frequency metadata entry.";
log.error(msg, e);
} }
} }

@ -92,11 +92,11 @@ public class DeviceTaskManagerImpl implements DeviceTaskManager {
@Override @Override
public void addOperations(DynamicTaskContext dynamicTaskContext) throws DeviceMgtTaskException { public void addOperations(DynamicTaskContext dynamicTaskContext, int frequency) throws DeviceMgtTaskException {
DeviceManagementProviderService deviceManagementProviderService = DeviceManagementDataHolder.getInstance(). DeviceManagementProviderService deviceManagementProviderService = DeviceManagementDataHolder.getInstance().
getDeviceManagementProvider(); getDeviceManagementProvider();
//list operations for device type //list operations for device type
List<String> operations = this.getValidOperationNames(); List<String> operations = this.getValidOperationNames(frequency);
if (operations.isEmpty()) { if (operations.isEmpty()) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("No operations are available."); log.debug("No operations are available.");
@ -117,12 +117,11 @@ public class DeviceTaskManagerImpl implements DeviceTaskManager {
} }
} }
private List<String> getValidOperationNames() throws DeviceMgtTaskException { private List<String> getValidOperationNames(int frequency) throws DeviceMgtTaskException {
List<MonitoringOperation> monitoringOperations = this.getOperationList(); List<MonitoringOperation> monitoringOperations = this.getOperationList();
List<String> opNames = new ArrayList<>(); List<String> opNames = new ArrayList<>();
Long milliseconds = System.currentTimeMillis(); Long milliseconds = System.currentTimeMillis();
int frequency = this.getTaskFrequency();
Map<String, Long> mp = Utils.getTenantedTaskOperationMap(map, deviceType); Map<String, Long> mp = Utils.getTenantedTaskOperationMap(map, deviceType);
for (MonitoringOperation top : monitoringOperations) { for (MonitoringOperation top : monitoringOperations) {

@ -20,6 +20,14 @@
package io.entgra.device.mgt.core.device.mgt.core.task.impl; package io.entgra.device.mgt.core.device.mgt.core.task.impl;
import com.google.gson.Gson; import com.google.gson.Gson;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceTaskManagerWrapper;
import io.entgra.device.mgt.core.task.mgt.common.bean.DynamicTask;
import io.entgra.device.mgt.core.task.mgt.common.exception.TaskManagementException;
import io.entgra.device.mgt.core.task.mgt.common.exception.TaskNotFoundException;
import io.entgra.device.mgt.core.task.mgt.common.spi.TaskManagementService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig; import io.entgra.device.mgt.core.device.mgt.common.OperationMonitoringTaskConfig;
import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder; import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder;
import io.entgra.device.mgt.core.device.mgt.core.task.DeviceMgtTaskException; import io.entgra.device.mgt.core.device.mgt.core.task.DeviceMgtTaskException;
@ -39,122 +47,77 @@ public class DeviceTaskManagerServiceImpl implements DeviceTaskManagerService {
public static final String TASK_TYPE = "DEVICE_MONITORING"; public static final String TASK_TYPE = "DEVICE_MONITORING";
public static final String TENANT_ID = "TENANT_ID"; public static final String TENANT_ID = "TENANT_ID";
private static String TASK_CLASS = "io.entgra.device.mgt.core.device.mgt.core.task.impl.DeviceDetailsRetrieverTask"; public static final String SCHEDULED_BY = "SCHEDULED_BY";
public static final String SCHEDULED_ON = "SCHEDULED_ON";
public static final String DEVICE_TYPE = "DEVICE_TYPE";
public static final String OPPCONFIG = "OPPCONFIG";
private final TaskManagementService taskManagementService = DeviceManagementDataHolder.getInstance().getTaskManagementService();;
// private DeviceTaskManager deviceTaskManager;
private static Log log = LogFactory.getLog(DeviceTaskManagerServiceImpl.class); private static Log log = LogFactory.getLog(DeviceTaskManagerServiceImpl.class);
@Override @Override
public void startTask(String deviceType, OperationMonitoringTaskConfig operationMonitoringTaskConfig) public void startTask(DeviceTaskManagerWrapper deviceTaskManagerWrapper)
throws DeviceMgtTaskException { throws DeviceMgtTaskException {
log.info("Task adding for " + deviceType);
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
try { try {
TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService(); PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
taskService.registerTaskType(TASK_TYPE);
if (log.isDebugEnabled()) {
log.debug("Device details retrieving task is started for the tenant id " + tenantId);
// log.debug("Device details retrieving task is at frequency of : " + deviceTaskManager
// .getTaskFrequency());
log.debug(
"Device details retrieving task is at frequency of : " + operationMonitoringTaskConfig
.getFrequency());
}
TaskManager taskManager = taskService.getTaskManager(TASK_TYPE);
TaskInfo.TriggerInfo triggerInfo = new TaskInfo.TriggerInfo();
// triggerInfo.setIntervalMillis(deviceTaskManager.getTaskFrequency());
triggerInfo.setIntervalMillis(operationMonitoringTaskConfig.getFrequency());
triggerInfo.setRepeatCount(-1);
Gson gson = new Gson(); Gson gson = new Gson();
String operationConfigs = gson.toJson(operationMonitoringTaskConfig); String operationConfigs = gson.toJson(deviceTaskManagerWrapper.getOperationMonitoringTaskConfig());
Map<String, String> taskProperties = new HashMap<>();
Map<String, String> properties = new HashMap<>(); taskProperties.put(TENANT_ID,String.valueOf(carbonContext.getTenantId()));
taskProperties.put(SCHEDULED_BY,carbonContext.getUsername());
properties.put(TENANT_ID, String.valueOf(tenantId)); taskProperties.put(SCHEDULED_ON,String.valueOf(System.currentTimeMillis()));
properties.put("DEVICE_TYPE", deviceType); taskProperties.put(DEVICE_TYPE, deviceTaskManagerWrapper.getDeviceType());
properties.put("OPPCONFIG", operationConfigs); taskProperties.put(TASK_TYPE,TASK_TYPE);
taskProperties.put(OPPCONFIG,operationConfigs);
String taskName = deviceType + String.valueOf(tenantId);
DynamicTask dynamicTask = new DynamicTask();
if (!taskManager.isTaskScheduled(deviceType)) { dynamicTask.setTaskClassName(DeviceDetailsRetrieverTask.class.getName());
dynamicTask.setCronExpression(deviceTaskManagerWrapper.getOperationMonitoringTaskConfig().getCronExpression());
TaskInfo taskInfo = new TaskInfo(taskName, TASK_CLASS, properties, triggerInfo); dynamicTask.setEnabled(true);
dynamicTask.setName(deviceTaskManagerWrapper.getDeviceType() + carbonContext.getTenantId());
taskManager.registerTask(taskInfo); dynamicTask.setProperties(taskProperties);
taskManager.rescheduleTask(taskInfo.getName()); if(!taskManagementService.isTaskExist(dynamicTask.getName())){
} else { taskManagementService.createTask(dynamicTask);
throw new DeviceMgtTaskException(
"Device details retrieving task is already started for this tenant " + tenantId);
} }
log.info("Task adding for " + deviceTaskManagerWrapper.getDeviceType() + " tenant " + carbonContext.getTenantId());
} catch (TaskException e) { } catch (TaskManagementException e) {
throw new DeviceMgtTaskException("Error occurred while creating the task for tenant " + tenantId, throw new DeviceMgtTaskException("Error occurred while creating the task for tenant ", e);
e);
} }
} }
@Override @Override
public void stopTask(String deviceType, OperationMonitoringTaskConfig operationMonitoringTaskConfig) public void stopTask(int taskId)
throws DeviceMgtTaskException { throws DeviceMgtTaskException {
try { try {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); taskManagementService.deleteTask(taskId);
TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService(); } catch (TaskManagementException e) {
if (taskService != null && taskService.isServerInit()) { String msg = "Error occurred while retrieving task manager to delete task '" + taskId + "'";
TaskManager taskManager = taskService.getTaskManager(TASK_TYPE); log.error(msg);
String taskName = deviceType + tenantId; throw new DeviceMgtTaskException(msg, e);
taskManager.deleteTask(taskName); } catch (TaskNotFoundException e) {
} String msg = "Task '" + taskId + "' not found while deleting the task";
} catch (TaskException e) { log.error(msg, e);
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); throw new DeviceMgtTaskException(msg, e);
throw new DeviceMgtTaskException("Error occurred while deleting the task for tenant " + tenantId,
e);
} }
} }
@Override @Override
public void updateTask(String deviceType, OperationMonitoringTaskConfig operationMonitoringTaskConfig) public void updateTask(int taskId, DeviceTaskManagerWrapper deviceTaskManagerWrapper)
throws DeviceMgtTaskException { throws DeviceMgtTaskException, TaskNotFoundException, TaskManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
// deviceTaskManager = new DeviceTaskManagerImpl();
try { try {
TaskService taskService = DeviceManagementDataHolder.getInstance().getTaskService(); DynamicTask dynamicTask = taskManagementService.getDynamicTask(taskId);
TaskManager taskManager = taskService.getTaskManager(TASK_TYPE); dynamicTask.setEnabled(true);
dynamicTask.setCronExpression(deviceTaskManagerWrapper.getCron());
if (taskManager.isTaskScheduled(deviceType)) { taskManagementService.updateTask(taskId,dynamicTask);
String taskName = deviceType + tenantId; } catch (TaskManagementException e) {
taskManager.deleteTask(taskName); String msg = "Error occurred while updating task '" + taskId + "'";
TaskInfo.TriggerInfo triggerInfo = new TaskInfo.TriggerInfo(); log.error(msg);
triggerInfo.setIntervalMillis(operationMonitoringTaskConfig.getFrequency()); } catch (TaskNotFoundException e) {
triggerInfo.setRepeatCount(-1); String msg = "Task '" + taskId + "' not found while updating the task";
log.error(msg, e);
Map<String, String> properties = new HashMap<>();
properties.put(TENANT_ID, String.valueOf(tenantId));
TaskInfo taskInfo = new TaskInfo(taskName, TASK_CLASS, properties, triggerInfo);
taskManager.registerTask(taskInfo);
taskManager.rescheduleTask(taskInfo.getName());
} else {
throw new DeviceMgtTaskException(
"Device details retrieving task has not been started for this tenant " +
tenantId + ". Please start the task first.");
}
} catch (TaskException e) {
throw new DeviceMgtTaskException("Error occurred while updating the task for tenant " + tenantId,
e);
} }
} }
} }

@ -18,6 +18,8 @@
package io.entgra.device.mgt.core.device.mgt.core.task; package io.entgra.device.mgt.core.device.mgt.core.task;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException; import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceTaskConfigurationService;
import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.DeviceTaskConfigurationServiceImpl;
import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService; import io.entgra.device.mgt.core.server.bootup.heartbeat.beacon.service.HeartBeatManagementService;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -59,6 +61,7 @@ public class DeviceTaskManagerTest extends BaseDeviceManagementTest {
private static final Log log = LogFactory.getLog(DeviceTaskManagerTest.class); private static final Log log = LogFactory.getLog(DeviceTaskManagerTest.class);
private static final String NEW_DEVICE_TYPE = "NEW-DEVICE-TYPE"; private static final String NEW_DEVICE_TYPE = "NEW-DEVICE-TYPE";
private static final int FREQUENCY = 60000;
private List<DeviceIdentifier> deviceIds; private List<DeviceIdentifier> deviceIds;
private DeviceTaskManager deviceTaskManager; private DeviceTaskManager deviceTaskManager;
private DeviceManagementProviderService deviceMgtProviderService; private DeviceManagementProviderService deviceMgtProviderService;
@ -117,9 +120,9 @@ public class DeviceTaskManagerTest extends BaseDeviceManagementTest {
} }
@Test(groups = "Device Task Manager Test Group", description = "Testing adding operations to devices.") @Test(groups = "Device Task Manager Test Group", description = "Testing adding operations to devices.")
public void testAddOperation() throws DeviceMgtTaskException, OperationManagementException { public void testAddOperation() throws DeviceMgtTaskException, OperationManagementException, MetadataManagementException {
log.info("Attempting to add operations for devices."); log.info("Attempting to add operations for devices.");
this.deviceTaskManager.addOperations(null); this.deviceTaskManager.addOperations(null,FREQUENCY);
for (DeviceIdentifier deviceId : deviceIds) { for (DeviceIdentifier deviceId : deviceIds) {
List<? extends Operation> operationList = this.operationManager.getOperations(deviceId); List<? extends Operation> operationList = this.operationManager.getOperations(deviceId);
Assert.assertNotNull(operationList); Assert.assertNotNull(operationList);
@ -130,25 +133,27 @@ public class DeviceTaskManagerTest extends BaseDeviceManagementTest {
@Test(groups = "Device Task Manager Test Group", @Test(groups = "Device Task Manager Test Group",
description = "Testing adding operations when no devices are available") description = "Testing adding operations when no devices are available")
public void testAddOperationsWithoutDevices() throws DeviceManagementException, DeviceMgtTaskException { public void testAddOperationsWithoutDevices() throws DeviceManagementException, DeviceMgtTaskException, MetadataManagementException {
this.deviceMgtProviderService.registerDeviceType( this.deviceMgtProviderService.registerDeviceType(
new TestDeviceManagementService(NEW_DEVICE_TYPE, TestDataHolder.SUPER_TENANT_DOMAIN)); new TestDeviceManagementService(NEW_DEVICE_TYPE, TestDataHolder.SUPER_TENANT_DOMAIN));
DeviceTaskManager taskManager = new DeviceTaskManagerImpl(NEW_DEVICE_TYPE, DeviceTaskManager taskManager = new DeviceTaskManagerImpl(NEW_DEVICE_TYPE,
TestDataHolder.generateMonitoringTaskConfig(true, 50000, 3)); TestDataHolder.generateMonitoringTaskConfig(true, 50000, 3));
taskManager.addOperations(null); taskManager.addOperations(null, FREQUENCY);
} }
@Test(groups = "Device Task Manager Test Group", dependsOnMethods = "testAddOperationsWithoutDevices", @Test(groups = "Device Task Manager Test Group", dependsOnMethods = "testAddOperationsWithoutDevices",
description = "Testing adding operations when no operations are scheduled") description = "Testing adding operations when no operations are scheduled")
public void testAddOperationsWithoutOperations() throws DeviceMgtTaskException { public void testAddOperationsWithoutOperations() throws DeviceMgtTaskException, MetadataManagementException {
DeviceTaskManager taskManager = new DeviceTaskManagerImpl(NEW_DEVICE_TYPE, DeviceTaskManager taskManager = new DeviceTaskManagerImpl(NEW_DEVICE_TYPE,
TestDataHolder.generateMonitoringTaskConfig(true, 50000, 3)); TestDataHolder.generateMonitoringTaskConfig(true, 50000, 3));
taskManager.addOperations(null); taskManager.addOperations(null, FREQUENCY);
} }
@Test(groups = "Device Task Manager Test Group", description = "Testing device detail retriever task execution") @Test(groups = "Device Task Manager Test Group", description = "Testing device detail retriever task execution")
public void testDeviceDetailRetrieverTaskExecute() throws OperationManagementException { public void testDeviceDetailRetrieverTaskExecute() throws OperationManagementException, MetadataManagementException {
DeviceDetailsRetrieverTask deviceDetailsRetrieverTask = new DeviceDetailsRetrieverTask(); DeviceDetailsRetrieverTask deviceDetailsRetrieverTask = new DeviceDetailsRetrieverTask();
DeviceTaskConfigurationService deviceTaskConfigurationService = DeviceTaskConfigurationServiceImpl.getInstance();
deviceTaskConfigurationService.addTaskFrequency(MultitenantConstants.SUPER_TENANT_ID, FREQUENCY,TestDataHolder.TEST_DEVICE_TYPE);
Map<String, String> map = new HashMap<>(); Map<String, String> map = new HashMap<>();
map.put("DEVICE_TYPE", TestDataHolder.TEST_DEVICE_TYPE); map.put("DEVICE_TYPE", TestDataHolder.TEST_DEVICE_TYPE);
deviceDetailsRetrieverTask.setProperties(map); deviceDetailsRetrieverTask.setProperties(map);

@ -124,6 +124,7 @@ public class DeviceTypeManagerService implements DeviceManagementService {
if (taskConfiguration != null) { if (taskConfiguration != null) {
operationMonitoringConfigs.setEnabled(taskConfiguration.isEnabled()); operationMonitoringConfigs.setEnabled(taskConfiguration.isEnabled());
operationMonitoringConfigs.setFrequency(taskConfiguration.getFrequency()); operationMonitoringConfigs.setFrequency(taskConfiguration.getFrequency());
operationMonitoringConfigs.setCronExpression(taskConfiguration.getCronExpression());
List<TaskConfiguration.Operation> ops = taskConfiguration.getOperations(); List<TaskConfiguration.Operation> ops = taskConfiguration.getOperations();
if (ops != null && !ops.isEmpty()) { if (ops != null && !ops.isEmpty()) {
monitoringOperations = new ArrayList<>(); monitoringOperations = new ArrayList<>();

@ -32,6 +32,16 @@ public class TaskConfiguration {
private boolean enabled; private boolean enabled;
private int frequency; private int frequency;
private List<Operation> operations; private List<Operation> operations;
private String cronExpression;
@XmlElement(name = "cronExpression", required = true)
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
@XmlElement(name = "Enable", required = true) @XmlElement(name = "Enable", required = true)
public boolean isEnabled() { public boolean isEnabled() {

@ -43,4 +43,6 @@ public interface TaskManagementService {
DynamicTask getDynamicTask(int dynamicTaskId) throws TaskManagementException; DynamicTask getDynamicTask(int dynamicTaskId) throws TaskManagementException;
List<DynamicTask> getActiveDynamicTasks() throws TaskManagementException; List<DynamicTask> getActiveDynamicTasks() throws TaskManagementException;
boolean isTaskExist(String taskName) throws TaskManagementException;
} }

@ -41,4 +41,6 @@ public interface DynamicTaskDAO {
List<DynamicTask> getActiveDynamicTasks(int tenantId) throws TaskManagementDAOException; List<DynamicTask> getActiveDynamicTasks(int tenantId) throws TaskManagementDAOException;
boolean isTaskExist(String taskName, int tenantId) throws TaskManagementDAOException;
} }

@ -200,4 +200,27 @@ public class DynamicTaskDAOImpl implements DynamicTaskDAO {
return dynamicTasks; return dynamicTasks;
} }
@Override
public boolean isTaskExist(String taskName, int tenantId) throws TaskManagementDAOException {
PreparedStatement stmt;
ResultSet rs;
try {
Connection conn = TaskManagementDAOFactory.getConnection();
String sql = "SELECT COUNT(*) FROM DYNAMIC_TASK WHERE NAME = ? AND TENANT_ID = ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, taskName);
stmt.setInt(2, tenantId);
rs = stmt.executeQuery();
if (rs.next()) {
return rs.getInt(1) > 0;
}
return false;
} catch (SQLException e) {
String msg = "Error occurred while checking if task '" + taskName + "' exists";
log.error(msg, e);
throw new TaskManagementDAOException(msg, e);
}
}
} }

@ -93,8 +93,11 @@ public class TaskManagementServiceImpl implements TaskManagementService {
dynamicTaskPropDAO.addTaskProperties(dynamicTaskId, dynamicTask.getProperties(), tenantId); dynamicTaskPropDAO.addTaskProperties(dynamicTaskId, dynamicTask.getProperties(), tenantId);
try { try {
serverHashIdx = TaskManagerDataHolder.getInstance().getHeartBeatService() serverHashIdx = 0;
.getServerCtxInfo().getLocalServerHashIdx(); if(TaskManagerDataHolder.getInstance().getHeartBeatService().isTaskPartitioningEnabled()){
serverHashIdx = TaskManagerDataHolder.getInstance().getHeartBeatService()
.getServerCtxInfo().getLocalServerHashIdx();
}
nTaskName = TaskManagementUtil.generateNTaskName(dynamicTaskId, serverHashIdx); nTaskName = TaskManagementUtil.generateNTaskName(dynamicTaskId, serverHashIdx);
} catch (HeartBeatManagementException e) { } catch (HeartBeatManagementException e) {
String msg = "Unexpected exception when getting server hash index."; String msg = "Unexpected exception when getting server hash index.";
@ -136,7 +139,13 @@ public class TaskManagementServiceImpl implements TaskManagementService {
String msg = "Error occurred while scheduling task '" + dynamicTask.getName() + "'"; String msg = "Error occurred while scheduling task '" + dynamicTask.getName() + "'";
log.error(msg, e); log.error(msg, e);
throw new TaskManagementException(msg, e); throw new TaskManagementException(msg, e);
} finally { } catch (Exception e) {
TaskManagementDAOFactory.rollbackTransaction();
String msg = "Unexpected error occurred while scheduling task '" + dynamicTask.getName() + "'";
log.error(msg, e);
throw new TaskManagementException(msg, e);
}
finally {
TaskManagementDAOFactory.closeConnection(); TaskManagementDAOFactory.closeConnection();
} }
} }
@ -430,6 +439,28 @@ public class TaskManagementServiceImpl implements TaskManagementService {
return dynamicTasks; return dynamicTasks;
} }
@Override
public boolean isTaskExist(String taskName) throws TaskManagementException {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
try {
TaskManagementDAOFactory.beginTransaction();
if (log.isDebugEnabled()) {
log.debug("Fetching the details of all active dynamic tasks");
}
boolean taskExists = dynamicTaskDAO.isTaskExist(taskName, tenantId);
TaskManagementDAOFactory.commitTransaction();
return taskExists;
} catch (TaskManagementDAOException e) {
String msg = "Error occurred while fetching all active dynamic tasks";
log.error(msg, e);
throw new TaskManagementException(msg, e);
} catch (TransactionManagementException e) {
throw new RuntimeException(e);
} finally {
TaskManagementDAOFactory.closeConnection();
}
}
// check whether task exist in the ntask core // check whether task exist in the ntask core
private boolean isTaskExists(String taskName) throws TaskManagementException, TaskException { private boolean isTaskExists(String taskName) throws TaskManagementException, TaskException {
if (StringUtils.isEmpty(taskName)) { if (StringUtils.isEmpty(taskName)) {

@ -26,6 +26,8 @@ public interface TenantManagerService {
void addDefaultAppCategories(TenantInfoBean tenantInfoBean) throws TenantMgtException; void addDefaultAppCategories(TenantInfoBean tenantInfoBean) throws TenantMgtException;
void addDefaultDeviceStatusFilters(TenantInfoBean tenantInfoBean) throws TenantMgtException; void addDefaultDeviceStatusFilters(TenantInfoBean tenantInfoBean) throws TenantMgtException;
void addDefaultDeviceTaskConfiguration(TenantInfoBean tenantInfoBean) throws TenantMgtException;
void deleteTenantApplicationData(int tenantId) throws TenantMgtException; void deleteTenantApplicationData(int tenantId) throws TenantMgtException;
void deleteTenantDeviceData(int tenantId) throws TenantMgtException; void deleteTenantDeviceData(int tenantId) throws TenantMgtException;
void addDeviceDetailsRetrieverTask(TenantInfoBean tenantInfoBean) throws TenantMgtException;
} }

@ -17,6 +17,7 @@
*/ */
package io.entgra.device.mgt.core.tenant.mgt.core; package io.entgra.device.mgt.core.tenant.mgt.core;
import io.entgra.device.mgt.core.device.mgt.core.task.DeviceMgtTaskException;
import io.entgra.device.mgt.core.tenant.mgt.common.exception.TenantMgtException; import io.entgra.device.mgt.core.tenant.mgt.common.exception.TenantMgtException;
import org.wso2.carbon.stratos.common.beans.TenantInfoBean; import org.wso2.carbon.stratos.common.beans.TenantInfoBean;
@ -44,6 +45,13 @@ public interface TenantManager {
*/ */
void addDefaultDeviceStatusFilters(TenantInfoBean tenantInfoBean) throws TenantMgtException; void addDefaultDeviceStatusFilters(TenantInfoBean tenantInfoBean) throws TenantMgtException;
/**
* Add default device task configuration to a tenant described by the tenant info bean
* @param tenantInfoBean The info bean that provides tenant info
* @throws TenantMgtException Throws when error occurred while adding default TaskFrequency
*/
void addDefaultDeviceTaskConfiguration(TenantInfoBean tenantInfoBean) throws TenantMgtException;
/** /**
* Delete Application related details of a tenant * Delete Application related details of a tenant
* @param tenantId ID of the tenant * @param tenantId ID of the tenant
@ -58,4 +66,11 @@ public interface TenantManager {
*/ */
void deleteTenantDeviceData(int tenantId) throws TenantMgtException; void deleteTenantDeviceData(int tenantId) throws TenantMgtException;
/**
* Add deviceDetailsRetrieverTask of a tenant
* @param tenantInfoBean ID of the tenant
* @throws TenantMgtException Throws when deleting Tenant related device data
*/
void addDeviceDetailsRetrieverTask(TenantInfoBean tenantInfoBean) throws TenantMgtException;
} }

@ -20,6 +20,8 @@ package io.entgra.device.mgt.core.tenant.mgt.core.impl;
import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException; import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager; import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager;
import io.entgra.device.mgt.core.application.mgt.core.config.ConfigurationManager; import io.entgra.device.mgt.core.application.mgt.core.config.ConfigurationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.DeviceManagementException;
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException; import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
import io.entgra.device.mgt.core.device.mgt.common.permission.mgt.PermissionManagementException; import io.entgra.device.mgt.core.device.mgt.common.permission.mgt.PermissionManagementException;
import io.entgra.device.mgt.core.device.mgt.common.roles.config.Role; import io.entgra.device.mgt.core.device.mgt.common.roles.config.Role;
@ -30,6 +32,10 @@ import io.entgra.device.mgt.core.device.mgt.common.exceptions.TransactionManagem
import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOException;
import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory; import io.entgra.device.mgt.core.device.mgt.core.dao.DeviceManagementDAOFactory;
import io.entgra.device.mgt.core.device.mgt.core.dao.TenantDAO; import io.entgra.device.mgt.core.device.mgt.core.dao.TenantDAO;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceTaskManagerWrapper;
import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceType;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import io.entgra.device.mgt.core.device.mgt.core.task.DeviceMgtTaskException;
import io.entgra.device.mgt.core.tenant.mgt.core.TenantManager; import io.entgra.device.mgt.core.tenant.mgt.core.TenantManager;
import io.entgra.device.mgt.core.tenant.mgt.common.exception.TenantMgtException; import io.entgra.device.mgt.core.tenant.mgt.common.exception.TenantMgtException;
import io.entgra.device.mgt.core.tenant.mgt.core.internal.TenantMgtDataHolder; import io.entgra.device.mgt.core.tenant.mgt.core.internal.TenantMgtDataHolder;
@ -122,6 +128,20 @@ public class TenantManagerImpl implements TenantManager {
} }
} }
@Override
public void addDefaultDeviceTaskConfiguration(TenantInfoBean tenantInfoBean) throws TenantMgtException {
initTenantFlow(tenantInfoBean);
try {
TenantMgtDataHolder.getInstance().getDeviceTaskConfigurationService().addDefaultTaskFrequency(tenantInfoBean.getTenantId());
} catch (MetadataManagementException e) {
String msg = "Error occurred while adding default TaskFrequencies";
log.error(msg, e);
throw new TenantMgtException(msg, e);
} finally {
endTenantFlow();
}
}
@Override @Override
public void deleteTenantApplicationData(int tenantId) throws TenantMgtException { public void deleteTenantApplicationData(int tenantId) throws TenantMgtException {
try { try {
@ -216,6 +236,31 @@ public class TenantManagerImpl implements TenantManager {
} }
@Override
public void addDeviceDetailsRetrieverTask(TenantInfoBean tenantInfoBean) throws TenantMgtException{
initTenantFlow(tenantInfoBean);
try {
DeviceManagementProviderService dms = TenantMgtDataHolder.getInstance().getDeviceManagementProvider();
List<DeviceType> deviceTypes = dms.getDeviceTypes();
DeviceTaskManagerWrapper deviceTaskManagerWrapper = new DeviceTaskManagerWrapper();
for (DeviceType deviceType : deviceTypes) {
deviceTaskManagerWrapper.setDeviceType(deviceType.getName());
deviceTaskManagerWrapper.setOperationMonitoringTaskConfig(dms.getDeviceMonitoringConfig(deviceType.getName()));
TenantMgtDataHolder.getInstance().getDeviceTaskManagerService().startTask(deviceTaskManagerWrapper);
}
} catch (DeviceMgtTaskException e) {
String msg = "Error occurred while adding default TaskFrequencies";
log.error(msg, e);
throw new TenantMgtException(msg, e);
} catch (DeviceManagementException e) {
String msg = "Error occurred while getting DeviceManagementService";
log.error(msg, e);
throw new TenantMgtException(msg, e);
} finally {
endTenantFlow();
}
}
private void initTenantFlow(TenantInfoBean tenantInfoBean) { private void initTenantFlow(TenantInfoBean tenantInfoBean) {
PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext privilegedCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); PrivilegedCarbonContext privilegedCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();

@ -39,6 +39,11 @@ public class TenantManagerServiceImpl implements TenantManagerService {
TenantMgtDataHolder.getInstance().getTenantManager().addDefaultDeviceStatusFilters(tenantInfoBean); TenantMgtDataHolder.getInstance().getTenantManager().addDefaultDeviceStatusFilters(tenantInfoBean);
} }
@Override
public void addDefaultDeviceTaskConfiguration(TenantInfoBean tenantInfoBean) throws TenantMgtException {
TenantMgtDataHolder.getInstance().getTenantManager().addDefaultDeviceTaskConfiguration(tenantInfoBean);
}
@Override @Override
public void deleteTenantApplicationData(int tenantId) throws TenantMgtException { public void deleteTenantApplicationData(int tenantId) throws TenantMgtException {
TenantMgtDataHolder.getInstance().getTenantManager().deleteTenantApplicationData(tenantId); TenantMgtDataHolder.getInstance().getTenantManager().deleteTenantApplicationData(tenantId);
@ -48,4 +53,9 @@ public class TenantManagerServiceImpl implements TenantManagerService {
public void deleteTenantDeviceData(int tenantId) throws TenantMgtException { public void deleteTenantDeviceData(int tenantId) throws TenantMgtException {
TenantMgtDataHolder.getInstance().getTenantManager().deleteTenantDeviceData(tenantId); TenantMgtDataHolder.getInstance().getTenantManager().deleteTenantDeviceData(tenantId);
} }
@Override
public void addDeviceDetailsRetrieverTask(TenantInfoBean tenantInfoBean) throws TenantMgtException {
TenantMgtDataHolder.getInstance().getTenantManager().addDeviceDetailsRetrieverTask(tenantInfoBean);
}
} }

@ -19,6 +19,10 @@ package io.entgra.device.mgt.core.tenant.mgt.core.internal;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager; import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceTaskConfigurationService;
import io.entgra.device.mgt.core.device.mgt.common.spi.DeviceManagementService;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import io.entgra.device.mgt.core.device.mgt.core.task.DeviceTaskManagerService;
import io.entgra.device.mgt.core.tenant.mgt.core.TenantManager; import io.entgra.device.mgt.core.tenant.mgt.core.TenantManager;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.WhiteLabelManagementService; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.WhiteLabelManagementService;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
@ -34,6 +38,13 @@ public class TenantMgtDataHolder {
private RealmService realmService; private RealmService realmService;
private DeviceStatusManagementService deviceStatusManagementService; private DeviceStatusManagementService deviceStatusManagementService;
private DeviceTaskConfigurationService deviceTaskConfigurationService;
private DeviceTaskManagerService deviceTaskManagerService;
private DeviceManagementService deviceManagementService;
private DeviceManagementProviderService deviceManagerProvider;
public RealmService getRealmService() { public RealmService getRealmService() {
return realmService; return realmService;
@ -43,6 +54,30 @@ public class TenantMgtDataHolder {
this.realmService = realmService; this.realmService = realmService;
} }
public DeviceTaskManagerService getDeviceTaskManagerService() {
return deviceTaskManagerService;
}
public void setDeviceTaskManagerService(DeviceTaskManagerService deviceTaskManagerService) {
this.deviceTaskManagerService = deviceTaskManagerService;
}
public DeviceManagementService getDeviceManagementService() {
return deviceManagementService;
}
public void setDeviceManagementService(DeviceManagementService deviceManagementService) {
this.deviceManagementService = deviceManagementService;
}
public DeviceManagementProviderService getDeviceManagementProvider() {
return deviceManagerProvider;
}
public void setDeviceManagementProvider(DeviceManagementProviderService deviceManagerProvider) {
this.deviceManagerProvider = deviceManagerProvider;
}
public ApplicationManager getApplicationManager() { public ApplicationManager getApplicationManager() {
return applicationManager; return applicationManager;
} }
@ -78,4 +113,12 @@ public class TenantMgtDataHolder {
public void setDeviceStatusManagementService(DeviceStatusManagementService deviceStatusManagementService) { public void setDeviceStatusManagementService(DeviceStatusManagementService deviceStatusManagementService) {
this.deviceStatusManagementService = deviceStatusManagementService; this.deviceStatusManagementService = deviceStatusManagementService;
} }
public DeviceTaskConfigurationService getDeviceTaskConfigurationService() {
return deviceTaskConfigurationService;
}
public void setDeviceTaskConfigurationService(DeviceTaskConfigurationService deviceTaskConfigurationService) {
this.deviceTaskConfigurationService = deviceTaskConfigurationService;
}
} }

@ -20,6 +20,13 @@ package io.entgra.device.mgt.core.tenant.mgt.core.internal;
import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager; import io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.WhiteLabelManagementService; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.WhiteLabelManagementService;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceStatusManagementService;
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.DeviceTaskConfigurationService;
import io.entgra.device.mgt.core.device.mgt.core.internal.DeviceManagementDataHolder;
import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.DeviceStatusManagementServiceImpl;
import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.DeviceTaskConfigurationServiceImpl;
import io.entgra.device.mgt.core.device.mgt.core.metadata.mgt.WhiteLabelManagementServiceImpl;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import io.entgra.device.mgt.core.device.mgt.core.task.DeviceTaskManagerService;
import io.entgra.device.mgt.core.tenant.mgt.common.spi.TenantManagerAdminService; import io.entgra.device.mgt.core.tenant.mgt.common.spi.TenantManagerAdminService;
import io.entgra.device.mgt.core.tenant.mgt.common.spi.TenantManagerService; import io.entgra.device.mgt.core.tenant.mgt.common.spi.TenantManagerService;
import io.entgra.device.mgt.core.tenant.mgt.core.TenantManager; import io.entgra.device.mgt.core.tenant.mgt.core.TenantManager;
@ -34,6 +41,34 @@ import org.osgi.service.component.annotations.*;
import org.wso2.carbon.stratos.common.listeners.TenantMgtListener; import org.wso2.carbon.stratos.common.listeners.TenantMgtListener;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
/**
* @scr.component name="io.entgra.device.mgt.core.tenant.manager" immediate="true"
* @scr.reference name="org.wso2.carbon.application.mgt.service"
* interface="io.entgra.device.mgt.core.application.mgt.common.services.ApplicationManager"
* cardinality="1..1"
* policy="dynamic"
* bind="setApplicationManager"
* unbind="unsetApplicationManager"
* @scr.reference name="user.realmservice.default"
* interface="org.wso2.carbon.user.core.service.RealmService"
* cardinality="1..1"
* policy="dynamic"
* bind="setRealmService"
* unbind="unsetRealmService"
* @scr.reference name="org.wso2.carbon.device.manager"
* interface="io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService"
* cardinality="1..1"
* policy="dynamic"
* bind="setDeviceManagementProviderService"
* unbind="unsetDeviceManagementProviderService"
* @scr.reference name="org.wso2.carbon.device.task.manager"
* interface="io.entgra.device.mgt.core.device.mgt.core.task.DeviceTaskManagerService"
* cardinality="1..1"
* policy="dynamic"
* bind="setDeviceTaskManagerService"
* unbind="unsetDeviceTaskManagerService"
*/
@Component( @Component(
name = "io.entgra.device.mgt.core.tenant.mgt.core.internal.TenantMgtServiceComponent", name = "io.entgra.device.mgt.core.tenant.mgt.core.internal.TenantMgtServiceComponent",
immediate = true) immediate = true)
@ -54,6 +89,16 @@ public class TenantMgtServiceComponent {
registerService(TenantManagerAdminService.class.getName(), tenantManagerAdminService, null); registerService(TenantManagerAdminService.class.getName(), tenantManagerAdminService, null);
TenantManager tenantManager = new TenantManagerImpl(); TenantManager tenantManager = new TenantManagerImpl();
TenantMgtDataHolder.getInstance().setTenantManager(tenantManager); TenantMgtDataHolder.getInstance().setTenantManager(tenantManager);
WhiteLabelManagementService whiteLabelManagementService = new WhiteLabelManagementServiceImpl();
componentContext.getBundleContext().registerService(WhiteLabelManagementServiceImpl.class.getName(),
whiteLabelManagementService, null);
TenantMgtDataHolder.getInstance().setWhiteLabelManagementService(whiteLabelManagementService);
DeviceStatusManagementService deviceStatusManagementService = new DeviceStatusManagementServiceImpl();
componentContext.getBundleContext().registerService(DeviceStatusManagementService.class.getName(),
deviceStatusManagementService, null);
TenantMgtDataHolder.getInstance().setDeviceStatusManagementService(deviceStatusManagementService);
DeviceTaskConfigurationService deviceTaskConfigurationService = DeviceTaskConfigurationServiceImpl.getInstance();
TenantMgtDataHolder.getInstance().setDeviceTaskConfigurationService(deviceTaskConfigurationService);
DeviceMgtTenantListener deviceMgtTenantListener = new DeviceMgtTenantListener(); DeviceMgtTenantListener deviceMgtTenantListener = new DeviceMgtTenantListener();
if(log.isDebugEnabled()) { if(log.isDebugEnabled()) {
log.info("Tenant management listener is registering"); log.info("Tenant management listener is registering");
@ -154,4 +199,28 @@ public class TenantMgtServiceComponent {
} }
TenantMgtDataHolder.getInstance().setRealmService(null); TenantMgtDataHolder.getInstance().setRealmService(null);
} }
protected void setDeviceTaskManagerService(DeviceTaskManagerService deviceTaskManagerService) {
if (log.isDebugEnabled()) {
}
TenantMgtDataHolder.getInstance().setDeviceTaskManagerService(deviceTaskManagerService);
}
protected void unsetDeviceTaskManagerService(DeviceTaskManagerService deviceTaskManagerService) {
if (log.isDebugEnabled()) {
}
TenantMgtDataHolder.getInstance().setDeviceTaskManagerService(null);
}
protected void setDeviceManagementProviderService(DeviceManagementProviderService deviceManagementProviderService) {
if (log.isDebugEnabled()) {
}
TenantMgtDataHolder.getInstance().setDeviceManagementProvider(deviceManagementProviderService);
}
protected void unsetDeviceManagementProviderService(DeviceManagementProviderService deviceManagementProviderService) {
if (log.isDebugEnabled()) {
}
TenantMgtDataHolder.getInstance().setDeviceTaskManagerService(null);
}
} }

@ -39,6 +39,8 @@ public class DeviceMgtTenantListener implements TenantMgtListener {
tenantManager.addDefaultRoles(tenantInfoBean); tenantManager.addDefaultRoles(tenantInfoBean);
tenantManager.addDefaultAppCategories(tenantInfoBean); tenantManager.addDefaultAppCategories(tenantInfoBean);
tenantManager.addDefaultDeviceStatusFilters(tenantInfoBean); tenantManager.addDefaultDeviceStatusFilters(tenantInfoBean);
tenantManager.addDefaultDeviceTaskConfiguration(tenantInfoBean);
tenantManager.addDeviceDetailsRetrieverTask(tenantInfoBean);
} catch (TenantMgtException e) { } catch (TenantMgtException e) {
String msg = "Error occurred while executing tenant creation flow"; String msg = "Error occurred while executing tenant creation flow";
log.error(msg, e); log.error(msg, e);

Loading…
Cancel
Save