This is an automated email from the ASF dual-hosted git repository.
wiener pushed a commit to branch edge-extensions
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
The following commit(s) were added to refs/heads/edge-extensions by this push:
new 1754994 some minor refactoring work on auto-offloading
1754994 is described below
commit 1754994e1c9b75f6795d7540301dbd0eea70b0d0
Author: Patrick Wiener <[email protected]>
AuthorDate: Sat Apr 17 01:30:25 2021 +0200
some minor refactoring work on auto-offloading
---
.../model/message/NotificationType.java | 7 +-
.../offloading/AutoOffloadingManager.java | 42 +++++
.../management/offloading/policies/Comparator.java | 23 +++
.../MultiOccurrenceThresholdViolationPolicy.java} | 40 +++--
.../offloading/policies/OffloadingPolicy.java | 24 +++
.../SingleOccurrenceThresholdViolationPolicy.java | 24 +++
.../management/pe/InvocableElementManager.java | 11 +-
.../management/rebalance/MigrationManager.java | 26 ---
.../management/rebalance/triggers/Comparator.java | 6 -
.../rebalance/triggers/ThresholdTriggerPolicy.java | 7 -
.../rebalance/triggers/TriggerPolicy.java | 7 -
.../management/resource/ResourceManager.java | 190 ++++++---------------
.../management/resource/utils/DiskSpace.java | 33 ++++
.../management/resource/utils/FileSystemType.java | 36 ++++
.../management/resource/utils/ResourceUtils.java | 97 +++++++++++
.../migration/MigrationPipelineGenerator.java | 17 ++
.../manager/node/StreamPipesClusterManager.java | 34 ++++
.../org/apache/streampipes/rest/impl/Node.java | 18 +-
.../node-configuration-details.component.ts | 4 -
19 files changed, 420 insertions(+), 226 deletions(-)
diff --git
a/streampipes-model/src/main/java/org/apache/streampipes/model/message/NotificationType.java
b/streampipes-model/src/main/java/org/apache/streampipes/model/message/NotificationType.java
index d7bf388..270d77d 100644
---
a/streampipes-model/src/main/java/org/apache/streampipes/model/message/NotificationType.java
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/message/NotificationType.java
@@ -71,10 +71,13 @@ public enum NotificationType {
ADMIN_USER_CREATED("Creating admin user...", ""),
NODE_JOIN_SUCCESS("Success", "Node successfully joined"),
- NODE_JOIN_ERROR("Error", "Node could not be joined");
+ NODE_JOIN_ERROR("Error", "Node could not be joined"),
+ OFFLOADING_SUCCESS("Offloading successful", "Pipeline element
successfully offloaded"),
+ OFFLOADING_ERROR("Offloading error", "Could not offload pipeline
element");
- private final String title;
+
+ private final String title;
private final String description;
NotificationType(String title, String description) {
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/AutoOffloadingManager.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/AutoOffloadingManager.java
new file mode 100644
index 0000000..bc30ea2
--- /dev/null
+++
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/AutoOffloadingManager.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.node.controller.management.offloading;
+
+import org.apache.streampipes.model.base.InvocableStreamPipesEntity;
+import
org.apache.streampipes.node.controller.management.pe.InvocableElementManager;
+import
org.apache.streampipes.node.controller.management.pe.storage.RunningInvocableInstances;
+
+import java.util.List;
+import java.util.Random;
+
+public class AutoOffloadingManager {
+
+ public static boolean offloadRandom(){
+ List<InvocableStreamPipesEntity> instances =
RunningInvocableInstances.INSTANCE.getAll();
+ if(instances.size() == 0)
+ return false;
+ InvocableStreamPipesEntity randomlySelectedInstance =
instances.get(new Random().nextInt(instances.size()));
+
InvocableElementManager.getInstance().postOffloadRequest(randomlySelectedInstance);
+ return true;
+ }
+
+ public static void offloadHeaviest(){
+ //TODO: Migrate the PE with the highest load on CPU (or possibly other
resource)
+ }
+
+}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/Comparator.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/Comparator.java
new file mode 100644
index 0000000..eb2a898
--- /dev/null
+++
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/Comparator.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.node.controller.management.offloading.policies;
+
+public enum Comparator {
+ SMALLER,
+ GREATER
+}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/TrendTriggerPolicy.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/MultiOccurrenceThresholdViolationPolicy.java
similarity index 54%
rename from
streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/TrendTriggerPolicy.java
rename to
streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/MultiOccurrenceThresholdViolationPolicy.java
index b5329eb..2e225a4 100644
---
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/TrendTriggerPolicy.java
+++
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/MultiOccurrenceThresholdViolationPolicy.java
@@ -1,4 +1,21 @@
-package org.apache.streampipes.node.controller.management.rebalance.triggers;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.node.controller.management.offloading.policies;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -6,23 +23,24 @@ import org.slf4j.LoggerFactory;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
-public class TrendTriggerPolicy<T extends Number> implements TriggerPolicy<T>{
+public class MultiOccurrenceThresholdViolationPolicy<T extends Number>
implements OffloadingPolicy<T> {
+ private static final Logger LOG =
+
LoggerFactory.getLogger(MultiOccurrenceThresholdViolationPolicy.class.getCanonicalName());
private Queue<T> history;
- private T threshold;
- private Comparator comparator;
- private int numberOfThresholdViolations;
- private static final Logger LOG =
-
LoggerFactory.getLogger(TrendTriggerPolicy.class.getCanonicalName());
+ private final T threshold;
+ private final Comparator comparator;
+ private final int numberOfThresholdViolations;
- public TrendTriggerPolicy(int length, Comparator comparator,T threshold,
int numberOfThresholdViolations){
+ public MultiOccurrenceThresholdViolationPolicy(int length, Comparator
comparator, T threshold,
+ int
numberOfThresholdViolations){
this.history = new ArrayBlockingQueue<>(length);
this.comparator = comparator;
this.threshold = threshold;
this.numberOfThresholdViolations = numberOfThresholdViolations;
}
- public TrendTriggerPolicy(int length, Comparator comparator, T threshold){
+ public MultiOccurrenceThresholdViolationPolicy(int length, Comparator
comparator, T threshold){
this(length, comparator, threshold, length);
}
@@ -35,7 +53,7 @@ public class TrendTriggerPolicy<T extends Number> implements
TriggerPolicy<T>{
}
@Override
- public boolean isTriggered() {
+ public boolean isViolated() {
int numViolations = 0;
switch (this.comparator){
case GREATER:
@@ -56,7 +74,7 @@ public class TrendTriggerPolicy<T extends Number> implements
TriggerPolicy<T>{
break;
}
if(numViolations >= this.numberOfThresholdViolations){
- LOG.info("Trend above threshold detected.");
+ LOG.info("Threshold violation detected");
return true;
}
return false;
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/OffloadingPolicy.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/OffloadingPolicy.java
new file mode 100644
index 0000000..1f0c802
--- /dev/null
+++
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/OffloadingPolicy.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.node.controller.management.offloading.policies;
+
+public interface OffloadingPolicy<T> {
+ void addValue(T value);
+ boolean isViolated();
+ void reset();
+}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/SingleOccurrenceThresholdViolationPolicy.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/SingleOccurrenceThresholdViolationPolicy.java
new file mode 100644
index 0000000..f7f514b
--- /dev/null
+++
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/offloading/policies/SingleOccurrenceThresholdViolationPolicy.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.node.controller.management.offloading.policies;
+
+public class SingleOccurrenceThresholdViolationPolicy<T extends Number>
extends MultiOccurrenceThresholdViolationPolicy<T> {
+ public SingleOccurrenceThresholdViolationPolicy(Comparator comparator, T
threshold) {
+ super(1, comparator, threshold, 1);
+ }
+}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/pe/InvocableElementManager.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/pe/InvocableElementManager.java
index 76f406b..11d69c2 100644
---
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/pe/InvocableElementManager.java
+++
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/pe/InvocableElementManager.java
@@ -38,7 +38,6 @@ import
org.apache.streampipes.model.staticproperty.StaticProperty;
import org.apache.streampipes.node.controller.config.NodeControllerConfig;
import org.apache.streampipes.node.controller.management.node.NodeManager;
import
org.apache.streampipes.node.controller.management.pe.storage.RunningInvocableInstances;
-import
org.apache.streampipes.node.controller.management.resource.model.ResourceMetrics;
import org.apache.streampipes.serializers.json.JacksonSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -164,10 +163,10 @@ public class InvocableElementManager implements
IPipelineElementLifeCycle {
return response;
}
- public void postMigrationRequest(InvocableStreamPipesEntity
instanceToMigrate){
+ public void postOffloadRequest(InvocableStreamPipesEntity
instanceToOffload){
try {
- String url = generateBackendMigrationEndpoint();
- String desc = toJson(instanceToMigrate);
+ String url = generateBackendOffloadEndpoint();
+ String desc = toJson(instanceToOffload);
org.apache.http.client.fluent.Response resp = Request.Post(url)
.bodyString(desc, ContentType.APPLICATION_JSON)
.execute();
@@ -306,13 +305,13 @@ public class InvocableElementManager implements
IPipelineElementLifeCycle {
+ NodeControllerConfig.INSTANCE.getNodeControllerId();
}
- private String generateBackendMigrationEndpoint() {
+ private String generateBackendOffloadEndpoint() {
return HTTP_PROTOCOL
+ NodeControllerConfig.INSTANCE.backendLocation()
+ COLON
+ NodeControllerConfig.INSTANCE.backendPort()
+ SLASH
- +
"streampipes-backend/api/v2/users/[email protected]/nodes/rebalance";
+ +
"streampipes-backend/api/v2/users/[email protected]/nodes/offload";
}
private void registerAtConsul(InvocableRegistration registration) {
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/MigrationManager.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/MigrationManager.java
deleted file mode 100644
index 28c98a6..0000000
---
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/MigrationManager.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.apache.streampipes.node.controller.management.rebalance;
-
-import org.apache.http.client.fluent.Request;
-import org.apache.streampipes.model.base.InvocableStreamPipesEntity;
-import
org.apache.streampipes.node.controller.management.pe.InvocableElementManager;
-import
org.apache.streampipes.node.controller.management.pe.storage.RunningInvocableInstances;
-
-import java.util.List;
-import java.util.Random;
-
-public class MigrationManager {
-
- public static boolean migrateRandomPE(){
- List<InvocableStreamPipesEntity> instances =
RunningInvocableInstances.INSTANCE.getAll();
- if(instances.size() == 0)
- return false;
- InvocableStreamPipesEntity randomlySelectedInstance =
instances.get(new Random().nextInt(instances.size()));
-
InvocableElementManager.getInstance().postMigrationRequest(randomlySelectedInstance);
- return true;
- }
-
- public static void migrateHeaviestPE(){
- //TODO: Migrate the PE with the highest load on CPU (or possibly other
resource)
- }
-
-}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/Comparator.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/Comparator.java
deleted file mode 100644
index efceb8f..0000000
---
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/Comparator.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.apache.streampipes.node.controller.management.rebalance.triggers;
-
-public enum Comparator {
- SMALLER,
- GREATER
-}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/ThresholdTriggerPolicy.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/ThresholdTriggerPolicy.java
deleted file mode 100644
index e1a349c..0000000
---
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/ThresholdTriggerPolicy.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.apache.streampipes.node.controller.management.rebalance.triggers;
-
-public class ThresholdTriggerPolicy<T extends Number> extends
TrendTriggerPolicy<T>{
- public ThresholdTriggerPolicy(Comparator comparator, T threshold) {
- super(1, comparator, threshold, 1);
- }
-}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/TriggerPolicy.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/TriggerPolicy.java
deleted file mode 100644
index 61103ea..0000000
---
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/rebalance/triggers/TriggerPolicy.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.apache.streampipes.node.controller.management.rebalance.triggers;
-
-public interface TriggerPolicy<T> {
- void addValue(T value);
- boolean isTriggered();
- void reset();
-}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/ResourceManager.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/ResourceManager.java
index edc2b97..eab7d60 100644
---
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/ResourceManager.java
+++
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/ResourceManager.java
@@ -18,42 +18,39 @@
package org.apache.streampipes.node.controller.management.resource;
import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
import org.apache.streampipes.node.controller.config.NodeControllerConfig;
-import
org.apache.streampipes.node.controller.management.pe.InvocableElementManager;
-import
org.apache.streampipes.node.controller.management.rebalance.MigrationManager;
-import
org.apache.streampipes.node.controller.management.rebalance.triggers.Comparator;
-import
org.apache.streampipes.node.controller.management.rebalance.triggers.TrendTriggerPolicy;
-import
org.apache.streampipes.node.controller.management.rebalance.triggers.TriggerPolicy;
+import
org.apache.streampipes.node.controller.management.offloading.AutoOffloadingManager;
+import
org.apache.streampipes.node.controller.management.offloading.policies.Comparator;
+import
org.apache.streampipes.node.controller.management.offloading.policies.MultiOccurrenceThresholdViolationPolicy;
+import
org.apache.streampipes.node.controller.management.offloading.policies.OffloadingPolicy;
import
org.apache.streampipes.node.controller.management.resource.model.ResourceMetrics;
+import
org.apache.streampipes.node.controller.management.resource.utils.DiskSpace;
+import
org.apache.streampipes.node.controller.management.resource.utils.ResourceUtils;
import org.apache.streampipes.serializers.json.JacksonSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import oshi.SystemInfo;
import oshi.hardware.*;
import oshi.software.os.*;
-import oshi.util.FormatUtil;
-import oshi.util.Util;
-
-import oshi.hardware.CentralProcessor;
import java.text.SimpleDateFormat;
-import java.time.Instant;
import java.util.*;
public class ResourceManager {
- private static final Logger LOG =
- LoggerFactory.getLogger(ResourceManager.class.getCanonicalName());
+ private static final Logger LOG =
LoggerFactory.getLogger(ResourceManager.class.getCanonicalName());
+ private static ResourceManager instance = null;
// OSHI to retrieve system information
private final SystemInfo si = new SystemInfo();
private final HardwareAbstractionLayer hal = si.getHardware();
private final OperatingSystem os = si.getOperatingSystem();
private final Calendar cal = Calendar.getInstance();
-
private final ResourceMetrics resourceMetrics = new ResourceMetrics();
-
- private static ResourceManager instance = null;
+ // Offloading policy
+ private final OffloadingPolicy<Float> multiStepThresholdPolicy = new
MultiOccurrenceThresholdViolationPolicy<>(5,
+ Comparator.GREATER,99f, 5);
private ResourceManager() {}
@@ -72,50 +69,52 @@ public class ResourceManager {
}
private final Runnable getCurrentResources = () -> {
-
- TriggerPolicy<Float> tp = new TrendTriggerPolicy<>(5,
Comparator.GREATER, 99f, 5);
-
while(true) {
try {
// get current node resource metrics
Thread.sleep(
NodeControllerConfig.INSTANCE.getNodeResourceUpdateFreqSecs() * 1000);
-
- cal.setTimeInMillis(System.currentTimeMillis());
- SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy
hh:mm:ss a");
-
- /**
- * Monitors the node resources
- */
- Map<String, Map<String, Long>> diskUsage =
getDiskUsage(this.os.getFileSystem());
-
-
resourceMetrics.setSystemTime(dateFormat.format(cal.getTime()));
- resourceMetrics.setBooted(getBooted(this.os));
- resourceMetrics.setUptime(getUptime(this.os));
- resourceMetrics.setCpuLoad(String.format("%.1f%%",
getCpuLoad(this.hal.getProcessor())));
-
resourceMetrics.setCpuLoadInPercent(getCpuLoad(this.hal.getProcessor()));
- resourceMetrics.setCpuTemperature(String.format("%.2f°C",
getCpuTemperature(this.hal.getSensors())));
-
resourceMetrics.setCpuTemperatureCelcius(getCpuTemperature(this.hal.getSensors()));
-
resourceMetrics.setFreeMemoryInBytes(getAvailableMemory(this.hal.getMemory()));
-
resourceMetrics.setUsedMemoryInBytes(this.hal.getMemory().getTotal() -
getAvailableMemory(this.hal.getMemory()));
-
resourceMetrics.setTotalMemoryInBytes(this.hal.getMemory().getTotal());
-
- for (Map.Entry<String, Map<String, Long>> k :
diskUsage.entrySet()) {
-
resourceMetrics.setFreeDiskSpaceInBytes(k.getValue().get("usableDiskSpace"));
- }
-
- tp.addValue(resourceMetrics.getCpuLoadInPercent());
- if(tp.isTriggered()){
- LOG.info("Auto migration triggered.");
- if(MigrationManager.migrateRandomPE())
- tp.reset();
- }
-
+ retrieveResources();
+ checkOffloadingPolicy();
} catch (InterruptedException e) {
LOG.error("Thread interrupted. {}", e.toString());
}
}
};
+ private void checkOffloadingPolicy() {
+
multiStepThresholdPolicy.addValue(resourceMetrics.getCpuLoadInPercent());
+ if(multiStepThresholdPolicy.isViolated()){
+ LOG.info("Policy violated. Offloading procedure triggered");
+ if(AutoOffloadingManager.offloadRandom())
+ multiStepThresholdPolicy.reset();
+ else {
+ LOG.info("Offloading procedure aborted - No pipeline element
seems to be running");
+ }
+ }
+ }
+
+ private void retrieveResources() {
+ cal.setTimeInMillis(System.currentTimeMillis());
+ SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy
hh:mm:ss a");
+
+ // Monitor node resources
+ resourceMetrics.setSystemTime(dateFormat.format(cal.getTime()));
+ resourceMetrics.setBooted(ResourceUtils.getBooted(this.os));
+ resourceMetrics.setUptime(ResourceUtils.getUptime(this.os));
+ resourceMetrics.setCpuLoad(String.format("%.1f%%",
ResourceUtils.getCpuLoad(this.hal.getProcessor())));
+
resourceMetrics.setCpuLoadInPercent(ResourceUtils.getCpuLoad(this.hal.getProcessor()));
+ resourceMetrics.setCpuTemperature(String.format("%.2f°C",
+ ResourceUtils.getCpuTemperature(this.hal.getSensors())));
+
resourceMetrics.setCpuTemperatureCelcius(ResourceUtils.getCpuTemperature(this.hal.getSensors()));
+
resourceMetrics.setFreeMemoryInBytes(ResourceUtils.getAvailableMemory(this.hal.getMemory()));
+ resourceMetrics.setUsedMemoryInBytes(this.hal.getMemory().getTotal() -
ResourceUtils.getAvailableMemory(this.hal.getMemory()));
+ resourceMetrics.setTotalMemoryInBytes(this.hal.getMemory().getTotal());
+
+ ResourceUtils.getDiskUsage(this.os.getFileSystem()).forEach((key,
value) -> {
+
resourceMetrics.setFreeDiskSpaceInBytes(value.get(DiskSpace.USABLE.getName()));
+ });
+ }
+
public String retrieveNodeResources() {
try {
return JacksonSerializer
@@ -123,98 +122,7 @@ public class ResourceManager {
.writerWithDefaultPrettyPrinter()
.writeValueAsString(resourceMetrics);
} catch (JsonProcessingException e) {
- LOG.error("Could not serialize node resources", e);
+ throw new SpRuntimeException("Could not serialize node resources "
+ e.getMessage(), e);
}
- return "{}";
- }
-
- private double getCpuTemperature(Sensors s) {
- return s.getCpuTemperature();
- }
-
- private Map<String, Map<String,Long>> getDiskUsage(FileSystem fs) {
- List<OSFileStore> fsArray = fs.getFileStores();
- Map<String, Map<String, Long>> m = new HashMap<>();
- for(OSFileStore f : fsArray) {
- Map<String, Long> i = new HashMap<>();
- // has SATA disk
- if (f.getVolume().contains("/dev/sda")){
- i.put("usableDiskSpace", f.getUsableSpace());
- i.put("totalDiskSpace", f.getTotalSpace());
- m.put(f.getVolume(), i);
- }
- else if (f.getVolume().contains("/dev/nvme")){
- i.put("usableDiskSpace", f.getUsableSpace());
- i.put("totalDiskSpace", f.getTotalSpace());
- m.put(f.getVolume(), i);
- }
- else if (f.getVolume().contains("/dev/disk")){
- i.put("usableDiskSpace", f.getUsableSpace());
- i.put("totalDiskSpace", f.getTotalSpace());
- m.put(f.getVolume(), i);
- }
- // Docker in RPi
- else if (f.getVolume().contains("/dev/root")){
- i.put("usableDiskSpace", f.getUsableSpace());
- i.put("totalDiskSpace", f.getTotalSpace());
- m.put(f.getVolume(), i);
- }
- // Docker in Jetson Nano
- else if (f.getVolume().contains("/dev/mmcblk0p1")){
- i.put("usableDiskSpace", f.getUsableSpace());
- i.put("totalDiskSpace", f.getTotalSpace());
- m.put(f.getVolume(), i);
- }
-// // has SATA disk
-// if (f.getVolume().contains("/dev/sda") && (
f.getMount().equals("/") || f.getMount().equals("/home"))){
-// i.put("usableDiskSpace", f.getUsableSpace());
-// i.put("totalDiskSpace", f.getTotalSpace());
-// m.put(f.getVolume(), i);
-// }
-// // has overlay disk (container setup)
-// else if (f.getVolume().equals("overlay") && (
f.getMount().equals("/") || f.getMount().equals("/home"))){
-// i.put("usableDiskSpace", f.getUsableSpace());
-// i.put("totalDiskSpace", f.getTotalSpace());
-// m.put(f.getVolume(), i);
-// }
-// // has NVME disk
-// else if(f.getVolume().contains("/dev/nvme") && (
f.getMount().equals("/") || f.getMount().equals("/home"))) {
-// i.put("usableDiskSpace", f.getUsableSpace());
-// i.put("totalDiskSpace", f.getTotalSpace());
-// m.put(f.getVolume(), i);
-// }
-// // disk on macOS
-// else if (f.getVolume().contains("/dev/disk") &&
f.getMount().equals("/")) {
-// i.put("usableDiskSpace", f.getUsableSpace());
-// i.put("totalDiskSpace", f.getTotalSpace());
-// m.put(f.getVolume(), i);
-// }
- }
- if (m.isEmpty()) {
- Map<String, Long> i = new HashMap<>();
- i.put("usableDiskSpace", 0L);
- i.put("totalDiskSpace", 0L);
- m.put("n/a", i);
- }
- return m;
- }
-
- private long getAvailableMemory(GlobalMemory m) {
- return m.getAvailable();
- }
-
- private float getCpuLoad(CentralProcessor c) {
- long[] prevTicks = c.getSystemCpuLoadTicks();
- // need to wait a second
- Util.sleep(1000);
- return (float) (c.getSystemCpuLoadBetweenTicks(prevTicks) * 100);
- }
-
- private String getUptime(OperatingSystem os) {
- return
String.valueOf(FormatUtil.formatElapsedSecs(os.getSystemUptime()));
- }
-
- private String getBooted(OperatingSystem os) {
- return String.valueOf(Instant.ofEpochSecond(os.getSystemBootTime()));
}
}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/utils/DiskSpace.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/utils/DiskSpace.java
new file mode 100644
index 0000000..326be6e
--- /dev/null
+++
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/utils/DiskSpace.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.node.controller.management.resource.utils;
+
+public enum DiskSpace {
+ USABLE("usableDiskSpace"),
+ TOTAL("totalDiskSpace");
+
+ private final String name;
+
+ DiskSpace(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/utils/FileSystemType.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/utils/FileSystemType.java
new file mode 100644
index 0000000..44984db
--- /dev/null
+++
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/utils/FileSystemType.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.node.controller.management.resource.utils;
+
+public enum FileSystemType {
+ SDA("/dev/sda"),
+ NVME("/dev/nvme"),
+ DISK("/dev/disk"),
+ ROOT("/dev/root"),
+ MMCBLK("/dev/mmcblk0p1");
+
+ private final String name;
+
+ FileSystemType(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git
a/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/utils/ResourceUtils.java
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/utils/ResourceUtils.java
new file mode 100644
index 0000000..603994f
--- /dev/null
+++
b/streampipes-node-controller/src/main/java/org/apache/streampipes/node/controller/management/resource/utils/ResourceUtils.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.node.controller.management.resource.utils;
+
+import oshi.hardware.CentralProcessor;
+import oshi.hardware.GlobalMemory;
+import oshi.hardware.Sensors;
+import oshi.software.os.FileSystem;
+import oshi.software.os.OSFileStore;
+import oshi.software.os.OperatingSystem;
+import oshi.util.FormatUtil;
+import oshi.util.Util;
+
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ResourceUtils {
+
+ public static double getCpuTemperature(Sensors s) {
+ return s.getCpuTemperature();
+ }
+
+ public static Map<String, Map<String,Long>> getDiskUsage(FileSystem fs) {
+ List<OSFileStore> fsArray = fs.getFileStores();
+ Map<String, Map<String, Long>> diskUsage = new HashMap<>();
+ for(OSFileStore f : fsArray) {
+ String volume = f.getVolume();
+ // has SATA disk
+ if (volume.contains(FileSystemType.SDA.getName())){
+ addDiskUsage(diskUsage, f);
+ } else if (volume.contains(FileSystemType.NVME.getName())){
+ addDiskUsage(diskUsage, f);
+ } else if (volume.contains(FileSystemType.DISK.getName())){
+ addDiskUsage(diskUsage, f);
+ } else if (volume.contains(FileSystemType.ROOT.getName())){
+ // Docker in RPi
+ addDiskUsage(diskUsage, f);
+ } else if (volume.contains(FileSystemType.MMCBLK.getName())){
+ // Docker in Jetson Nano
+ addDiskUsage(diskUsage, f);
+ }
+ }
+ return diskUsage.isEmpty() ? defaultDiskUsage() : diskUsage;
+ }
+
+ public static void addDiskUsage(Map<String, Map<String, Long>> m,
OSFileStore f) {
+ Map<String, Long> i = new HashMap<>();
+ i.put(DiskSpace.USABLE.getName(), f.getUsableSpace());
+ i.put(DiskSpace.TOTAL.getName(), f.getTotalSpace());
+ m.put(f.getVolume(), i);
+ }
+
+ public static Map<String, Map<String, Long>> defaultDiskUsage() {
+ return new HashMap<String, Map<String, Long>>() {{
+ put("n/a", new HashMap<String, Long>() {{
+ put(DiskSpace.USABLE.getName(), 0L);
+ put(DiskSpace.TOTAL.getName(), 0L);
+ }});
+ }};
+ }
+
+ public static long getAvailableMemory(GlobalMemory m) {
+ return m.getAvailable();
+ }
+
+ public static float getCpuLoad(CentralProcessor c) {
+ long[] prevTicks = c.getSystemCpuLoadTicks();
+ // need to wait a second
+ Util.sleep(1000);
+ return (float) (c.getSystemCpuLoadBetweenTicks(prevTicks) * 100);
+ }
+
+ public static String getUptime(OperatingSystem os) {
+ return
String.valueOf(FormatUtil.formatElapsedSecs(os.getSystemUptime()));
+ }
+
+ public static String getBooted(OperatingSystem os) {
+ return String.valueOf(Instant.ofEpochSecond(os.getSystemBootTime()));
+ }
+}
diff --git
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/migration/MigrationPipelineGenerator.java
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/migration/MigrationPipelineGenerator.java
index 83bff42..b8a688e 100644
---
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/migration/MigrationPipelineGenerator.java
+++
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/migration/MigrationPipelineGenerator.java
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
package org.apache.streampipes.manager.migration;
import com.fasterxml.jackson.core.JsonProcessingException;
diff --git
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/node/StreamPipesClusterManager.java
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/node/StreamPipesClusterManager.java
index 2e49f8e..3ab464b 100644
---
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/node/StreamPipesClusterManager.java
+++
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/node/StreamPipesClusterManager.java
@@ -17,16 +17,23 @@
*/
package org.apache.streampipes.manager.node;
+import org.apache.streampipes.manager.migration.MigrationPipelineGenerator;
import
org.apache.streampipes.manager.node.management.cluster.AbstractClusterManager;
import org.apache.streampipes.manager.node.management.cluster.NodeSyncOptions;
import
org.apache.streampipes.manager.node.management.healthcheck.ClusterHealthCheck;
+import org.apache.streampipes.manager.operations.Operations;
+import org.apache.streampipes.model.Response;
+import org.apache.streampipes.model.base.InvocableStreamPipesEntity;
import org.apache.streampipes.model.eventrelay.SpDataStreamRelayContainer;
import org.apache.streampipes.model.message.Message;
import org.apache.streampipes.model.message.NotificationType;
import org.apache.streampipes.model.message.Notifications;
import org.apache.streampipes.model.node.NodeInfoDescription;
+import org.apache.streampipes.model.pipeline.Pipeline;
+import org.apache.streampipes.model.pipeline.PipelineOperationStatus;
import org.apache.streampipes.storage.api.INodeDataStreamRelay;
import org.apache.streampipes.storage.api.INodeInfoStorage;
+import org.apache.streampipes.storage.api.IPipelineStorage;
import org.apache.streampipes.storage.management.StorageDispatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -161,6 +168,29 @@ public class StreamPipesClusterManager extends
AbstractClusterManager {
getNodeDataStreamRelayStorageApi().deleteRelayContainer(relayContainer);
}
+ public static Message handleOffloadRequest(InvocableStreamPipesEntity
elementToMigrate) {
+ Pipeline currentPipeline =
getPipelineStorageApi().getPipeline(elementToMigrate.getCorrespondingPipeline());
+ Pipeline offloadPipeline =
MigrationPipelineGenerator.generateMigrationPipeline(elementToMigrate,
+ currentPipeline);
+ //TODO: Handle this case properly
+ if(offloadPipeline == null)
+ return Notifications.error(NotificationType.UNKNOWN_ERROR);
+
+ try {
+ PipelineOperationStatus status =
Operations.handlePipelineElementMigration(offloadPipeline,
+ true, true, true);
+ if (status.isSuccess()) {
+ return
Notifications.success(NotificationType.OFFLOADING_SUCCESS);
+ } else {
+ return
Notifications.success(NotificationType.OFFLOADING_ERROR);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return Notifications.error(NotificationType.UNKNOWN_ERROR);
+ }
+ }
+
// Helpers
private static INodeInfoStorage getNodeStorageApi() {
@@ -171,4 +201,8 @@ public class StreamPipesClusterManager extends
AbstractClusterManager {
return
StorageDispatcher.INSTANCE.getNoSqlStore().getNodeDataStreamRelayStorage();
}
+ private static IPipelineStorage getPipelineStorageApi() {
+ return
StorageDispatcher.INSTANCE.getNoSqlStore().getPipelineStorageAPI();
+ }
+
}
diff --git
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Node.java
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Node.java
index 2a434e1..5ccd75b 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Node.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Node.java
@@ -121,24 +121,10 @@ public class Node extends AbstractRestResource implements
INode {
@POST
- @Path("/rebalance")
+ @Path("/offload")
@Produces(MediaType.APPLICATION_JSON)
@JacksonSerialized
public Response migrateProcessorToOtherNode(InvocableStreamPipesEntity
elementToMigrate) {
- Pipeline correspondingPipeline =
getPipelineStorage().getPipeline(elementToMigrate.getCorrespondingPipeline());
- Pipeline desiredPipeline =
MigrationPipelineGenerator.generateMigrationPipeline(elementToMigrate,
- correspondingPipeline);
- //TODO: Handle this case properly
- if(desiredPipeline == null)
- return
statusMessage(Notifications.error(NotificationType.UNKNOWN_ERROR));
-
- try {
- PipelineOperationStatus status =
Operations.handlePipelineElementMigration(desiredPipeline,
- true, true, true);
- return ok(status);
- } catch (Exception e) {
- e.printStackTrace();
- return
statusMessage(Notifications.error(NotificationType.UNKNOWN_ERROR));
- }
+ return
statusMessage(StreamPipesClusterManager.handleOffloadRequest(elementToMigrate));
}
}
diff --git
a/ui/src/app/configuration/node-configuration/node-configuration-details/node-configuration-details.component.ts
b/ui/src/app/configuration/node-configuration/node-configuration-details/node-configuration-details.component.ts
index bd9d555..86560e4 100644
---
a/ui/src/app/configuration/node-configuration/node-configuration-details/node-configuration-details.component.ts
+++
b/ui/src/app/configuration/node-configuration/node-configuration-details/node-configuration-details.component.ts
@@ -28,10 +28,6 @@ import {PanelType} from
"../../../core-ui/dialog/base-dialog/base-dialog.model";
import {DialogService} from
"../../../core-ui/dialog/base-dialog/base-dialog.service";
import {MatSnackBar} from "@angular/material/snack-bar";
-export interface Fruit {
- name: string;
-}
-
@Component({
selector: 'node-configuration-details',
templateUrl: './node-configuration-details.component.html',